1 TRICORE C LANGUAGE

This chapter contains the following sections:

Introduction

Data Types

Keywords

Function Qualifiers

Intrinsic Functions
Minimum and Maximum of (Short) Integers
Fractional Data Type Support
Packed Data Type Support
Interrupt Handling
Insert Single Assembly Instruction
Register Handling
Insert / Extract Bitfields and Bits
Miscellaneous Intrinsic Functions

Pragmas

Predefined Macros

1.1 Introduction

The TASKING TriCore C compiler fully supports the ANSI C standard but adds possibilities to program the special functions of the TriCore.

This chapter contains complete overviews of the following C language extensions of the TASKING TriCore C compiler:

1.2 Data Types

The TASKING TriCore C compiler ctc supports the following data types:

Type Keyword Size
(bit)
Align (bit) Ranges
Bit __bit 8 8 0 or 1
Boolean _Bool 8 8 0 or 1
Character char signed char 8 8 -27 .. 27-1
unsigned char 8 8 0 .. 28-1
Integral short signed short 16 16 -215 .. 215-1
unsigned short 16 16 0 .. 216-1
int signed int long signed long 32 16 -231 .. 231-1
unsigned int unsigned long 32 16 0 .. 232-1
enum 8
16
32
8
16
-27 .. 27-1
-215 .. 215-1
-231 .. 231-1
long long signed
long long
64 32 -263 .. -263-1
unsigned
long long
64 32 0 .. 264-1
Pointer pointer to data pointer to func 32 32 0 .. 232-1
Floating Point float 32 16 -3.402e38 .. -1.175e-38
1.175e-38 .. 3.402e38
double long double 64 32 -1.797e308 .. -2.225e-308
2.225e-308 .. 1.797e308
Fract __sfract 16 16 [-1, 1>
__fract 32 32 [-1, 1>
Accum __laccum 64 64 [-131072,131072>
Packed __packb signed __packb 32 16 4x: -27 .. 27-1
unsigned __packb 32 16 4x: 0 .. 28-1
__packhw signed __packhw 32 16 2x: -215 .. 215-1
unsigned __packhw 32 16 2x: 0 .. 216-1

Table 1-1: Data Types

1.3 Keywords

__a0, __a1, __a8, __a9

The data object is located in a section that is addressable with a sign-extended 16-bit offset from address register A0, A1, A8 or A9 respectively.

__asm()

With the __asm() keyword you can use assembly instructions in the C source and pass C variables as operands to the assembly code.

instruction_template Assembly instructions that may contain parameters from the input list or output list in the form: %parm_nr [.regnum]

%parm_nr[.regnum] Parameter number in the range 0 .. 9. With the optional .regnum you can access an individual register from a register pair or register quad. For example, with register pair d0/d1, .0 selects register d0.

output_param_list [[ "=[&]constraint_char"(C_expression)],...]

input_param_list [[ "constraint_char"(C_expression)],...]

& Says that an output operand is written to before the inputs are read, so this output must not be the same register as any input.

constraint _char Constraint character: the type of register to be used for the C_expression.

C_expression Any C expression. For output parameters it must be an lvalue, that is, something that is legal to have on the left side of an assignment.

register_save_list [["register_name"],...]

register_name Name of the register you want to reserve.

Constraint character Type Operand Remark
a Address register a0 .. a15
d Data register d0 .. d15
e Data register pair e0 .. e7
m Memory variable Stack or memory operand
number Type of operand it is associated with same as %number Indicates that %number and number are the same register.

Table 1-2: Available input/output operand constraints

For more information on __asm, see section 3.6, Using Assembly in the C Source, in Chapter TriCore C Language of the User's Guide.

__at()

With the attribute __at() you can place an object at an absolute address.

__atbit()

If you have defined a 32-bits base variable (int, long) you can declare a single bit of that variable as a bit variable with the keyword __atbit(). The syntax is:

name is the name of an integer variable in which the bit is located. offset (range 0-31) is the bit-offset within the variable.

__circ

The TriCore C compiler supports the __circ keyword for circular buffers.

For more information see section 3.4.1, Circular Buffers, in Chapter TriCore C Language of the User's Guide.

__near
__far

With keyword __near the declared data object will be located in the first 16 kB of a 256 MB block. These parts of memory are directly addressable with the absolute addressing mode.

With keyword __far the data object can be located anywhere in the indirect addressable memory region.

__sfrbit16
__sfrbit32

With the data type qualifiers __sfrbit16 and __sfrbit32 you can declare bit fields in special function registers. These keywords force 16-bit or 32-bit access.

For more information see section 3.4.2, Declare an SFR Bit Field: __sfrbit16 and ___sfrbit32, in Chapter TriCore C Language of the User's Guide.

1.4 Function Qualifiers

__enable_
__bisr_()

During the execution of an interrupt service routine or trap service routine, the system blocks the CPU from taking further interrupt requests. You can immediately re-enable the system to accept interrupt requests:

The function qualifier __bisr_() also re-enables the system to accept interrupt requests. In addition, the current CPU priority number (CCPN) in the interrupt control register is set:

For more information see section 3.9.2, Interrupt and Trap Functions, in Chapter TriCore C Language of the User's Guide.

__indirect

Functions are default called with a single word direct call. However, when you link the application and the target address appears to be out of reach (+/- 16 MB from the callg or jg instruction), the linker generates an error. In this case you can use the __indirect keyword to force the less efficient, two and a half word indirect call to the function:

inline
__noinline

You can use the inline qualifier to tell the compiler to inline the function body instead of calling the function. Use the __noinline qualifier to tell the compiler not to inline the function body.

For more information see section 3.9.1, Inlining Functions: inline, in Chapter TriCore C Language of the User's Guide.

__interrupt()
__interrupt_fast()

You can use the qualifier __interrupt() to declare a function as an interrupt service routine.

The vector_number identifies the entry into the interrupt vector table (0..255). Unlike other interrupt systems, the priority number (PIPN) of the interrupt now being serviced by the CPU identifies the entry into the vector table.

When you define an interrupt service routine with the __interrupt_fast() qualifier, the interrupt handler is directly placed in the interrupt vector table, thereby eliminating the jump code.

For more information see section 3.9.2, Interrupt and Trap Functions, in Chapter TriCore C Language of the User's Guide.

__trap()
__trap_fast()
__syscallfunc()

The definition of a trap service routine is similar to the definition of an interrupt service routine. Trap functions cannot accept arguments and do not return anything:

The argument class identifies the entry into the trap vector table. TriCore defines eight classes of trap functions. Each class has its own trap handler.

When you define a trap service routine with the __trap_fast() qualifier, the trap handler is directly placed in the trap vector table, thereby eliminating the jump code.

A special kind of trap service routine is the system call trap. With a system call the trap service routine of class 6 is called. For the system call trap, the trap identification number (TIN) is taken from the immediate constant specified with the function qualifier __syscallfunc():

The TIN is a value in the range 0 and 255. You can only use __syscallfunc() in the function declaration. A function body is useless, because when you call the function declared with __syscallfunc(), a trap class 6 occurs which calls the corresponding trap service routine.

For more information see section 3.9.2, Interrupt and Trap Functions, in Chapter TriCore C Language of the User's Guide.

__stackparm

The function qualifier __stackparm changes the standard calling convention of a function into a convention where all function arguments are passed via the stack, conforming a so called stack model. This qualifier is only needed for situations where you need to use an indirect call to a function for which you do not have a valid prototype.

1.5 Intrinsic Functions

The TASKING TriCore C compiler recognizes intrinsic functions that serve the following purposes:

All intrinsic functions begin with a double underscore character (__). You can use intrinsic functions as if they were ordinary C functions.

1.5.1 Minium and maximum of (Short) Integers

The next table provides an overview of the intrinsic functions that return the minium or maximum of a signed integer, unsigned integer or short integer.

Intrinsic Function Description
int __min( int,int ) Return minimum of two integers
short __mins( short,short ) Return minimum of two short integers
unsigned int
__minu( unsigned int, unsigned int )
Return minimum of two unsigned integers
int __max( int,int ) Return maximum of two integers
short __maxs( short,short ) Return maximum of two short integers
unsigned int
__maxu( unsigned int, unsigned int )
Return maximum of two unsigned integers

Table 1-3: Intrinsic Functions for obtaining min/max values

1.5.2 Fractional Arithmetic Support

The next table provides an overview of intrinsic functions to convert fractional values. Note that the TASKING TriCore C compiler fully supports the fractional type so normally you should not need these intrinsic functions (except for __mulfractlong). For compatibility reasons the TASKING TriCore C compiler does support these functions.

Conversion of Fractional Values

Intrinsic Function Description
long
__mulfractlong( __fract,long )
Integer part of __fract x long
__sfract
__round16( __fract )
Convert __fract to __sfract
__fract
__getfract( __accum )
Convert __accum to __fract
short
__clssf( __sfract )
Count the consecutive number of bits that have the same value as bit 15 of an __sfract
__sfract
__shasfracts( __sfract,int )
Left/right shift of an __sfract
__fract
__shafracts( __fract,int )
Left/right shift of an __fract
__laccum
__shaaccum( __laccum,int )
Left/right shift of an __laccum

Table 1-4: Intrinsic Functions for Conversion of Fractional Values

1.5.3 Packed Data Type Support

The next table provides an overview of the intrinsic functions for initialization of packed data type.

Initialize Packed Data Types

Intrinsic Function Description
__packb __initpackbl( long ) Initalize __packb with a long integer
__packb __initpackb( int,int,int,int ) Initalize __packb with four integers
__packhw __initpackhwl( long ) Initalize __packhw with a long integer
__packhw __initpackhw( int,int ) Initalize __packhw with two integers

Table 1-5: Intrinsic Functions to Initialize Packed Data Types

Extract Values from Packed Data Types

The next table provides an overview of the intrinsic functions to extract a single byte or halfword from a __packb or __packhw data type.

Intrinsic Function Description
char __extractbyte1( __packb ) Extract first byte from a __packb
char __extractbyte2( __packb ) Extract second byte from a __packb
char __extractbyte3( __packb ) Extract third byte from a __packb
char __extractbyte4( __packb ) Extract fourth byte from a __packb
short __extracthw1( __packhw ) Extract first short from a __packhw
short __extracthw2( __packhw ) Extract second short from a __packhw
char __getbyte1( __packb * ) Extract first byte from a __packb
char __getbyte2( __packb * ) Extract second byte from a __packb
char __getbyte3( __packb * ) Extract third byte from a __packb
char __getbyte4( __packb * ) Extract fourth byte from a __packb
short __gethw1( __packhw * ) Extract first integer from a __packhw
short __gethw2( __packhw * ) Extract short integer from a __packhw

Table 1-6: Intrinsic Functions to Extract Values from Packed Data Types

Insert Values into Packed Data Types

The next table provides an overview of the intrinsic functions to insert a single byte or halfword into a __packb or __packhw data type.

Intrinsic Function Description
__packb __insertbyte1( __packb, char ) Insert char into first byte of a __packb
__packb __insertbyte2( __packb, char ) Insert char into second byte of a __packb
__packb __insertbyte3( __packb, char ) Insert char into third byte of a __packb
__packb __insertbyte4( __packb, char ) Insert char into fourth byte of a __packb
__packhw __inserthw1( __packhw, short ) Insert short into first halfword of a __packhw
__packhw __inserthw2( __packhw, short ) Insert short into second halfword of a __packhw
void __setbyte1( __packb *, char ) Insert first byte into a __packb
void __setbyte2( __packb *, char ) Insert second byte into a __packb
void __setbyte3( __packb *, char ) Insert third byte into a __packb
void __setbyte4( __packb *, char ) Insert fourth byte into a __packb
void __sethw1( __packhw *, short ) Insert first integer into a __packhw
void __sethw2( __packhw *, short ) Insert short integer into a __packhw

Table 1-7: Intrinsic Functions to Insert Values into Packed Data Types

Combine Packed Data Types into a Packed Word

The next table provides an overview of the intrinsic functions to combine the value of packed data types into a packed word. You can combine two __packb (2 x 4 bytes) into a long long or two __packhw (2 x 2 halfwords) into a long long.

The packed word is a double register that is represented by the additional datatype __packw. To access the values in a _packw variable, you can use a union data type: typedef double __packw.

These intrinsics are only supported for the TriCore2 (--is-tricore2).

Intrinsic Function Description
unsigned long long
__transpose_byte( __packb,__packb )
Combine two __packb
unsigned long long
__transpose_hword( __packhw,__packhw )
Combine two __packhw

Table 1-8: Intrinsic Functions to Combine Packed Data Types

Calculate Absolute Values of Packed Data Type Values

The next table provides an overview of the intrinsic functions to calculate the absolute value of packed data type values.

Intrinsic Function Description
__packb __absb( __packb ) Absolute value of __packb
__packhw __absh( __packhw ) Absolute value of __packhw
__sat __packhw
__abssh( __sat __packhw )
Absolute value of __packhw using saturation

Table 1-9: Intrinsic Functions to Calculate Absolute Values

Calculate Minimum Packed Data Type Values

The next table provides an overview of the intrinsic functions to calculate the minimum from two packed data type values.

Intrinsic Function Description
__packb __minb( __packb,__packb ) Minimum of two __packb values
unsigned __packb __minbu( unsigned __packb, unsigned __packb ) Minimum of two unsigned __packb values
__packhw __minh( __packhw,__packhw ) Minimum of two __packhw values
unsigned __packhw __minhu( unsigned __packhw, unsigned __packhw ) Minimum of two unsigned __packhw values

Table 1-10: Intrinsic Functions to Calculate Absolute Values

1.5.4 Interrupt Handling

The next table provides an overview of the intrinsic functions to read or set interrupt handling:.

Intrinsic Function Description
void __enable ( void ) Enable interrupts immediately at function entry
void __disable ( void ) Disable interrupts Only supported for TriCore1.
int __disable_and_save ( void ) Disable interrupts and return previous interrupt state (enabled or disabled). Only supported for TriCore2 (--is-tricore2).
void __restore ( int ) Restore interrupt state. Only supported for TriCore2 (--is-tricore2).
void __bisr ( int ) Set CPU priority number [0..512] and enable interrupts immediately at function entry
void __sysc ( int ) Call a system call function number

Table 1-11: Intrinsic Functions for Interrupt Handling

1.5.5 Insert Single Assembly Instruction

The next table provides an overview of the intrinsic functions that you can use to insert a single assembly instruction.

You can also use inline assembly but these intrinsics provide a shorthand for frequently used assembly instructions.

See section 3.6 , Using Assembly in the C Source: __asm() of the User's Guide

Intrinsic Function Description
void __debug( void ) Insert DEBUG instruction
void __dsync( void ) Insert DSYNC instruction
void __isync( void ) Insert ISYNC instruction
void __svlcx( void ) Insert SVLCX instruction
void __rslcx( void ) Insert RSLCX instruction
void __nop( void ) Insert NOP instruction

Table 1-12: Intrinsic Functions for Inserting Assembly Instructions

1.5.6 Register Handling

Access Control Registers

The next table provides an overview of the intrinsic functions that you can use to acces control registers.

Intrinsic Function Description
int __mfcr( int ) move contents of the addressed core SFR into a data register
void __mtcr ( int,int ) move contents of a data register (second int) to the addressed core SFR (first int)

Table 1-13: Intrinsic Functions for Accessing Control Registers

Perform Register Value Operations

The next table provides an overview of the intrinsic functions that operate on a register and return a value in another register.

Intrinsic Function Description
int __clz ( int ) Count leading zeros in int
int __clo ( int ) Count leading ones in int
int __cls ( int ) Count number of redundant sign bits (all consecutive bits with the same value as bit 31)
int __satb ( int ) Return saturated byte
int __satbu ( int ) Return saturated unsigned byte
int __sath ( int ) Return saturated halfword
int __sathu ( int ) Return saturated unsigned halfword
int __abs ( int ) Return absolute value
int __abss ( int ) Return absolute value with saturation
int __parity ( int ) Return parity

Table 1-14: Intrinsic Functions for Performing Register Value Operations

1.5.7 Insert / Extract Bit-fields and Bits

Insert / Extract Bit-fields

The next table provides an overview of the intrinsic functions to insert or extract a bit-field.

Intrinsic Function Description
int __extr ( int value,
int pos,int width )
Extract a bit-field (bit pos to bit pos+width) from value
unsigned int __extru ( int
value,int pos,int width )
Same as __extr() but return bit-field as unsigned integer
int __insert ( int src,int
trg, int pos,int width )
Extract bit-field (bit pos to bit pos+width) from src and insert it in trg.
int _ins( int trg, int trgbit,
int src, int srcbit )
Return trg but replace trgbit by srcbit in src.
int _insn(int trg, int trgbit,
int src, int srcbit )
Return trg but replace trgbit by inverse of srcbit in src.

Table 1-15: Intrinsic Functions to Insert / Extract Bit-fields

Atomic Load-Modify-Store

With the next intrinsic function you can peform atomic Load-Modify-Store of a bit-field from an integer value. This function uses the IMASK and LDMST instruction. The intrinsic writes the number of bits of an integer value at a certain address location in memory with a bitoffset. The number of bits must be a constant value.

Intrinsic Function
void __imaskldmst(int* address,int value,int bitoffset,int bits)

Store a single bit

With the intrinsic macro __putbit() you can store a single bit atomicly in memory at a specified bit offset. The bit at offset 0 in value is stored at an address location in memory with a bitoffset.

This intrinsic is implemented as a macro definition which uses the _imaskldmst() intrinsic:

Intrinsic Macro
void __putbit( int value, int* address, int bitoffset )

Load a single bit

With the intrinsic macro __getbit() you can load a single bit from memory at a specified bit offset. A bit value is loaded from an address location in memory with a bitoffset and returned as an unsigned integer value.

This intrinsic is implemented as a macro definition which uses the __extru() intrinsic function:

Intrinsic Macro
unsigned integer __getbit( int* address, int bitoffset )

1.5.8 Miscellaneous Intrinsic Functions

Multiply and Scale Back

The next intrinsic multiplies two 32-bit numbers to an intermediate 64-bit result, and scales back the result to 32 bits. To scale back the result, 32 bits are extracted from the intermediate 64-bit result: bit 63-offset to bit 31-offset.

Intrinsic Function
int __mulsc( int a, int b, int offset )

Swap Mask

The next intrinsic exchanges the values of value and memory, but only those bits that are allowed by mask. Before the __swapmsk instruction is generated, the parameters value and mask are moved into a double register.

This intrinsic is only supported for the TriCore2 (--is-tricore2).

Intrinsic Function
void __swapmsk ( int value, int mask, int * memory )

Initialize Circular Pointer

With the next intrinsic you can initialize a circular pointer with a dynamically allocated buffer at run-time.

Intrinsic Function
__circ void * __initcirc( void * buf, unsigned short bufsize,
unsigned short byteindex )

See also Section 3.4.1 , Circular Buffers, in Chapter TriCore C Language of the User's Guide.

1.6 Pragmas

Pragmas are keywords in the C source that control the behavior of the compiler. Pragmas overrule compiler options and keywords. The syntax is:

The compiler recognizes the following pragmas, other pragmas are ignored.

Pragma name Description
align {n|restore} Specifies object alignment
clear
noclear
Specifies 'clearing' of non-initialized static/public variables
default_a0_size value Threshold for '__a0' allocation
default_near_size value Threshold for '__near' allocation
inline
noinline
smartinline
Specifies function inlining
optimize flags
endoptimize
Controls compiler optimizations
pack {2|0} Specifies packing of structures
section type[=]"name " Changes section names
section code_init
section data_overlay
At startup copy code to RAM
Allow overlaying data sections
source
nosource
Specifies which C source lines must be shown in assembly output
switch {auto|jumptab|
linear|lookup|restore}
Specifies switch statement

Table 1-16: Pragmas

For more information see section 3.7, Pragmas to Control the Compiler, in Chapter TriCore C Language of the User's Guide.

1.7 Predefined Macros

In addition to the predefined macros required by the ISO C standard, the TASKING TriCore C compiler supports the predefined macros as defined in Table 1-17. The macros are useful to make conditional C code.

Macro Description
__DOUBLE_FP__ Defined when you do not use compiler option -F (Treat double as float)
__SINGLE_FP__ Defined when you use compiler option -F (Treat double as float)
__FPU__ Defined when you use compiler option --fpu-present (Use hardware floating point instructions)
__CTC__ Identifies the compiler. You can use this symbol to flag parts of the source which must be recognized by the ctc compiler only. It expands to the version number of the compiler.
__TASKING__ Identifies the compiler as the TASKING TriCore compiler. It expands to 1.
__DSPC__ Indicates conformation to the DSP-C standard. It expands to 1.
__DSPC_VERSION__ Expands to the decimal constant 200001L.

Table 1-17: Predefined macros


Copyright © 2003 Altium BV