SLAA534A June   2013  – June 2020

 

  1. Introduction
    1. 1.1  ABIs for the MSP430
    2. 1.2  Scope
    3. 1.3  ABI Variants
    4. 1.4  Toolchains and Interoperability
    5. 1.5  Libraries
    6. 1.6  Types of Object Files
    7. 1.7  Segments
    8. 1.8  MSP430 Architecture Overview
    9. 1.9  MSP430 Memory Models
    10. 1.10 Reference Documents
    11. 1.11 Code Fragment Notation
  2. Data Representation
    1. 2.1 Basic Types
    2. 2.2 Data in Registers
    3. 2.3 Data in Memory
    4. 2.4 Pointer Types
    5. 2.5 Complex Types
    6. 2.6 Structures and Unions
    7. 2.7 Arrays
    8. 2.8 Bit Fields
      1. 2.8.1 Volatile Bit Fields
    9. 2.9 Enumeration Types
  3. Calling Conventions
    1. 3.1 Call and Return
      1. 3.1.1 Call Instructions
        1. 3.1.1.1 Indirect Calls
        2. 3.1.1.2 Direct Calls
      2. 3.1.2 Return Instruction
      3. 3.1.3 Pipeline Conventions
      4. 3.1.4 Weak Functions
    2. 3.2 Register Conventions
      1. 3.2.1 Argument Registers
      2. 3.2.2 Callee-Saved Registers
    3. 3.3 Argument Passing
      1. 3.3.1 Register Singles
      2. 3.3.2 Register Pairs
      3. 3.3.3 Split Pairs
      4. 3.3.4 Quads (Four-Register Arguments)
      5. 3.3.5 Special Convention for Compiler Helper Functions
      6. 3.3.6 C++ Argument Passing
      7. 3.3.7 Passing Structs and Unions
      8. 3.3.8 Stack Layout of Arguments Not Passed in Registers
      9. 3.3.9 Frame Pointer
    4. 3.4 Return Values
    5. 3.5 Structures and Unions Passed and Returned by Reference
    6. 3.6 Conventions for Compiler Helper Functions
    7. 3.7 Scratch Registers for Functions Already Seen
    8. 3.8 _ _mspabi_func_epilog Helper Functions
    9. 3.9 Interrupt Functions
  4. Data Allocation and Addressing
    1. 4.1 Data Sections and Segments
    2. 4.2 Addressing Modes
    3. 4.3 Allocation and Addressing of Static Data
      1. 4.3.1 Addressing Methods for Static Data
        1. 4.3.1.1 Absolute Addressing
        2. 4.3.1.2 Symbolic Addressing
        3. 4.3.1.3 Immediate Addressing
      2. 4.3.2 Placement Conventions for Static Data
        1. 4.3.2.1 Abstract Conventions for Placement
        2. 4.3.2.2 Abstract Conventions for Addressing
      3. 4.3.3 Initialization of Static Data
    4. 4.4 Automatic Variables
    5. 4.5 Frame Layout
      1. 4.5.1 Stack Alignment
      2. 4.5.2 Register Save Order
    6. 4.6 Heap-Allocated Objects
  5. Code Allocation and Addressing
    1. 5.1 Computing the Address of a Code Label
      1. 5.1.1 Absolute Addressing for Code
      2. 5.1.2 Symbolic Addressing
      3. 5.1.3 Immediate Addressing
    2. 5.2 Branching
    3. 5.3 Calls
      1. 5.3.1 Direct Call
      2. 5.3.2 Far Call Trampoline
      3. 5.3.3 Indirect Calls
  6. Helper Function API
    1. 6.1 Floating-Point Behavior
    2. 6.2 C Helper Function API
    3. 6.3 Special Register Conventions for Helper Functions
    4. 6.4 Floating-Point Helper Functions for C99
  7. Standard C Library API
    1. 7.1  Reserved Symbols
    2. 7.2  <assert.h> Implementation
    3. 7.3  <complex.h> Implementation
    4. 7.4  <ctype.h> Implementation
    5. 7.5  <errno.h> Implementation
    6. 7.6  <float.h> Implementation
    7. 7.7  <inttypes.h> Implementation
    8. 7.8  <iso646.h> Implementation
    9. 7.9  <limits.h> Implementation
    10. 7.10 <locale.h> Implementation
    11. 7.11 <math.h> Implementation
    12. 7.12 <setjmp.h> Implementation
    13. 7.13 <signal.h> Implementation
    14. 7.14 <stdarg.h> Implementation
    15. 7.15 <stdbool.h> Implementation
    16. 7.16 <stddef.h> Implementation
    17. 7.17 <stdint.h> Implementation
    18. 7.18 <stdio.h> Implementation
    19. 7.19 <stdlib.h> Implementation
    20. 7.20 <string.h> Implementation
    21. 7.21 <tgmath.h> Implementation
    22. 7.22 <time.h> Implementation
    23. 7.23 <wchar.h> Implementation
    24. 7.24 <wctype.h> Implementation
  8. C++ ABI
    1. 8.1  Limits (GC++ABI 1.2)
    2. 8.2  Export Template (GC++ABI 1.4.2)
    3. 8.3  Data Layout (GC++ABI Chapter 2)
    4. 8.4  Initialization Guard Variables (GC++ABI 2.8)
    5. 8.5  Constructor Return Value (GC++ABI 3.1.5)
    6. 8.6  One-Time Construction API (GC++ABI 3.3.2)
    7. 8.7  Controlling Object Construction Order (GC++ ABI 3.3.4)
    8. 8.8  Demangler API (GC++ABI 3.4)
    9. 8.9  Static Data (GC++ ABI 5.2.2)
    10. 8.10 Virtual Tables and the Key function (GC++ABI 5.2.3)
    11. 8.11 Unwind Table Location (GC++ABI 5.3)
  9. Exception Handling
    1. 9.1  Overview
    2. 9.2  PREL31 Encoding
    3. 9.3  The Exception Index Table (EXIDX)
      1. 9.3.1 Pointer to Out-of-Line EXTAB Entry
      2. 9.3.2 EXIDX_CANTUNWIND
      3. 9.3.3 Inlined EXTAB Entry
    4. 9.4  The Exception Handling Instruction Table (EXTAB)
      1. 9.4.1 EXTAB Generic Model
      2. 9.4.2 EXTAB Compact Model
      3. 9.4.3 Personality Routines
    5. 9.5  Unwinding Instructions
      1. 9.5.1 Common Sequence
      2. 9.5.2 Byte-Encoded Unwinding Instructions
    6. 9.6  Descriptors
      1. 9.6.1 Encoding of Type Identifiers
      2. 9.6.2 Scope
      3. 9.6.3 Cleanup Descriptor
      4. 9.6.4 Catch Descriptor
      5. 9.6.5 Function Exception Specification (FESPEC) Descriptor
    7. 9.7  Special Sections
    8. 9.8  Interaction With Non-C++ Code
      1. 9.8.1 Automatic EXIDX Entry Generation
      2. 9.8.2 Hand-Coded Assembly Functions
    9. 9.9  Interaction With System Features
      1. 9.9.1 Shared Libraries
      2. 9.9.2 Overlays
      3. 9.9.3 Interrupts
    10. 9.10 Assembly Language Operators in the TI Toolchain
  10. 10DWARF
    1. 10.1 DWARF Register Names
    2. 10.2 Call Frame Information
    3. 10.3 Vendor Names
    4. 10.4 Vendor Extensions
  11. 11ELF Object Files (Processor Supplement)
    1. 11.1 Registered Vendor Names
    2. 11.2 ELF Header
    3. 11.3 Sections
      1. 11.3.1 Section Indexes
      2. 11.3.2 Section Types
      3. 11.3.3 Extended Section Header Attributes
      4. 11.3.4 Subsections
      5. 11.3.5 Special Sections
      6. 11.3.6 Section Alignment
    4. 11.4 Symbol Table
      1. 11.4.1 Symbol Types
      2. 11.4.2 Common Block Symbols
      3. 11.4.3 Symbol Names
      4. 11.4.4 Reserved Symbol Names
      5. 11.4.5 Mapping Symbols
    5. 11.5 Relocation
      1. 11.5.1 Relocation Types
        1. 11.5.1.1 Absolute Relocations
        2. 11.5.1.2 PC-Relative Relocations
        3. 11.5.1.3 Relocations in Data Sections
        4. 11.5.1.4 Relocations for MSP430 Instructions
        5. 11.5.1.5 Relocations for MSP430X Instructions
        6. 11.5.1.6 Other Relocation Types
      2. 11.5.2 Relocation Operations
      3. 11.5.3 Relocation of Unresolved Weak References
  12. 12ELF Program Loading and Linking (Processor Supplement)
    1. 12.1 Program Header
      1. 12.1.1 Base Address
      2. 12.1.2 Segment Contents
      3. 12.1.3 Thread-Local Storage
    2. 12.2 Program Loading
  13. 13Build Attributes
    1. 13.1 MSP430 ABI Build Attribute Subsection
    2. 13.2 MSP430 Build Attribute Tags
  14. 14Copy Tables and Variable Initialization
    1. 14.1 Copy Table Format
    2. 14.2 Compressed Data Formats
      1. 14.2.1 RLE
      2. 14.2.2 LZSS Format
    3. 14.3 Variable Initialization
  15. 15Revision History

