summaryrefslogtreecommitdiff
path: root/devdocs/gcc~13/named-address-spaces.html
blob: 59906126bf2fb97fa4440e1eca1ad95c8fcd6a6d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<div class="section-level-extent" id="Named-Address-Spaces"> <div class="nav-panel"> <p> Next: <a href="zero-length" accesskey="n" rel="next">Arrays of Length Zero</a>, Previous: <a href="fixed-point" accesskey="p" rel="prev">Fixed-Point Types</a>, Up: <a href="c-extensions" accesskey="u" rel="up">Extensions to the C Language Family</a> [<a href="index#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="indices" title="Index" rel="index">Index</a>]</p> </div>  <h1 class="section" id="Named-Address-Spaces-1"><span>6.17 Named Address Spaces<a class="copiable-link" href="#Named-Address-Spaces-1"> ¶</a></span></h1>  <p>As an extension, GNU C supports named address spaces as defined in the N1275 draft of ISO/IEC DTR 18037. Support for named address spaces in GCC will evolve as the draft technical report changes. Calling conventions for any target might also change. At present, only the AVR, M32C, PRU, RL78, and x86 targets support address spaces other than the generic address space. </p> <p>Address space identifiers may be used exactly like any other C type qualifier (e.g., <code class="code">const</code> or <code class="code">volatile</code>). See the N1275 document for more details. </p> <ul class="mini-toc"> <li><a href="#AVR-Named-Address-Spaces-1" accesskey="1">AVR Named Address Spaces</a></li> <li><a href="#M32C-Named-Address-Spaces" accesskey="2">M32C Named Address Spaces</a></li> <li><a href="#PRU-Named-Address-Spaces" accesskey="3">PRU Named Address Spaces</a></li> <li><a href="#RL78-Named-Address-Spaces" accesskey="4">RL78 Named Address Spaces</a></li> <li><a href="#x86-Named-Address-Spaces" accesskey="5">x86 Named Address Spaces</a></li> </ul> <div class="subsection-level-extent" id="AVR-Named-Address-Spaces-1"> <h2 class="subsection"><span>6.17.1 AVR Named Address Spaces<a class="copiable-link" href="#AVR-Named-Address-Spaces-1"> ¶</a></span></h2> <p>On the AVR target, there are several address spaces that can be used in order to put read-only data into the flash memory and access that data by means of the special instructions <code class="code">LPM</code> or <code class="code">ELPM</code> needed to read from flash. </p> <p>Devices belonging to <code class="code">avrtiny</code> and <code class="code">avrxmega3</code> can access flash memory by means of <code class="code">LD*</code> instructions because the flash memory is mapped into the RAM address space. There is <em class="emph">no need</em> for language extensions like <code class="code">__flash</code> or attribute <a class="ref" href="variable-attributes"><code class="code">progmem</code></a>. The default linker description files for these devices cater for that feature and <code class="code">.rodata</code> stays in flash: The compiler just generates <code class="code">LD*</code> instructions, and the linker script adds core specific offsets to all <code class="code">.rodata</code> symbols: <code class="code">0x4000</code> in the case of <code class="code">avrtiny</code> and <code class="code">0x8000</code> in the case of <code class="code">avrxmega3</code>. See <a class="ref" href="avr-options">AVR Options</a> for a list of respective devices. </p> <p>For devices not in <code class="code">avrtiny</code> or <code class="code">avrxmega3</code>, 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 <em class="emph">and</em> to generate the right instructions to access this data without using (inline) assembler code, special address spaces are needed. </p> <dl class="table"> <dt>
<span><code class="code">__flash</code><a class="copiable-link" href="#index-_005f_005fflash-AVR-Named-Address-Spaces"> ¶</a></span>
</dt> <dd>
<p>The <code class="code">__flash</code> qualifier locates data in the <code class="code">.progmem.data</code> section. Data is read using the <code class="code">LPM</code> instruction. Pointers to this address space are 16 bits wide. </p> </dd> <dt>
    <span><code class="code">__flash1</code><a class="copiable-link" href="#index-_005f_005fflash1-AVR-Named-Address-Spaces"> ¶</a></span>
</dt> <dt><code class="code">__flash2</code></dt> <dt><code class="code">__flash3</code></dt> <dt><code class="code">__flash4</code></dt> <dt><code class="code">__flash5</code></dt> <dd>
<p>These are 16-bit address spaces locating data in section <code class="code">.progmem<var class="var">N</var>.data</code> where <var class="var">N</var> refers to address space <code class="code">__flash<var class="var">N</var></code>. The compiler sets the <code class="code">RAMPZ</code> segment register appropriately before reading data by means of the <code class="code">ELPM</code> instruction. </p> </dd> <dt>
<span><code class="code">__memx</code><a class="copiable-link" href="#index-_005f_005fmemx-AVR-Named-Address-Spaces"> ¶</a></span>
</dt> <dd>
<p>This is a 24-bit address space that linearizes flash and RAM: If the high bit of the address is set, data is read from RAM using the lower two bytes as RAM address. If the high bit of the address is clear, data is read from flash with <code class="code">RAMPZ</code> set according to the high byte of the address. See <a class="xref" href="avr-built-in-functions"><code class="code">__builtin_avr_flash_segment</code></a>. </p> <p>Objects in this address space are located in <code class="code">.progmemx.data</code>. </p>
</dd> </dl> <p><b class="b">Example</b> </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">char my_read (const __flash char ** p)
{
    /* p is a pointer to RAM that points to a pointer to flash.
       The first indirection of p reads that flash pointer
       from RAM and the second indirection reads a char from this
       flash address.  */

    return **p;
}

/* Locate array[] in flash memory */
const __flash int array[] = { 3, 5, 7, 11, 13, 17, 19 };

int i = 1;

int main (void)
{
   /* Return 17 by reading from flash memory */
   return array[array[i]];
}</pre>
</div> <p>For each named address space supported by avr-gcc there is an equally named but uppercase built-in macro defined. The purpose is to facilitate testing if respective address space support is available or not: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">#ifdef __FLASH
const __flash int var = 1;

int read_var (void)
{
    return var;
}
#else
#include &lt;avr/pgmspace.h&gt; /* From AVR-LibC */

const int var PROGMEM = 1;

int read_var (void)
{
    return (int) pgm_read_word (&amp;var);
}
#endif /* __FLASH */</pre>
</div> <p>Notice that attribute <a class="ref" href="variable-attributes"><code class="code">progmem</code></a> locates data in flash but accesses to these data read from generic address space, i.e. from RAM, so that you need special accessors like <code class="code">pgm_read_byte</code> from <a class="uref" href="https://www.nongnu.org/avr-libc/user-manual/">AVR-LibC</a> together with attribute <code class="code">progmem</code>. </p> <p><b class="b">Limitations and caveats</b> </p> <ul class="itemize mark-bullet"> <li>Reading across the 64 KiB section boundary of the <code class="code">__flash</code> or <code class="code">__flash<var class="var">N</var></code> address spaces shows undefined behavior. The only address space that supports reading across the 64 KiB flash segment boundaries is <code class="code">__memx</code>. </li>
<li>If you use one of the <code class="code">__flash<var class="var">N</var></code> address spaces you must arrange your linker script to locate the <code class="code">.progmem<var class="var">N</var>.data</code> sections according to your needs. </li>
<li>Any data or pointers to the non-generic address spaces must be qualified as <code class="code">const</code>, i.e. as read-only data. This still applies if the data in one of these address spaces like software version number or calibration lookup table are intended to be changed after load time by, say, a boot loader. In this case the right qualification is <code class="code">const</code> <code class="code">volatile</code> so that the compiler must not optimize away known values or insert them as immediates into operands of instructions. </li>
<li>The following code initializes a variable <code class="code">pfoo</code> located in static storage with a 24-bit address: <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">extern const __memx char foo;
const __memx void *pfoo = &amp;foo;</pre>
</div> </li>
<li>On the reduced Tiny devices like ATtiny40, no address spaces are supported. Just use vanilla C / C++ code without overhead as outlined above. Attribute <code class="code">progmem</code> is supported but works differently, see <a class="ref" href="variable-attributes">AVR Variable Attributes</a>. </li>
</ul> </div> <div class="subsection-level-extent" id="M32C-Named-Address-Spaces"> <h2 class="subsection"><span>6.17.2 M32C Named Address Spaces<a class="copiable-link" href="#M32C-Named-Address-Spaces"> ¶</a></span></h2>  <p>On the M32C target, with the R8C and M16C CPU variants, variables qualified with <code class="code">__far</code> are accessed using 32-bit addresses in order to access memory beyond the first 64 Ki bytes. If <code class="code">__far</code> is used with the M32CM or M32C CPU variants, it has no effect. </p> </div> <div class="subsection-level-extent" id="PRU-Named-Address-Spaces"> <h2 class="subsection"><span>6.17.3 PRU Named Address Spaces<a class="copiable-link" href="#PRU-Named-Address-Spaces"> ¶</a></span></h2>  <p>On the PRU target, variables qualified with <code class="code">__regio_symbol</code> are aliases used to access the special I/O CPU registers. They must be declared as <code class="code">extern</code> because such variables will not be allocated in any data memory. They must also be marked as <code class="code">volatile</code>, and can only be 32-bit integer types. The only names those variables can have are <code class="code">__R30</code> and <code class="code">__R31</code>, representing respectively the <code class="code">R30</code> and <code class="code">R31</code> special I/O CPU registers. Hence the following example is the only valid usage of <code class="code">__regio_symbol</code>: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">extern volatile __regio_symbol uint32_t __R30;
extern volatile __regio_symbol uint32_t __R31;</pre>
</div> </div> <div class="subsection-level-extent" id="RL78-Named-Address-Spaces"> <h2 class="subsection"><span>6.17.4 RL78 Named Address Spaces<a class="copiable-link" href="#RL78-Named-Address-Spaces"> ¶</a></span></h2>  <p>On the RL78 target, variables qualified with <code class="code">__far</code> are accessed with 32-bit pointers (20-bit addresses) rather than the default 16-bit addresses. Non-far variables are assumed to appear in the topmost 64 KiB of the address space. </p> </div> <div class="subsection-level-extent" id="x86-Named-Address-Spaces"> <h2 class="subsection"><span>6.17.5 x86 Named Address Spaces<a class="copiable-link" href="#x86-Named-Address-Spaces"> ¶</a></span></h2>  <p>On the x86 target, variables may be declared as being relative to the <code class="code">%fs</code> or <code class="code">%gs</code> segments. </p> <dl class="table"> <dt>
 <span><code class="code">__seg_fs</code><a class="copiable-link" href="#index-_005f_005fseg_005ffs-x86-named-address-space"> ¶</a></span>
</dt> <dt><code class="code">__seg_gs</code></dt> <dd>
<p>The object is accessed with the respective segment override prefix. </p> <p>The respective segment base must be set via some method specific to the operating system. Rather than require an expensive system call to retrieve the segment base, these address spaces are not considered to be subspaces of the generic (flat) address space. This means that explicit casts are required to convert pointers between these address spaces and the generic address space. In practice the application should cast to <code class="code">uintptr_t</code> and apply the segment base offset that it installed previously. </p> <p>The preprocessor symbols <code class="code">__SEG_FS</code> and <code class="code">__SEG_GS</code> are defined when these address spaces are supported. </p>
</dd> </dl> </div> </div>  <div class="nav-panel"> <p> Next: <a href="zero-length">Arrays of Length Zero</a>, Previous: <a href="fixed-point">Fixed-Point Types</a>, Up: <a href="c-extensions">Extensions to the C Language Family</a> [<a href="index#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="indices" title="Index" rel="index">Index</a>]</p> </div><div class="_attribution">
  <p class="_attribution-p">
    &copy; Free Software Foundation<br>Licensed under the GNU Free Documentation License, Version 1.3.<br>
    <a href="https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Named-Address-Spaces.html" class="_attribution-link">https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Named-Address-Spaces.html</a>
  </p>
</div>