w65 ABI
Types
Alignment
Each Primitive Type shall have an alignment equal to its size, up to a maximum fundamental alignment of 4.
Type Sizes
The sizes of scalar types are given as follows:
- CHAR_BIT shall be defined as precisely 8. That is, char, unsigned char, and signed char are 8-bit
- unsigned short, short, unsigned int, and int shall all have size 2.
- long, unsigned long, all pointer types, shall have size 4
- long long and unsigned long long shall both have size 8
- All uint_leastN_t and int_leastN_t types shall be the same as the corresponding uintN_t or intN_t type, respectively.
- All uint_fastN_t and int_fastN_t types, except for uint_fast8_t and int_fast8_t, shall be the same as the corresponding uintN_t or uintN_t types.
- The uint_fast8_t and int_fast8_t types shall have size 2
- size_t shall be unsigned int. ptrdiff_t shall be signed int.
- The underlying type of an unscoped enumeration type without a fixed underlying type shall be int. (This applies to repr(C) fieldless enums in rust)
uint_fast8_t
The uint_fast8_t typedef corresponds to a special type which has size 2, and the following properties:
- It shall be capable of storing and exactly representing any value of type unsigned char
- After storing any value of such a type, passing the value as a parameter, or returning the value from a function, the value of the most significant byte is undefined. The value of the least significant byte is equivalent to the value representation of the value interpreted as type unsigned char.
- When passing a value of type uint_fast8_t to a function, it is passed as a 16-bit value. If all parameters passed in the X or Y registers are of this type or of type int_fast8_t, the value of the x flag is undefined upon entry to the function.
- When returning a value of type uint_fast8_t, it is returned as a 16-bit value, except that the value of the m flag is undefined upon return to the caller,
The int_fast8_t typedef corresponds to a special type with the same properties as above, except that it shall be capable of storing and exactly representing any value of type signed char.
Signed Integer Representation
This document defines that signed integers shall be represented using 2s complement.
Floating Point Representation
The type float shall be represented as an IEEE 754 binary single precision floating-point value. The type double shall be represented as a binary double precision value. The type long double
shall be represented as an IEEE 754 binary double precision value, as an IEEE 754 quad precision value, or as an 80-bit extended double precision value. It is implementation-defined which type long double
represents.
If the implementation may define an extended __float16
or _Float16
type, it shall be represented as an IEEE 754 binary half precision value.
If the implementation may define an extended __float128
or _Float128
type, it shall be represented as an IEEE 754 quad precision value, and shall be compatible with the long double
type if long double
is represented as an IEEE 754 quad precision value.
Support for 80-bit floating-point arithmetic is not defined by this document.
Atomics
Atomic operations of size 16 or 8 shall be treated as always lock free. Other sizes of atomics are never treated as lock free. Accessing an non-lock free atomic from an interrupt handler other than BRK or COP has undefined behavior if the interrupt handler interrupts any non-lock free atomic operation.
As a suggested extension, implementations are recommended to implement non-lock free atomics such that the IRQ handler may additionally access non-lock free atomics as though they were lock free. Implementations are recommended to document when this is the case.
va_list
The va_list type shall be an array of 1 element containing a pointer to void. The va_start
macro shall initialize the list with a pointer to the first variadic parameter on the stack, and the va_arg
macro shall increment by the size of the type, rounded up to 2, after aligning to the proper alignment by incrementing the pointer
jmp_buf
The jmp_buf
type shall be an array of 1 element containing the following exposition-only structure type
struct __jmp_buf{
unsigned long __regs[3];
unsigned int _S;
unsigned int _D;
unsigned int _PC;
unsigned char _K;
unsigned char __pad;
};
The setjmp
macro shall initialize the __jmp_buf
as follows:
__regs
shall be initialized to the values of__r6
,__r7
, and__r8
respectively_S
shall be initialized to some offset of the current stack pointer_D
shall be initialized to the value of the Direct Page Register_PC
and_K
shall be initialized to some unspecified value such that executing that combined address will transfer control to the instruction immediately following the setjmp macro.__pad
shall be initialized to zero
The longjmp
function shall restore each register from the given __jmp_buf
, and store it’s second argument in the return value.
The __builtin_setjmp
function shall be defined by the implementation, with the signature int __builtin_setjmp(struct __jmp_buf*)
, which performs the behaviour specified above for the setjmp
macro, treating the return value as the instruction immediately following the setjmp macro.
fenv_t
The fenv_t type shall be an alias of the long
type.
The fexception_t
type shall be an alias of the int
type.
(Note: The fenv_t
type may be extended in future versions, and thus should not be passed across an abi boundery by-value)
The fegetenv
function shall be an alias for the __float_getenv
function, and the fesetenv
function shall be an alias for the __float_setenv
function.
The value loaded by __float_getenv
and stored by __float_setenv
is the 32-bit value given as follows:
- The lower 16-bits (except) shall be a bitmask of the exceptions indicated by the environment,
- Bit 17 (emask) shall be set if floating-point exceptions are suppressed from triggering interrupts (otherwise, it is implementation-defined whether an interrupt occurs as a result of floating-point exceptions)
- Bits 18-21 (rnd) encode the rounding mode, given below
- All other bits are reserved, and are set to
0
by__float_getenv
and ignored (masked) by__float_setenv
. Reserved bits may be used in future versions of the ABI
The Floating-Point exception mask in fenv_t
and fexception_t
is given by the following table
| Bit | Exception |
|—–|————-|
| 0 | FE_DIVBYZERO|
| 1 | FE_UNDERFLOW|
| 2 | FE_OVERFLOW |
| 3 | FE_INEXACT |
| 4 | FE_INVALID |
Other bits may be defined and used by future versions, but are otherwise reserved, and are set to 0
by __float_getenv, and ignored (masked) by
__float_setenv`.
The <fenv.h>
header shall define constants with the names given in the above table, corresponding to the value (1<<Bit)
, where Bit
is the corresponding bit for the exception given in the above table.
The Rounding Mode in bits 18-21 (rnd) is given by the following table: | Value | Mode | |——-|————–| | 0 | FE_TONEAREST | | 1 | FE_DOWNWARD | | 2 | FE_UPWARD | | 3 | FE_TOWARDZERO|
Other rounding mode values are not defined, and will not be produced by __float_getenv
. The behaviour of setting such a mode is undefined.
The FE_DEF_ENV
macro shall expand to a pointer to the symbol __float_defenv
. The value of __float_defenv
is unspecified, except that no exceptions shall be indicated by it and rnd
shall be FE_TONEAREST
.
If the implementation provides a _Reset
implementation that calls the main
function, then prior to calling the main
function, the _Reset
implementation shall execute the equivalent of __float_setenv(&__float_defenv)
. Otherwise, it is unspecified whether the floating-point environment is intialized prior to the first call to __float_setenv
.
Extended (in-memory) Registers
This ABI requires that implementations define 8 Extended Registers as symbols, which are available in Bank 0, for storing 4-byte values and additional 8-byte values. These registers shall be stored contiguously in memory, in ascending numerical order, with no padding between each register, and shall be aligned to 4 bytes (and even numbered registers shall be aligned to 8). The registers are indicated by __r
n
where n is the register number from 0 to 7.
Given each register, there shall be 3 additional sub-registers, which access part of the memory allocated for the extended register. These registers shall be indicated as __r
n
w
, which accesses the lower 2-bytes of __r
n
, __r
n
h
, which access the high byte of __r
n
w
, and __r
n
l
, which accesses the lowest order byte of __r
n
.
Calling Conventions
C Calling Convention (Main/Default/Extern C)
Registers
The e flag, as well as the S, PC, K registers, and the __r6
, __r7
, and __r8
extended register are all callee saved (non-volatile). All other registers are caller saved (volatile).
Upon entry or exit of a function, the direct page register shall be set to an unspecified value for which all extended registers are reachable from. Upon calling a function, the m flag shall be set. Upon return from a function, the x flag shall be clear.
Parameter and Return Value ABI
Small Types
- The first two bool (
_Bool
) parameters are passed inverted in the Z then C flags, all remaining bool (_Bool
) parameters are treated as 1-byte parameters. bool (_Bool
) values are returned, inverted, in the Z flag. The return value shall also be present in the A register (the m flag is set on return for bool (_Bool
) return types).- The value of false shall be 0. The value of true shall be the value 1. The behaviour of returning or passing a bool (
_Bool
) value with any other object representation is undefined.
- The value of false shall be 0. The value of true shall be the value 1. The behaviour of returning or passing a bool (
- The first two 1 or 2 byte parameters are passed (in order) in the X and Y registers. If all of these parameters which exist are 1 byte, then the x flag is set, otherwise, the x flag is clear (including if there are no 1 or 2-byte parameters) and any 1 byte parameters are extended to 2-bytes (zero extended if the source type is unsigned, sign-extended if signed). Remaining parameters use the
__r
n
w
(for 2 byte parameters) and__r
n
l
(for 1 byte parameters) in the order defined for 4 byte parameters, then remaining ones are passed on the stack, 1 or 2 byte parameters are returned in the A register (m is set on return for 1 byte return values, otherwise m is clear, including for return type void, or an larger return type)- As a special case, if either such parameter is uinfreet_fast8_t (resp. int_fast8_t) or an equivalent type, the type of the other parameter determines the value of the x flag. If both parameters have this type, then the value of the x flag is indeterminate. If a function returns a value of this type, the value of the m flag is indeterminate.
- 4 byte parameters (including pointers), and additional 1 or 2 byte parameters, are passed in the extended registers in order
__r1
,__r2
,__r3
,__r4
,__r5
,__r6
- 8 byte (16 byte resp.) parameters are passed as 2 (4 resp.) 4-byte parameters
- 0 sized parameters, and empty classes defined in C++ except for empty classes that are non-trivially for the purposes of abi, are ignored and synthesized as arguments and return values.
- All remaining parameters are pushed to the stack from Right to left.
- All passed and static normal pointers are treated as 4-byte values. For the purposes of this abi, pointer values are valid and inbounds only if the most significant byte is 0. A program that attempts to dereference a pointer with a most significant byte other than 0 has undefined behaviour. All objects and functions defined by a compliant implementation shall be placed at memory address corresponding to such a pointer.
- User Code should not rely on this behaviour being preserved in future versions. See Future Directions for details.
- Varargs parameters are always pushed onto the stack from Right to left.
Other Structs/Unions/Large Values
- Any type not explicitly mentioned above, as well as types defined in C++ that are non-trivial for the purposes of calls, are pushed onto the stack before other parameters, and a pointer to the parameter is passed in the parameter’s position.
- A pointer to the place to store/construct the returned value is passed in
__r0
. The return value is stored/constructed at that pointer, and the pointer is then returned in__r0
.
No parameters are passed to any function with an empty parameter list and that returns either void, or does not return.
A regular function which has external linkage, or for which a pointer is created, shall be called with the jsl (Jump to Subroutine Long, opcode $22) instruction and return with the rtl (return from subroutine long, opcode $6B) instruction.
Interrupt Calling convention
A special convention is defined to be suitable for use in defining native mode interrupt handlers. Such interrupt handlers must have an empty parameter list and return void.
The behavior is undefined if an interrupt handler function is called, except by an interrupt vector. Implementations are encouraged to diagnose such violations.
Interrupt Handlers shall save any register, other than the status register, used by the handler (including any caller saved registers whenever it calls a function). If __atomic_reset_enabled
is set, the value in X shall be stored to the pointer at __r1
. __atomic_reset_enabled
shall then be cleared.
Returning from a function with this calling convention executes the RTI instruction.
The requirements imposed on interrupt handlers are the same as those imposed on asynchronous signal handlers within the C11 standard, except that the BRK and COP interrupts are treated as synchronous signal handlers (as though triggered by a call to raise/abort). The behaviour is undefined if an interrupt handler exits via an exception or unwinding panic.
The following symbols are defined to correspond with various interrupt vectors used in native mode, and shall be defined with this calling convention (no diagnostic is required):
- __native_cop (Coprocessor Interrupt)
- __native_brk (Software Break)
- __native_irq (Interrupt Request)
- __native_nmi (Non-maskable Interrupt)
- __native_abort (Abort Execution)
The following symbols are defined to correspond with various interrupt vectors used in emulation mode:
- __emulation_cop (Coprocessor Interrupt)
- __emulation_irq (Interrupt Request/Software Break)
- __emulation_nmi (Non-maskable Interrupt)
- __emulation_abort (Abort Execution)
- _Reset (Reset Processor)
Additionally, the following symbols are reserved. The behaviour of a program that defines a symbol with any such name is undefined:
- __emulation_brk
- __emulation_reset
- __native_reset
Implementation Provided _Reset
If the _Reset
symbol is not defined by the program, then the implementation may provide a definition of the _Reset
symbol that calls a function by the name of main
with no arguments, and that returns void
. If it does so, the following is guaranteed to be performed:
- All objects with static storage are either constant/static initialized if defined in a language without dynamic initialization of objects with static storage duration or if the object has constant initialization (or performs constant initialization), and zero-initialized otherwise
- The floating-point environment is initialized as if by the call
__float_setenv(&__float_defenv)
- All objects with static storage duration that have dynamic initialization and are defined at file or namespace scope have dynamic initialization performed
- The main function is called
It is implementation-defined whether the implementation provides the _Reset
symbol if not user-defined. The definition shall handle returning from the main
function, and terminate execution in an unspecified manner.
The implementation shall support unwinding out of the main
function and doing so shall terminate execution in an unspecified manner.
Language ABIs
Itanium C++ ABI
C++ classes that are non-trivial for the purposes of calls use large value abi, regardless of size or alignment. Empty C++ classes that are not non-trivial for the purposes of calls are treated as zero sized types for the purposes of passing and returning values, otherwise are treated as though they have size 1 and alignment 1 (unless modified).
Pointer to Member Functions do not use the least significant bit to differentiate between vtable offsets and non-virtual function addresses. Rather, it uses the most significant bit. (This permits implementations to pack function definitions together, with no padding between, when space constraints would make requiring even addresses unreasonable). There are no changes to the this-adjustment offset, nor any other changes to the layout of a Pointer-to-member function.
Rust
This section applies to all rust implementations that conform to this abi.
The extern”C” and extern”system” abis are equivalent to the C Calling Convention documented above. The extern”platform-intrinsic” abi is reserved for future extensions, but should otherwise be treated as equivalent. Rust implementations shall define the extern”w65-interrupt” abi, to correspond to the Interrupt Calling Convention defined above. All other abis are not specified by this document and excluding the extern”Rust”, extern”rust-call”, and extern”rust-intrinsic” abi, programs that conform to this ABI shall not use such abis. This ABI imposes no requirements that implementations forbid or diagnose the use of such abis.
LCRust Versioned ABI
This section applies only to rust implementations that implement the LCRust ABI, version 0, or any later version subject to changes in those versions, documented here.
extern"Rust"
is equivalent to the C Calling Convention described above.
The hash algorithm used for computing the hash-part of TypeId shall be FNV-1a 32-bit.
The correspondence of types, for the purposes of Mangling According to the section following are as follows:
u8
andi8
shall correspond tounsigned char
andsigned char
respectivelyu16
andi16
shall correspond tounsigned short
andsigned short
respectivelyu32
andi32
shall correspond tounsigned long
andsigned long
respectively.u64
andi64
shall correspond tounsigned long long
andsigned long long
respectively.u128
andi128
shall correspond to the extended__uint128
and__int128
types.usize
andisize
shall be mangled asu5usize
andu5isize
.
ELF Files
65816 Common
65816 ELF Files may use the e_machine value EM_65816, 257.
The class for 65816 elf files is ELFCLASS32; the order is ELFDATA2LSB (Little Endian). Use of ELFCLASS64 or ELFDATA2MSB is not specified.
By default, 65816 ELF Files are recommended to use either ELFOSABINONE (Sys-V) or ELFOSABISTANDALONE. Use of other abis is not specified.
Use of EOSABINONE is recommended if and only if produced by a compiler (or hand-written assembly) which subscribes to the above defined ABI.
65816 Relocatable ELF Files may use the following relocations. If a relocation occurs across a bank boundary, the behaviour is undefined.
- R_WC65816_NONE (0), which performs no relocation
- R_WC65816_ABS24 (1), which performs a 3-byte (long address) relocation against a symbol’s absolute long address. Long address relocations are of the form [ll hh bb], where hhll forms the symbol’s binary address (value&0xffff), and bb forms the symbol’s bank (value&0xff0000»16).
- R_WC65816_ABS16 (2), which performs a 2-byte (standard address) relocation against a symbol’s bank-local address. Bank-local address relocations are of the form [ll hh], where hhll forms the symbol’s binary address. The bank of the symbol is ignored.
- R_WC65816_REL8 (3), which performs a 1-byte (local) relocation against the lower 1-byte of a symbol’s PC Relative address (which is checked relative to the byte immediately before the relocation). If the symbol is not within 256 bytes (wrapping at bank boundaries) of the PC value immediately prior to the relocation, an error shall be issued at link-time
- R_WC65816_REL16 (4), which performs a 2-byte (relative address) relocation against the symbol’s pc relative address. If the symbol is not within the same bank, an error shall be issued at link time.
- R_WC65816_BANK (5), which performs a 1-byte (bank) relocation against the symbol’s absolute address. Bank relocations are of the form [bb], where bb forms the symbol’s bank.
- R_WC65816_ABS8 (6) which performs a 1-byte relocation against the symbols Direct Page address (the low byte of the symbol’s value). It is an error if the symbol’s bank is not 0. The behaviour is undefined if the symbol is accessed by this relocation while the symbol is not accessible from the direct page.
- R_WC65816_DIR (7) which performs a 2-byte relocation against the symbols Direct Page Base address (which is the symbol’s 16-bit address, rounded down to the last multiple of 256).
- Relocations 8 and 9 are reserved for future expansion.
- R_WC65816_RELAX_JSL (10), hint that a jsl <long> sequence can be relaxed to jsr <abs> to the relocation symbol if the relocation symbol of this relocation is within the same bank as $.
- R_WC65816_RELAX_JML (11), hint that a jmp <long> sequence can be replaced with a jmp <abs> sequence, if the destination symbol is within the same bank as $. Also permits replacement with bra rel8 if the destination is within range.
- R_WC65816_RELAX_BRL (12), hint that a brl <rel16> sequence can be replaced by a bra <rel8> sequence, if the destination symbol is within the range of a rel8 jmp.
- R_WC65816_RELAX_DIR (13), hints that an abs16 or abs24 operation can be relaxed to a abs8 operation, if the value is within the 256 bytes following the value of __direct_page, wrapping around bank boundaries.
- R_WC65816_RELAX_ABS (14), hints that an abs24 operation can be relaxed to an abs16 operation, if the value is in the same bank as $. Note: this can only be used correctly if DBR=K.
- R_WC65816_RELAX_JMP (15), hints that an jmp abs16 can be replaced with a bra rel8 if the destination is in range
- Relocations 16-31 are reserved for future expansion
- Relocations 32-63 may have implementation-defined behaviour.
- Implementations which use these relocation numbers are recommended to use some mechanism to ensure files produced by other implementations using such numbers expecting different behaviour are not processed. This document does not specify such a mechanism.
When an implementation emits relocations 10-15, it shall also emit valid relocations (as necessary) for the explicitly generated code. Use of relocations 10-15 is advisory only, an implementation need not perform any replacement indicated by any such relocation, and may choose to ignore such relocations instead.
Additional Requirements
Pointer to Function Trampoline
The implementation shall define a function _FnPtrTrampoline
. The program should not call this function directly. It must be called with JSL. When called with a function pointer in __r8
, it shall perform a tailcall to that function. Otherwise, the behaviour of the function is undefined.
Extended Arithmetic
The implementation shall, for each value N in 8, 16, 32, 64, and optionally 128, the define each of the following functions with the given prototypes and behaviour (where the N
in the symbol name and in the prototypes are replaced with the integer):
intN_t __add_intN(intN_t a, intN_t b)
- Adds two signed integers with width N and returns the result
uintN_t __add_uintN(uintN_t a, uintN_t b)
- Adds two unsigned integers with width N and returns the result
_Fixed intN_t __add_fixedN(_Fixed intN_t a, _Fixed intN_t b);
- Adds two fixed point integers with width N and returns the result
intN_t __sub_intN(intN_t a, intN_t b)
- Subtracts two signed integers with width N and returns the result
uintN_t __sub_uintN(uintN_t a, uintN_t b)
- Subtracts two unsigned integers with width N and returns the result
_Fixed intN_t __sub_fixedN(_Fixed intN_t a, _Fixed intN_t b);
- Subtracts two fixed point integers with width N and returns the result
intN_t __mul_intN(intN_t a, intN_t b)
- Multiplies two signed integers with width N and returns the result
uintN_t __mul_uintN(uintN_t a, uintN_t b)
- Multiplies two unsigned integers with width N and returns the result
_Fixed intN_t __mul_fixedN(_Fixed intN_t a, _Fixed intN_t b);
- Multiplies two fixed point integers with width N and returns the result
intN_t __lsh_intN(intN_t a, intN_t b)
- Left-shifts two signed integers with width N and returns the result
uintN_t __lsh_uintN(uintN_t a, uintN_t b)
- Left-shifts two unsigned integers with width N and returns the result
_Fixed intN_t __lsh_fixedN(_Fixed intN_t a, _Fixed intN_t b);
- Left-shifts two fixed point integers with width N and returns the result
intN_t __rsh_intN(intN_t a, intN_t b)
- Adds two signed integers with width N and returns the result
uintN_t __rsh_uintN(uintN_t a, uintN_t b)
- Right-shifts two unsigned integers with width N and returns the result
_Fixed intN_t __rsh_fixedN(_Fixed intN_t a, _Fixed intN_t b);
- Right-shifts two fixed point integers with width N and returns the result
int_divN_t __div_intN(intN_t a, intN_t b)
- Divides two unsigned integers with width N and returns the quotient and the remainder
uint_divN_t __div_uintN(uintN_t a, uintN_t b)
- Divides two unsigned integers with width N and returns the quotient and the remainder
_Fixed intN_t __div_fixedN(_Fixed intN_t a, _Fixed intN_t b);
- Divides two fixed point integers with width N and returns the result
Where the uint_divN_t
type is an expostion-only type which has the following definition:
struct uint_divN_t{
uintN_t quotient;
uintN_t remainder;
};
And the int_divN_t
type is defined the same but using intN_t
instead of uintN_t
.
Whether or not any particular symbol is defined by the implementation for N=128 is implementation-defined. Every symbol defined by this section is reserved [Note: this includes the 128-bit forms even if the implementation chooses not to define them].
If any operation, other than fixed point division or multiplication, defined in this section overflows, the integer operation wraps mod 2^N. If fixed point division or multiplication overflows, the result is unspecified.
Floating Point Operations
For each N in 16, 32, 64, and 128, an implementation optionally defines the following symbols wit the following prototypes, where _FloatN
has meaning as follows:
_Float16
is an exposition-only type with size 2 and alignment 2 that is a scalar type and represents 16-bit floating-point values according to the Half Precision Binary Floating-point format defined by IEEE 754._Float32
is an exposition-only typedef that is defined as though bytypedef float _Float32;
_Float64
is an exposition-only typedef that is defined as though bytypedef double _Float64;
except that any prototype in this section may also be called and declared as though_Float64
were defined astypedef long double _Float64;
iflong double
is represented as a Double Precision Floating-point value_Float128
is an exposition-only type with size 16 and alignment 2 that is a scalar type and represents 128-bit floating-point values according to the Quad Precision Binary Floating-point format defined by IEEE 754. Iflong double
is represented as a Quad Precision Floating-point value, the implementation shall define the prototypes as though_Float128
were an defined astypedef long double _Float128;
_FloatN __float_addN(_FloatN x,_FloatN y);
- Adds two floating point values x and y and returns the result, according to the current rounding mode.
_FloatN __float_subN(_FloatN x, _FloatN y)
- Subtracts two floating point values x and y and returns the result, according to the current rounding mode.
_FloatN __float_mulN(_FloatN x,_FloatN y);
- Multiplies two floating point values x and y and returns the result, according to the current rounding mode.
_FloatN __float_divN(_FloatN x,_FloatN y);
- Divides two floating point values x and y and returns the result, according to the current rounding mode.
_FloatCmpResult __float_cmpN(_FloatN x,_FloatN y);
- Performs a partially ordered comparison of x and y
The type _FloatCmpResult
is an exposition-only type defined as though by the C++ enumeration definition:
enum _FloatCmpResult : signed char{
Less = -1,
Greater = 1,
Equal = 0,
Unordered = 0x7f
}
int __float_getenv(long* env);
- Loads the 32-bit floating-point environment into the
long
pointed to byenv
and returns0
int __float_setenv(const long* env);
- Stores the
long
pointed to byenv
into the 32-bit floating-point environment and returns0
const long __float_defenv;
- Stores an unspecified value corresponding to the implementations default floating-point environment.
All operations described within this section shall operate according to the IEC 559/IEEE 754 standard, and according to Annex G of ISO 9899. The result of the function shall fall within half the Unit of Least Precision which the implementation may support.
It is implementation-defined whether any symbol defined within this section is made available. Any symbol defined within this section is reserved, regardless of whether or not the implementation makes the symbol available.
Feature Test Symbols
The following symbols shall be defined by the implementation as follows, otherwise the symbol shall be undefined. If no particular value is given, then the value of the symbol shall be an unspecified non-zero value that fits in an unsigned 16-bit value.
__feature_test
is defined by the implementation if it supports testing features as defined within this section__feature_int128
is defined by the implementation if it supports Extended Integer Arithmetic on 128-bit integers__feature_float
is defined by the implementation if it supports Floating-point Operations__feature_float128
is defined by the implementation if it supports 128-bit floating-point operations__feature_fenv
is defined by the implemenation if it supports modification and testing of the floating-point enviornment (__float_getenv
/__float_setenv
)__feature_main
is defined by the implementation if it provides a definition of the_Reset
symbol (reguardless of whether the definition is overriden by the program)
It is implementation-defined whether feature testing as defined within this section is supported. Implementations are permitted to define symbols within this section to non-zero values reguardless of whether it support feature testing.
Extensions to this ABI
Space Constrained Environments
In a space constrained environment, it may be infeasible to allocate space for Extended registers. In such environments, it is permissible to use only the first 4 extended registers, or none at all. Implementations should document when this is the case, or may be made available. If extended registers are not used, then the Direct Page register is Caller Saved.
Future Directions
Position Independent Code
The symbol with the name _GLOBAL_OFFSET_TABLE_
is reserved for future use pertaining to position independent code. The symbol _DYNAMIC_
is reserved for future use pertaining to position independent code.
Additional Extended registers
The symbols of form __r
, followed by a decimal positive integer are reserved for additional extended registers.
Any symbol of a form reserved by this section followed by the letters w
, l
, or h
are also reserved.
Address Space Extensions
The 8 most significant bits of any valid pointer value are reserved for use in extensions that provide an extended address space. User code should not rely on any particular value in future versions, except that no function will have an address with the most significant bit set.
Reserved Symbol Glossary
The following is a list of every symbol reserved by this specification.
Reserved Symbols may be specified as user-defineable (IE. Interrupt Handler Functions). If so, restrictions for each symbol are given. The result of defining the symbol may affect generated code. Otherwise, Reserved Symbols may be defined with a prototype presented by this document. If a definition is provided by this document, then compliant code may use the symbol according to it’s definition. Otherwise, compliant code may only reference the symbol by name as a weak symbol to determine whether the symbol exists, except that complaint code may not reference any local symbol form.
Local Symbol Forms
If a symbol is reserved by this ABI, or is the name of a function defined by the C Standard, then any symbol that starts with that name followed by a .
is reserved.
Main Function
The symbol main
is reserved for use by an Implementation provided _Reset
symbol, unless the program defines the _Reset
symbol. Complaint programs may define this symbol as a function with the signature void main(void);
Reserved as Interrupt Handler Functions
These functions are reserved as the name of interrupt handler functions. Complaint Programs may define these symbols according to the requirements prescribed in Interrupt Calling convention:
- __native_cop
- __native_brk
- __native_nmi
- __native_abort
- __native_irq
- __emulation_cop
- __emulation_nmi
- __emulation_abort
- __emulation_irq
- _Reset
Additionally the following symbols are reserved and may not be defined:
- __native_reset
- __emulation_reset
- __emulation_brk
Reserved For Feature Testing
The symbols of either of the following forms are reserved for use with feature testing:
- Any symbol that starts with
__feature_
, - Any that starts with
__featureN_
The following symbol forms are additionally reserved for specific use and will not be defined by this psABI or a future version thereof:
- Any symbol starting with
__feature_impl_
is reserved for implementation-specific use, - Any symbol starting with
__feature_snesdev_
, and the symbol__feature_snesdev
, is reserved for the SNES-Dev Machine Supplicant and SNES-Dev API Specification,
Reserved For Code Generation
Arithmetic Operations
Any symbol that is a valid C identifier and starts with one of the following prefixes, and ends with a decimal integer, is reserved for generating code handling integer and floating-point operations:
__uint_
__int_
__fixed_
__float_
-
__decimal_
- __inc_rn where n is a positive decimal integer
- __dec_rn where n is a positive decimal integer
Atomic Operations
The following symbols are reserved for generating code handling atomic operations:
- __atomic_thread_fence
- __atomic_signal_fence
- _atomic_load_n, where _n is a decimal number of bytes
- _atomic_store_n, where _n is a decimal number of bytes
- _atomic_exchange_n, where _n is a decimal number of bytes
- _atomic_compare_exchange_n, where _n is a decimal number of bytes
- __atomic_test_and_set
- __atomic_clear
Position Independent Code
The following symbols are reserved for future use related to position-independent code:
_GLOBAL_OFFSET_TABLE_
_DYNAMIC_
Misc
The following symbols are reserved for miscellaneous code generation use:
_FnPtrTrampoline
Hardware Floating-Point
The following symbols are reserved for future use related to operating hardware-floating point
Reserved for Register Memory Locations
Any symbol __r
n
, where n is a decimal number is reserved. Any symbol __r
n
w
, __r
n
l
, or __r
n
h
is reserved.
Reserved for Previous Use
The following symbols were previously used by the specification and are reserved:
_InterruptSavedRegisters