Variable Initialization

As described in Section 4.2, initialized read-write variables are collected into dedicated section(s) of the object file, for example .data. The section contains an image of its initial state upon program startup.

The TI toolchain supports two models for loading such sections. In the so-called RAM model, some unspecified external agent such as a loader is responsible for getting the data from the executable file to its location in read-write memory. This is the typical direct-initialization model used in OS-based systems or, in some instances, boot-loaded systems.

The other model, called the ROM model, is intended for bare-metal embedded systems that must be capable of cold starts without support of an OS or other loader. Any data needed to initialize the program must reside in persistent offline storage (ROM), and get copied into its RAM location upon startup. The TI toolchain implements this by leveraging the copy table capability described in Chapter 14. The initialization mechanism is conceptually similar to copy tables, but differs slightly in the details.

Figure 14-3 depicts the conceptual operation of variable initialization under the ROM model. In this model, the linker removes the data from sections that contain initialized variables. The sections become uninitialized sections, allocated into RAM at their run-time address (much like, say, .bss). The linker encodes the initialization data into a special section called .cinit (for C Initialization), where the startup code from the run-time library decodes and copies it to its run address.

GUID-0BA59A60-13BA-4334-B0AB-58EF34C385F0-low.gifFigure 14-3 ROM-Based Variable Initialization Via cinit

