SPRUI04F july 2015 – april 2023
Define a C Callable Procedure
label .cproc [argument1 [, argument2 , …]]
.endproc
Use the .cproc/.endproc directive pair to delimit a section of your code that you want the assembly optimizer to optimize and treat as a C/C++ callable function. This section is called a procedure. The .cproc directive is similar to the .proc directive in that you use .cproc at the beginning of a section and .endproc at the end of a section. In this way, you can set off sections of your assembly code that you want to be optimized, like functions. The directives must be used in pairs; do not use .cproc without the corresponding .endproc. Specify a label with the .cproc directive. You can have multiple procedures in a linear assembly file.
The .cproc directive differs from the .proc directive in that the compiler treats the .cproc region as a C/C++ callable function. The assembly optimizer performs some operations automatically in a .cproc region in order to make the function conform to the C/C++ calling conventions and to C/C++ register usage conventions.
These operations include the following:
For more information, see Section 8.3 and Section 8.4.
Use the optional argument to represent function parameters. The argument entries are very similar to parameters declared in a C/C++ function. The arguments to the .cproc directive can be of the following types:
frame .cproc arg1
The assembly optimizer either allocates arg1 to A4, or arg1 is allocated to a different register (such as B7) and an MV A4, B7 is automatically generated.
For example, the .cproc defined as follows:
_fcn: .cproc arg1, arg2hi:arg2lo, arg3, B6, arg5, B9:B8
...
.return res
...
.endproc
corresponds to a C function declared as:
int fcn(int arg1, long arg2, int arg3, int arg4, int arg5, long arg6);
In this example, the fourth argument of .cproc is register B6. This is allowed since the fourth argument in the C/C++ calling conventions is passed in B6. The sixth argument of .cproc is the actual register pair B9:B8. This is allowed since the sixth argument in the C/C++ calling conventions is passed in B8 or B9:B8 for longs.
If you are calling a procedure from C++ source, you must use the appropriate linkname for the procedure label. Otherwise, you can force C naming conventions by using the extern C declaration. See Section 7.12 and Section 8.6 for more information.
When .endproc is used with a .cproc directive, it cannot have arguments. The live out set for a .cproc region is determined by any .return directives that appear in the .cproc region. (A value is live out if it has been defined before or within the procedure and is used as an output from the procedure.) Returning a value from a .cproc region is handled by the .return directive. The return branch is automatically generated in a .cproc region. See the .return topic for more information.
Only code within procedures is optimized. The assembly optimizer copies any code that is outside of procedures to the output file and does not modify it. See Section 5.4.1 for a list of instruction types that cannot appear in a .cproc region.
Here is an example in which .cproc and .endproc are used:
_if_then: .cproc a, cword, mask, theta
.reg cond, if, ai, sum, cntr
MVK 32,cntr ; cntr = 32
ZERO sum ; sum = 0
LOOP:
AND cword,mask,cond ; cond = codeword & mask
[cond] MVK 1,cond ; !(!(cond))
CMPEQ theta,cond,if ; (theta == !(!(cond)))
LDH *a++,ai ; a[i]
[if] ADD sum,ai,sum ; sum += a[i]
[!if] SUB sum,ai,sum ; sum -= a[i]
SHL mask,1,mask ; mask = mask << 1
[cntr] ADD -1,cntr,cntr ; decrement counter
[cntr] B LOOP ; for LOOP
.return sum
.endproc