Skip to main content

IAR Embedded Workbench for RX 5.20

Examples of using CFI directives

In this section:

The following is a generic example of how to add and use the required CFI directives. The example is not created for the RX microcontroller. To obtain an example specific to the the RX 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

0000

SP + 2

undefined

SAME

CFA - 2

func1: PUSH R1

0002

SP + 4

CFA - 4

MOV R1,#4

0004

CALL func2

0006

POP R0

0008

SP + 2

R0

MOV R1,R0

000A

SAME

RET

Table 120. Code sample with call frame information  


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 trivialNames
Defining 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 trivialCommon

Note

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