Like copy tables, the source data in the .cinit tables may or may not be compressed. If it is compressed, the encoding and decoding scheme is identical to that of copy tables so that the handler tables and decompression handlers can be shared.

The .cinit section contains some or all of the following items:

  • The cinit table, consisting of cinit records, which are similar to copy records.
  • The handler table, consisting of pointers to decompression routines, as described in Section 14.2. The handler table and handlers are shared by initialization and copy tables.
  • The source data, consisting of compressed or uncompressed data used to initialize variables.

These items may be in any order.

Figure 14-4 is a schematic depiction of the .cinit section.

GUID-4D35E64F-7F44-416F-83A9-191292DD559F-low.gifFigure 14-4 The .cinit Section

The .cinit section has the section type SHT_TI_INITINFO which identifies it as being in this format. Tools should rely on the section type and not on the name .cinit.

Two special symbols are defined to delimit the cinit table: __TI_CINIT_Base points to the cinit table, and __TI_CINIT_Limit points one byte past the end of the table. The startup code references the table using these symbols.

The format of the CINT_RECORD structure depends on the code and data model being used.

For the small data model and small code model:

        typedef struct  {
           void  * source_data; /* 16-bit pointer */
           void  * dest;        /* 16-bit pointer */
        } CINIT_RECORD;

For the small data model and large code model:

        typedef struct  {
           uint32  source_data; /* 32-bit storage for data or code pointer */
           uint32  dest;        /* 32-bit storage for data or code pointer */
        } CINIT_RECORD;

For the large (or restricted) data model and large code model:

        typedef struct  {
           void  * source_data; /* 20-bit pointer */
           void  * dest;        /* 20-bit pointer */
        } CINIT_RECORD;
  • The source_data field points to the source data in the cinit section.
  • The dest field points to the destination address. Unlike copy table records, cinit records do not contain a size field; the size is always encoded in the source data.

The source data has the same format as compressed copy table source data (see Section 14.2), and the handlers have the same interface. In addition to the RLE and LZSS formats, there are two additional formats defined for cinit records: uncompressed, and zero-initialized.

  • The explicit uncompressed format is required because unlike a copy table record, there is no overloaded size field in a cinit record. The size field is always encoded into the source data, even when no compression is used. The encoding is as follows:
    GUID-3A235658-F83B-4E34-926C-857CB5E676B0-low.png

    The encoded data includes a size field, which is aligned on the next 2-byte boundary following the handler index. The size of the "size" field depends on the memory model. For the small code and small data model, the size is 2 bytes. In all other memory model combinations, the size is 4 bytes. The size field specifies how many bytes are in the data payload, which begins immediately following the size field. The initialization operation copies sizebytes from the data field to the destination address. The TI run-time library contains a handler called _ _TI_decompress_none for the uncompressed format.

  • The zero-initialization format is a compact format used for the common case of variables whose initial value is zero. The encoding is as follows:
    GUID-1CD24896-7391-42EA-9415-3F03050D6680-low.png

    The size field is aligned on the next 2-byte boundary following the handler index. The size of the "size" field depends on the memory model. For the small code and small data model, the size is 2 bytes. In all other memory model combinations, the size is 4 bytes. The initialization operation fills size consecutive bytes at the destination address with zero. The TI run-time library contains a handler called _ _TI_zero_init for this format.

    As an optimization, the linker is free to coalesce initializations of adjacent objects into single cinit records if they can be profitably encoded using the same format. This is typically significant for zero-initialized objects.