Keywords: sdccman

Subsections

- 3.5.1.1 __data / __near
- 3.5.1.2 __xdata / __far
- 3.5.1.3 __idata
- 3.5.1.4 __pdata
- 3.5.1.5 __code
- 3.5.1.6 __bit
- 3.5.1.7 __sfr / __sfr16 / __sfr32 / __sbit
- 3.5.1.8 Pointers to MCS51/DS390 intrinsic named address spaces
- 3.5.1.9 Notes on MCS51 memory layout

## 3.5.1 MCS51/DS390 intrinsic named address spaces

SDCC supports the following MCS51-specific intrinsic address spaces:

###
3.5.1.1 __data / __near

This is the default (generic) address space for the Small Memory model. Variables in this address space will be allocated in the directly addressable portion of the internal RAM of a 8051, e.g.:

> __data unsigned char test_data;

Writing 0x01 to this variable generates the assembly code:

> 75*00 01 mov _test_data,#0x01

###
3.5.1.2 __xdata / __far

Variables in this address space will be placed in the external RAM. This is the default (generic) address space for the Large Memory model, e.g.:

> __xdata unsigned char test_xdata;

Writing 0x01 to this variable generates the assembly code:

> 90s00r00 mov dptr,#_test_xdata
> 74 01 mov a,#0x01
> F0 movx @dptr,a

###
3.5.1.3 __idata

Variables in this address space will be allocated into the indirectly addressable portion of the internal ram of a 8051, e.g.:

> __idata unsigned char test_idata;

Writing 0x01 to this variable generates the assembly code:

> 78r00 mov r0,#_test_idata
> 76 01 mov @r0,#0x01

Please note, the first 128 byte of idata physically access the same RAM as the data memory. The original 8051 had 128 byte idata memory, nowadays most devices have 256 byte idata memory. The stack is located in idata memory (unless --xstack is specified).

###
3.5.1.4 __pdata

Paged xdata access is just as straightforward as using the other addressing modes of a 8051. It is typically located at the start of xdata and has a maximum size of 256 bytes. The following example writes 0x01 to the pdata variable. Please note, pdata access physically accesses xdata memory. The high byte of the address is determined by port P2 (or in case of some 8051 variants by a separate Special Function Register, see section 4.1). This is the default (generic) address space for the Medium Memory model, e.g.:

> __pdata unsigned char test_pdata;

Writing 0x01 to this variable generates the assembly code:

> 78r00 mov r0,#_test_pdata
> 74 01 mov a,#0x01
> F2 movx @r0,a

If the —xstack option is used the pdata memory area is followed by the xstack memory area and the sum of their sizes is limited to 256 bytes.

###
3.5.1.5 __code

'Variables' in this address space will be placed in the code memory:

> __code unsigned char test_code;

Read access to this variable generates the assembly code:

> 90s00r6F mov dptr,#_test_code
> E4 clr a
> 93 movc a,@a+dptr

char indexed arrays of characters in code memory can be accessed efficiently:

> __code char test_array[] = {'c','h','e','a','p'};

Read access to this array using an 8-bit unsigned index generates the assembly code:

> E5*00 mov a,_index

> 90s00r41 mov dptr,#_test_array

> 93 movc a,@a+dptr

###
3.5.1.6 __bit

This is a data-type and an address space. When a variable is declared as a bit, it is allocated into the bit addressable memory of 8051, e.g.:

> __bit test_bit;

Writing 1 to this variable generates the assembly code:

> D2*00 setb _test_bit

The bit addressable memory consists of 128 bits which are located from 0x20 to 0x2f in data memory.
Apart from this 8051 specific intrinsic named address space most architectures support ANSI-C bit-fields3.3. In accordance with ISO/IEC 9899 bits and bitfields without an explicit signed modifier are implemented as unsigned.

###
3.5.1.7 __sfr / __sfr16 / __sfr32 / __sbit

Like the __bit keyword, __sfr / __sfr16 / __sfr32 / __sbit signify both a data-type and named address space, they are used to describe the special function registers and special __bit variables of a 8051, eg:

> __sfr __at (0x80) P0; /* special function register P0 at location 0x80 */
> /* 16 bit special function register combination for timer 0
> with the high byte at location 0x8C and the low byte at location 0x8A */
> __sfr16 __at (0x8C8A) TMR0;
> __sbit __at (0xd7) CY; /* CY (Carry Flag) */

