7 RUN-TIME ENVIRONMENT

This chapter contains the following sections:

Startup Code
Register Usage
Stack
Heap
Floating Point Arithmetic
Special Floating Point Values
Trapping Floating Point Exceptions
Floating Point Trap Handling API

7.1 Startup Code

When linking your C modules with the library, you automatically link the object module, containing the C startup code. This module is called cstart.obj and is present in every C library.

Because this module specifies the run-time environment of your TriCore C application, you might want to edit it to match your needs. Therefore, this module is delivered in source in the file cstart.asm in the src subdirectory of the lib directory. Typically, you will copy the template startup file to your own directory and edit it. The startup code contains equates to tune the startup code. The invocation (using the cctri control program) is:

In the C startup code an absolute code section is defined for setting up the power on vector and the TriCore C environment. The power-on vector contains a definition of the the _START label. This global label should not be removed, since the C compiler referres to it. It is also used as the default start address of the application.

In the file cstart.asm the actual location of several special function registers is required. These addresses are specified in the regcpu_name.def SFR system include files. You can include such a file with the assembler option -Ccpu_name. In EDE the appropriate file is included when you have selected a CPU type. If you do not specify an SFR file, the default SFR regtc10gp.def file is included.

The stack size is defined in the locator control file (tri.i in directory etc) with the macros USTACK and ISTACK which results in sections called ustack and istack. See Stack for detailed information on the stack.

The heap is defined in the description file with the keyword heap, which results in as section called heap. See section 7.4 Heap for detailed information on heap management.

The startup code takes care of clearing global variables and initializing C variables residing in RAM. The startup code copies the initial values of initialized C variables from ROM to RAM, using a locator generated table (also known as the 'copy table') and a run-time library function _c_init.

When everything described above has been executed, your C application is called, using the global label main, which has been generated by ctri for the C function main().

When the C application 'returns', which is not likely to happen in an embedded environment, the program ends with a DEBUG16 instruction, at the assembly label _exit. When using a debugger, it can be useful to set a breakpoint on this label to indicate that the program has reached the end, or that the library function exit() has been called.

To control cstart.asm from within EDE, you first have to add cstart.asm to your project:

Select the Project | Configure Selected CPU... menu item and activate the Cstart tab. Enable the Automatically Add cstart.asm check box and click OK.

The file cstart.asm is added to your project. Now you can specify all your startup settings in the Startup Code tab of the Configure Selected CPU dialog:

Select the Project | Configure Selected CPU... menu item.

You can specify CPU settings in the same dialog:

Select the Project | Configure Bus... menu and select the appropriate bus configuration settings. EDE automatically defines macros according to the selected settings.

A number of other macro preprocessor symbols are used. These can be enabled or disabled using the assembler command line option -D with the following syntax:

In the startup file the following macro preprocessor symbols are used:

