C55x C and Assembly Language Mixed Programming
[Copy link]
1 Register rules
In the C environment, there are strict rules for the use of special registers for special operations. Embedding assembly programs in C programs needs to follow these rules, so DSP programmers must understand the register rules.
The register rules specify how the compiler uses registers and how to save values when calling functions.
The register rules stipulate that registers used when calling functions must be saved in advance. This work is partially completed by the parent function. Registers that are not saved by the parent function but are used by the child function are saved by the child function.
2 Function structure and calling rules
2.1. How the parent function calls other functions
(1) Put the parameters to be passed to the child function into registers or stacks.
If the parameters of the child function are declared with ellipsis (indicating that the number of parameters is variable), the last explicitly declared parameter is passed to the stack first, and then the other parameters are passed to the stack. The stack address will be used as an index to access other undeclared parameters.
The parameters declared before the last explicitly declared parameter follow the following rules:
The compiler usually classifies the parameters to be passed first, and then puts the parameters into registers according to type. There are three types of parameters used by the compiler:
data pointers (int *, long *, etc.)
16-bit data (char, short, int)
32-bit data (long, float, double, function pointer)
Structures of double word length (32 bits) or less are treated as 32-bit data parameters and passed through registers.
If the length of the structure is greater than 32 bits, the compiler passes the address of the structure as a data pointer.
Parameters are assigned to registers in the order in which they are listed in the function declaration. The type of register in which the parameters are placed is determined by the type of the parameter. If the number of parameters exceeds the number of available registers, the excess parameters are pushed onto the stack.
The parameters placed on the stack are processed as follows: First, the stack is adjusted to an even boundary; then, each parameter is arranged on the stack according to the corresponding parameter type.
(2) The child function saves all entry save registers (T2, T3, AR5~AR7). The parent function must save the values of other registers that will be used after the call by pushing them onto the stack.
(3) The parent function calls the child function.
(4) The parent function collects the return value.
Short data, long data and data pointer are returned in T0, AC0 and (X)AR0 respectively. If the child function returns a structure, the parent function allocates space of the corresponding size for the structure in the local stack.
2.2. Response of the called function (child function)
(1) The called function allocates sufficient storage space for local variables, temporary storage space and parameters that the function may call. This work is completed at the beginning of the function call.
(2) If the child function modifies some entry-level save registers (T2, T3, AR5~AR7), these values must be pushed into the stack or stored in an unused register. The called function can modify other registers without saving the values in them.
(3) If the parameter of the child function is a structure, it receives a pointer to the structure. If the structure needs to be written in the called function, it needs to be copied to the local space. If no write operation is performed, the structure can be directly accessed through the pointer.
(4) The child function executes the code.
(5) If the child function returns a value, it places the value according to the following rules:
short integer data value is returned to T0
long integer data value is returned to AC0
data pointer value is returned to (X)AR0
If the child function returns a structure, the parent function will allocate storage space for the structure and pass a pointer to this space to (X)AR0. To return this structure, the called function only needs to copy the structure to the storage module pointed to by this pointer.
(6) The child function restores all registers saved in step 2.
(7) The child function restores the values stored in the stack to their original locations.
(8) The function returns.
3 Interface between C and assembly language
The main methods of mixing C code and assembly language code are:
using several independent assembly code modules and linking them with the compiled C module, which is the most common method.
Using assembly language variables and constants in C source code.
Embedding assembly language programs directly into C source code.
Using intrinsic functions in C source code to directly call assembly language statements.
|