Special function registers which are located on an address dividable by 8 are bit-addressable, an __sbit addresses a specific bit within these sfr.
16 Bit and 32 bit special function register combinations which require a certain access order are better not declared using __sfr16 or __sfr32. Although SDCC usually accesses them Least Significant Byte (LSB) first, this is not guaranteed.

Please note, if you use a header file which was written for another compiler then the __sfr / __sfr16 / __sfr32 / __sbit intrinsic named address spaces will most likely be not compatible. Specifically the syntax sfr P0 = 0x80; is compiled without warning by SDCC to an assignment of 0x80 to a variable called P0. Nevertheless with the file compiler.h it is possible to write header files which can be shared among different compilers (see section 6.1).

###
3.5.1.8 Pointers to MCS51/DS390 intrinsic named address spaces

SDCC allows (via language extensions) pointers to explicitly point to any of the named address spaces of the 8051. In addition to the explicit pointers, the compiler uses (by default) generic pointers which can be used to point to any of the memory spaces.
Pointer declaration examples:

> /* pointer physically in internal ram pointing to object in external ram */
> __xdata unsigned char * __data p;
> /* pointer physically in external ram pointing to object in internal ram */
> __data unsigned char * __xdata p;
> /* pointer physically in code rom pointing to data in xdata space */
> __xdata unsigned char * __code p;
> /* pointer physically in code space pointing to data in code space */
> __code unsigned char * __code p;
> /* generic pointer physically located in xdata space */
> unsigned char * __xdata p;
> /* generic pointer physically located in default memory space */
> unsigned char * p;
> /* the following is a function pointer physically located in data space */
> char (* __data fp)(void);

Well you get the idea.
All unqualified pointers are treated as 3-byte (4-byte for the ds390) generic pointers.
The highest order byte of the generic pointers contains the data space information. Assembler support routines are called whenever data is stored or retrieved using generic pointers. These are useful for developing reusable library routines. Explicitly specifying the pointer type will generate the most efficient code.

###
3.5.1.9 Notes on MCS51 memory layout

The 8051 family of microcontrollers have a minimum of 128 bytes of internal RAM memory which is structured as follows:
- Bytes 00-1F - 32 bytes to hold up to 4 banks of the registers R0 to R7,
- Bytes 20-2F - 16 bytes to hold 128 bit variables and,
- Bytes 30-7F - 80 bytes for general purpose use.

Additionally some members of the MCS51 family may have up to 128 bytes of additional, indirectly addressable, internal RAM memory (__idata). Furthermore, some chips may have some built in external memory (__xdata) which should not be confused with the internal, directly addressable RAM memory (__data). Sometimes this built in __xdata memory has to be activated before using it (you can probably find this information on the datasheet of the microcontroller your are using, see also section 4.1.4 Startup-Code).

Normally SDCC will only use the first bank of registers (register bank 0), but it is possible to specify that other banks of registers (keyword __using ) should be used for example in interrupt routines. By default, the compiler will place the stack after the last byte of allocated memory for variables. For example, if the first 2 banks of registers are used, and only four bytes are used for data variables, it will position the base of the internal stack at address 20 (0x14). This implies that as the stack grows, it will use up the remaining register banks, and the 16 bytes used by the 128 bit variables, and 80 bytes for general purpose use. If any bit variables are used, the data variables will be placed in unused register banks and after the byte holding the last bit variable. For example, if register banks 0 and 1 are used, and there are 9 bit variables (two bytes used), data variables will be placed starting from address 0x10 to 0x20 and continue at address 0x22. You can also use —data-loc to specify the start address of the data and —iram-size to specify the size of the total internal RAM (data+idata).

By default the 8051 linker will place the stack after the last byte of (i)data variables. Option —stack-loc allows you to specify the start of the stack, i.e. you could start it after any data in the general purpose area. If your microcontroller has additional indirectly addressable internal RAM (idata) you can place the stack on it. You may also need to use —xdata-loc to set the start address of the external RAM (xdata) and —xram-size to specify its size. Same goes for the code memory, using —code-loc and —code-size. If in doubt, don't specify any options and see if the resulting memory layout is appropriate, then you can adjust it.

The linker generates two files with memory allocation information. The first, with extension .map shows all the variables and segments. The second with extension .mem shows the final memory layout. The linker will complain either if memory segments overlap, there is not enough memory, or there is not enough space for stack. If you get any linking warnings and/or errors related to stack or segments allocation, take a look at either the .map or .mem files to find out what the problem is. The .mem file may even suggest a solution to the problem.