Define Description
External Boot Memory Configuration (BOOTCFG)
_BOOTCFG_ADDRC Address generation value
_BOOTCFG_AGEN Read access wait-states value
_BOOTCFG_BCGEN Address Cycles value
_BOOTCFG_CFG Variable wait-state insertion value
_BOOTCFG_CMULT Extended address setup value
_BOOTCFG_SETUP Active /WAIT level value
_BOOTCFG_WAIT Byte control signal timing mode value
_BOOTCFG_WAITINV Wait cycle multiplier value
_BOOTCFG_WAITRDC Boot Memory Data Width value
Memory Control (PMUCON0/DMUCON)
_PMUCON0_CCBYP Code cache bypass value
_PMUCON0_CCSIZ Code cache size value
_DMUCON_DCAON If defined, Enable data cache
Startup
_NO_BTV_INIT If define, Base Address of Trap Vector Table is not initialized with trap table start address (trap_tab).
_NO_BIV_INIT If defined, Base Address of Interrupt Vector Table is not initialized with interrupt table start address (_lc_u_int_tab).
_NO_ISP_INIT If defined, Interrupt Stack Pointer is not initialized with end address of interrupt stack (_lc_ue_istack).
_NO_USP_INIT If defined, User Stack Pointer is not initialized with end address of user stack (_lc_ue_istack).
_NO_PCX_RESET If defined, the Previous Context is not explicitly cleared.
_NO_PSW_RESET If defined, the Call Depth Counter is not explicitly cleared.
_NO_A0A1_ADDRESSING If defined, global address register A0/A1 is not initialized with start address of the _a0/_a1 addressable area (_lc_gb_a0/1).
_NO_A8A9_ADDRESSING If defined, global address register A8/A9 is not initialized with start address of the _a8/_a9 addressable area (_lc_gb_a8/9).
_NO_CSA_INIT If defined, Context Save Area lists are not initialized.
_NO_WATCHDOG_INIT If defined, Watchdog timer disabled.
_NO_BUS_CONF If defined, bus configuration registers are not initialized.
_NO_C_INIT If defined, C variables are not initialized.
_NO_ARG_INIT If defined, disable initialization of argc and argv[].
_NO_EXIT If defined, C library function exit() or abort() not supported.
Miscellaneous
_CALL_INIT Can be set to a function to be called before main. This function cannot have a return or arguments. This function can be used, for example, to initialize the serial port before main is called. This is useful for building programs without making any modifications to the original source.
_CALL_ENDINIT Can be set to a function to be called before the ENDINIT instruction is executed. Like the CALLINIT function, it cannot not have a return value or arguments.
CPU functional bypasses
_TC112_XXX If defined, TC112 CPU functional defect XXX is bypassed and/or checked.
_TC113_XXX If defined, TC113 CPU functional defect XXX is bypassed and/or checked. See appendix C CPU functional Problems CPU Functional Problems for a complete list of these macros.

Table 7-1: Defines used in cstart.src

The following table shows the locator labels used in the startup code.

Define Description
_START start label, mentioned in description file (tri.dsc)
_c_init label copy table init function
main start label user C program
exit start label of exit() function
_exit exit() function jumps to this place
_CALL_ENDINIT label called before ENDINIT
_CALL_INIT _CALL_INIT label called before main()
_lc_gb_a0 locator label start of A0 addressable area
_lc_gb_a1 locator label start of A1 addressable area
_lc_gb_a8 locator label start of A8 addressable area
_lc_gb_a9 locator label start of A9 addressable area
_lc_u_int_tab locator label interrupt table
_lc_ub_csa locator label context save area begin
_lc_ue_csa locator label context save area end
_lc_ue_istack locator label interrupt stack end
_lc_ue_ustack locator label user stack end

Table 7-2: Locator labels used in startup code

7.2 Register Usage

ctri will try to use the available registers as efficient as possible. The compiler uses a flexible register allocation scheme, which implies that any change to the C code may result in a different register usage.

The TriCore register file consists of 16 data registers and 16 address registers, which are 32 bits wide. The contents of registers D8-D15 and A10-A15 are saved by the CALL instruction and restored by the RET instruction. As a result, these registers (with the exception of the link register A11) can be used in a function without the need to save and restore their original contents. The registers D0-D7 and A2-A7 are considered "scratch": their contents is undefined after a function call. The "global registers" A0-A1 and A8-A9 are not changed by a function call or context switch.

For C function return types, the following registers are used:

Return type Register Description
char D2 return register
short D2
int/ long / float D2
double D2/D3 (most significant part in D3)
pointer A2 return register

Table 7-3: C function return types

Structures and unions of up to 8 bytes in size are returned in registers D2/D3. Larger structures or unions are returned on the stack. The address of this return area is passed as an implicit first argument in A4.

The following table summarize the register usage conventions used by ctri:

Register Usage Register Usage
D0 scratch A0 global
D1 scratch A1 global
D2 return register for arithmetic types A2 return register for pointers
D3 most significant part of 64 bit result A3 scratch
D4 parameter A4 parameter
D5 parameter A5 parameter
D6 parameter A6 parameter
D7 parameter A7 parameter
D8 saved register A8 global
D9 saved register A9 global
D10 saved register A10 stack pointer
D11 saved register A11 link register
D12 saved register A12 saved register
D13 saved register A13 saved register
D14 saved register A14 saved register
D15 saved register, implicit register A15 saved register, implicit pointer

Table 7-4: Register usage

7.3 Stack

The stack is used for local automatic variables, function parameters and saved registers.

The following diagram show the structure of a stack frame.

Figure 7-1: Stack diagram

The stack size is defined in the locator control file (tri.i in directory etc) with the macro USTACK and istack, which results in sections called ustack and istack.

The locator defined label _lc_ue_ustack refers to the top of the user stack area and is used in the file cstart.asm to initialize the user stack pointer register (SP). The locator defined label _lc_ue_istack refers to the top of the interrupt stack area and is used in the file cstart.asm to initialize the interrupt stack pointer register (ISP)

As long as the user program does not change the IS bit in the program status word (PSW), only the user stack is used. Refer to the TriCore Architecture (v1.3) Manual for the implications of an IS bit change.

7.4 Heap

The heap is only needed when dynamic memory management library functions are used: malloc(), calloc(), free() and realloc(). The heap is a reserved area in memory. Only if you use one of the memory allocation functions listed above, the locator automatically allocates a heap, as specified in the locator description file with the keyword heap.

A special section called heap is used for the allocation of the heap area. The size of the heap is defined in the locator control file (tri.i in directory etc) with the macro HEAP, which results in a section called heap. The locator defined labels _lc_bh and _lc_eh (begin and end of heap) are used by the library function sbrk(), which is called by malloc() when memory is needed from the heap.

The special heap section is only allocated when its locator labels are used in the program.

7.5 Floating Point Arithmetic

Floating point arithmetic support for the compiler ctri is included in the software as a separate set of libraries or in the hardware when available (only single precision). During linking you have to specify the desired floating point library after the C library. The libraries are reentrant, and only use temporary program stack memory.

To ensure portability of floating point arithmetic, floating point arithmetic for the compiler ctri has been implemented complying to the IEEE-754 standard for floating point arithmetic. See the IEEE Standard Binary for Floating-Point Arithmetic document [IEEE Computer Society, 1985] for more details on the floating point arithmetic definitions. This document is referred to as IEEE-754 in this manual.

The compiler ctri supports both single and double precision floating point operations using the ANSI C types float and double respectively. To optimize for speed, also a non-trapping library is included. For the library names, see section 6.3, C Libraries.

It is possible to intercept floating point exceptional cases and, if desired, handle them with an application defined exception handler. The intercepting of floating point exceptions is referred to as 'trapping'. Examples of how to install a trap handler are included.

7.5.1 Compliance to IEEE-754

The level to which the floating point implementation complies to the IEEE-754 standard, depends on the choosen configuration.

All floating point calculations are executed using the 'round to nearest (even)' rounding mode, since this is required by ANSI-C 89. This is conform IEEE-754. Because there are no double precision floating point hardware instructions, an emulating library is always needed for double precision calculation.

When the use of hardware FPU instructions is choosen (-FPU), the available hardware instructions for single precision floating point will be used either in the compiler or in one of the libraries. For double precision floating point calculations the choosen floating point emulaton library will be used. When no hardware FPU instructions are allowed, all floating point operations will be used from the choosen floating point emulaton library.

In EDE you can specify to use the single precision floating point hardware: Select the Project | C Compiler Options | Project Options... menu item and enable the Use hardware single precision floating point instructions check box in the Misc tab.

This option is only available (and relevant) when you enable the FPU present (on user defined CPU) check box on the CPU tab in the Project | Processor options... menu item.

-FPU in Chapter 4, Compiler Use.

Compliance with IEEE-754: TriCore hardware FPU instructions

