Examples of using CFI directives
The following is a generic example of how to add and use the required CFI directives. The example is not created for the RL78 microcontroller. To obtain an example specific to the the RL78 microcontroller, generate assembler output when you compile a C source file.
Consider a generic processor with a stack pointer SP, and two registers R0 and R1. Register R0 is used as a scratch register—the register may be destroyed by a function call—whereas register R1 must be restored after the function call. To simplify, all instructions, registers, and addresses are assumed to have a width of 16 bits.
Consider the following short code example with the corresponding call frame information. At entry, assume that the stack contains a 16-bit return address. The stack grows from high addresses toward zero. The CFA denotes the top of the call frame, in other words, the value of the stack pointer after returning from the function.
Address | CFA | R0 | R1 | RET | Assembler code |
|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
| ||
|
| ||||
|
| ||||
|
|
|
| ||
|
|
|
Each row describes the state of the tracked resources before the execution of the instruction. As an example, for the MOV R1,R0 instruction the original value of the R1 register is located in the R0 register and the top of the function frame (the CFA column) is SP + 2. The row at address 0000 is the initial row and the result of the calling convention used for the function.
The RET column is the return address column—that is, the location of the return address. The value of R0 is undefined because it does not need to be restored on exit from the function. The R1 column has SAME in the initial row to indicate that the value of the R1 register will be restored to the same value it already has.
Defining the names block
The names block for the small example above would be:
cfi names trivialNames
cfi resource SP:16, R0:16, R1:16
cfi stackframe CFA SP DATA
; The virtual resource for the return address column.
cfi virtualresource RET:16
cfi endnames trivialNamesDefining the common block
The common block for the simple example above would be:
cfi common trivialCommon using trivialNames
cfi returnaddress RET DATA
cfi CFA SP + 2
cfi R0 undefined
cfi R1 samevalue
; Offset -2 from top of frame.
cfi RET frame(CFA,-2)
cfi endcommon trivialCommonNote
SP cannot be changed using a CFI directive as it is the resource associated with CFA.
Annotating your source code within a data block
You should place the CFI directives at the point where the call frame information has changed, in other words, immediately after the instruction that changes the call frame information.
Continuing the simple example, the data block would be:
rseg CODE:CODE
cfi block func1block using trivialCommon
cfi function func1
func1 push r1
cfi CFA SP + 4
cfi R1 frame(CFA,-4)
mov r1,#4
call func2
pop r0
cfi R1 R0
cfi CFA SP + 2
mov r1,r0
cfi R1 samevalue
ret
cfi endblock func1block