The following implementation issues for the single precision hardware instructions (optionally implemented on the TriCore chip), are important:

Compliance with IEEE-754: Trapping emulation library

The following implementation issues for the trapping floating point library are important:

Compliance with IEEE-754: Hand-optimized non-trapping emulation library

The following implementation issues for the non-trapping floating point library are important:

7.5.2 Special Floating Point Values

Below is a list of special, IEEE-754 defined, floating point values as they can occur during run-time.

Special value Sign Exponent Mantissa
+0.0 (Positive Zero) 0 all zeros all zeros
-0.0 (Negative Zero) 1 all zeros all zeros
+INF (Positive Infinite) 0 all ones all zeros
-INF (Negative Infinite) 1 all ones all zeros
NaN (Not a number) 0 all ones not all zeros

Table 7-5: Special floating point values

7.5.3 Trapping Floating Point Exceptions

Four floating point run-time libraries are delivered for every memory model:

By specifying the -fptrap option to the control program cctri, the trapping type floating point library is linked into your application. By specifying the -FPU option to the control program cctri, a floating point library with single precision FPU instructions is linked into your application. If these options are not specified, the floating point library without trapping mechanism and without FPU instructions is used.

In EDE you can specify to use the trapping type floating point library as follows: Select the Project | Linker/Locator Options... menu and enable the Use trapping floating point library check box in the Linker tab.

IEEE-754 Trap Handler

In the IEEE-754 standard a trap handler is defined, which is invoked on (specified) exceptional events, passing along much information about the event. To install your own trap handler, use the library call _fp_install_trap_handler. When installing your own exception handler, you must select on which types of exceptions you want to have your handler invoked, using the function call _fp_set_exception_mask. See below for more details on the floating point library exception handling function interface.

SIGFPE Signal Handler

In ANSI-C the regular approach of dealing with floating point exceptions is by installing a so-called signal handler by means of the ANSI-C library call signal. If such a handler is installed, floating point exceptions cause this handler to be invoked. To have the signal handler for the SIGFPE signal actually become operational with the provided floating point libraries, a (very) basic version of the IEEE-754 exception handler must be installed (see example below) which will raise the desired signal by means of the ANSI-C library function call raise. For this to be achieved, the function call _fp_install_trap_handler is present. When installing your own exception handler, you will have to select on which types of exceptions you want to receive a signal, using the function call _fp_set_exception_mask. See further below for more details on the floating point library exception handling function interface.

There is no way to specify any information about the context or nature of the exception to the signal handler. Just that a floating point exception occurred can be detected. See therefor the IEEE-754 trap handler discussion above if you want more control over floating point results.

Example:

7.5.4 Floating Point Trap Handling API

For purposes of dealing with floating point arithmetic exceptions, the following library calls are available:

A pair of functions to get or set the mask which controls which type of floating point arithmetic exceptions are either ignored or passed on to the trap handler. The types of possible exception flag bits are defined as:

while,

is the OR of all possible flags. See below for an explanation of each flag.

A pair of functions for examining or presetting the status word containing the accumulation of all floating point exception types which occurred so far. See the possible exception type flags above.

This function call expects a pointer to a function, which in turn expects a pointer to a structure of type _fp_exception_info_t. The members of _fp_exception_info_t are:

The member d is not present when specifying the -F option to the C compiler.

The following table lists all the exception code flags, the corresponding error description and result:

Error Description Exception Flag Default Result with Trapping
Invalid Operation EFINVOP NaN
Division by zero EFDIVZ +INF or -INF
Overflow EFOVFL +INF or -INF
Underflow EFUNFL zero
Inexact EFINEXT undefined
INF Infinite which is the largest absolute floating point number,
which is always: -INF < every finite number < +INF
NAN Not a Number, a symbolic entity encoded in floating point format.

Table 7-6: Exception Type Flag Codes

To ensure all exception types are specified, you can specify EFALL to a function, which is the binary OR of all above enlisted flags.


Copyright © 2002 Altium BV