2.9. Built-In Functions and Intrinsics

The C29x compiler has many intrinsic functions (also called “built-in functions”) that provide built-in access from C/C++ to assembly instructions or sequences of instructions. All intrinsic functions begin with the prefix __builtin_c29_.

Note

This page describes only some of the intrinsics that are available. For a list of builtin intrinsics supported by the C29x compiler, see the C2000 C29x CPU and Instruction Set User’s Guide, which is available through your TI Field Application Engineer. Search for __builtin in that guide.

Note that you can use the __has_builtin function-like preprocessor macro to test for the existence of a built-in function. This, and other preprocessor macros are extensions provided by Clang. It evaluates to 1 if the function is supported or 0 if not. It can be used like this:

#if __has_builtin(__builtin_c29_fast_strlen)
    mystrlen __builtin_c29_fast_strlen( mystr );
#else
    abort();
#endif

See the Clang Language Extensions section of the Clang documentation for details and additional macros and extensions.

2.9.1. Interrupt Control Intrinsics

Table 2.18 Interrupt Control Intrinsics

Intrinsic syntax

Description

unsigned int
__builtin_c29_disable_INT()

Disable INT interrupts

unsigned int
__builtin_c29_enable_INT()

Enable INT interrupts

void __builtin_c29_restore_INT(
unsigned int ui0 )

Restore previous INT interrupt enable/disable setting as stored in ui0

void __builtin_c29_atomic_enter()

Interrupts are blocked until ATOMIC counter reaches 0 or ATOMIC_END instruction is executed. NMI interrupts are not blocked.

void __builtin_c29_atomic_mem_enter()

Interrupts are blocked until ATOMIC counter reaches 0 or ATOMIC_END instruction is executed. NMI interrupts not blocked. Generate side band strobes to indicate that this is a window of mutually exclusive (MUTEX) memory operations.

void __builtin_c29_atomic_leave()

Clears ATOMIC counter set by __builtin_c29_atomic_enter() or __builtin_c29_atomic_mem_enter(.)

2.9.2. String and Memory Intrinsics

Table 2.19 String and Memory Intrinsics

Intrinsic syntax

Description

void __builtin_c29_fast_memcpy(
void *dest,
const void * src,
size_t numBytes )

Optimized instruction sequence for memcpy() function. This has the same signature as its associated C library function.

int __builtin_c29_fast_strcmp(
const char* str1,
const char* str2 )

Optimized instruction sequence for strcmp() function. This has the same signature as its associated C library function. It requires 4 bytes of post-padding.

size_t __builtin_c29_fast_strlen(
const char* str )

Optimized instruction sequence for strlen() function. This has the same signature as its associated C library function. It requires up to 60 bytes of post-padding.

2.9.3. Data and Tracking Intrinsics

Table 2.20 Data and Tracking Intrinsics

Intrinsic syntax

Description

void __builtin_c29_datalog_tag(
auto tag_id)
Tags a datalog entry with an identifier value (0-0x7fff). This is paired with a c29clang-tidy check “c29-datalog-intrinsics” to ensure each write entry has an associated tag.
void __builtin_c29_datalog_write(
/* arithmetic type */ value )
Writes a scalar value to datalog.

2.9.4. Arithmetic Intrinsics

The C2000 C29x CPU and Instruction Set User’s Guide, which is available through your TI Field Application Engineer, describes the arithmetic instructions available for C29x processors. For each instruction that has a corresponding intrinsic function that can be called from C/C++, the syntax is provided. The arithmetic intrinsics include intrinsics to perform:

  • Integer addition, subtraction, multiplication, and division

  • Absolute and negative value operations

  • Integer comparisons

  • Increment/decrement operations

  • Logarithmic operations

  • Trigonometric operations

  • Square root and inverse power operations

  • Bit counting and searching

  • Bitwise AND, ANDOR, OR, and XOR operations

  • Left and right shifts

  • Cyclic Redundancy Checks (CRC)

// Increments value and applies modulo (circular increment)
// result = (value + 1) % modulo
unsigned int __builtin_c29_inccirc(unsigned int value, unsigned int modulo);

// Decrements value and applies modulo (circular decrement)
// result = (value - 1) % modulo
unsigned int __builtin_c29_deccirc(unsigned int value, unsigned int modulo);

// Logical shift right and mask operation
// result = (value >> shift_amount) & bit_mask
int __builtin_c29_lsrand(int value, unsigned int shift_amount, unsigned int bit_mask);

// Logical shift right with sign extension to 8 bits
// result = (int)(int8_t)(value >> shift_amount)
int __builtin_c29_lsrsext_8(int value, unsigned int shift_amount);

// Logical shift right with sign extension to 16 bits
// result = (int)(int16_t)(value >> shift_amount)
int __builtin_c29_lsrsext_16(int value, unsigned int shift_amount);

Note

The following intrinsics has two usages:

  1. Part of the calculation the C library trigonometric function atan2f(), using the float result. However, prefer __builtin_c29_fast_atan2f for this purpose.

  2. Splits a graph into 16 segments and returns the segment in which a given (*x_component, *y_component) coordinate belongs.

// Determines per-unit segment location (0-15) and base angle offset while normalizing coordinates for atan2pu calculations
// - segment: OUTPUT - receives per-unit segment location information (0-15)
// - y_component: INPUT/OUTPUT - y-coordinate, normalized during processing
// - x_component: INPUT/OUTPUT - x-coordinate, normalized during processing
// Returns a base angle offset (0.0, 0.25, 0.5, -0.25, -0.5) for atan2pu calculations
float __builtin_c29_quadf32(unsigned int * segment, float * y_component, float * x_component);

Separate versions of the intrinsics operate on various registers and datatypes and/or perform variants such as signed or unsigned integer saturation.

For division operations, the following intrinsics return the quotient and remainder in *quot* and *rem. These functions fall into the following variant categories:

  • Unsigned division: div

  • Traditional (truncated) signed division: tdiv

  • Euclidean signed division: ediv

  • Modulo (floored) signed division: mdiv

void __builtin_c29_div_u32_u32(unsigned *quot, unsigned *rem, unsigned a, unsigned b)
void __builtin_c29_div_u64_u32(unsigned long long *quot, unsigned *rem,
                               unsigned long long a, unsigned b)
void __builtin_c29_div_u64_u64(unsigned long long *quot, unsigned long long *rem,
                               unsigned long long a, unsigned long long b)

void __builtin_c29_tdiv_s32_u32(int *quot, int *rem, int a, unsigned b)
void __builtin_c29_tdiv_s32_s32(int *quot, int *rem, int a, int b)
void __builtin_c29_tdiv_s64_u32(long long *quot, int *rem, long long a, unsigned b)
void __builtin_c29_tdiv_s64_s32(long long *quot, int *rem, long long a, int b)
void __builtin_c29_tdiv_s64_s64(long long *quot, long long *rem, long long a, long long b)

void __builtin_c29_ediv_s64_s32(long long *quot, int *rem, long long a, int b)
void __builtin_c29_ediv_s32_s32(int *quot, int *rem, int a, int b)
void __builtin_c29_ediv_s64_s64(long long *quot, long long *rem, long long a, long long b)

void __builtin_c29_mdiv_s64_s32(long long *quot, int *rem, long long a, int b)
void __builtin_c29_mdiv_s32_s32(int *quot, int *rem, int a, int b)
void __builtin_c29_mdiv_s64_s64(long long *quot, long long *rem, long long a, long long b)

2.9.5. Floating-Point Arithmetic Intrinsics

The C2000 C29x CPU and Instruction Set User’s Guide, which is available through your TI Field Application Engineer, describes the floating-point arithmetic instructions available for C29x processors. For each instruction that has a corresponding intrinsic function that can be called from C/C++, the syntax is provided. The floating-point arithmetic intrinsics provided include intrinsics to perform:

  • Floating-point addition, subtraction, and multiplication

  • Floating-point comparisons

  • Absolute value and negation operations

  • Fractional portion extraction

  • Floating-point trigonometric and mathematical operations

Note

The following intrinsics expand to a sequence of instructions. This is in contrast to other intrinsics listed on this page, which generally correspond to a single instruction.

For floating division operations, the following intrinsics return the quotient given from the dividend *dividend and divisor *divisor. These functions fall into one of two following variant categories:

  • Accuracy sequence: expanded division sequence

  • Fast approximation: resolves to single DIVF instruction

float __builtin_c29_div_f32(float dividend, float divisor);

double __builtin_c29_div_f64(double dividend, double divisor);

float __builtin_c29_fast_div_f32(float dividend, float divisor);

For floating-point trigonometric and mathematical operations, the following intrinsics expand into sequences that perform fast approximations. The purpose of these intrinsics is to provide more performant floating-point operations than the standard RTS calls, trading some accuracy for performance.

float __builtin_c29_fast_acosf(float angle);

float __builtin_c29_fast_asinf(float angle);

float __builtin_c29_fast_atan2f(float y_component, float x_component);

float __builtin_c29_fast_ceilf(float value);

float __builtin_c29_fast_floorf(float value);

float __builtin_c29_fast_fmodf(float dividend, float divisor);

float __builtin_c29_fast_logf(float value);

float __builtin_c29_fast_roundf(float value);

float __builtin_c29_fast_truncf(float value);

// Standard cosine function (not a fast approximation)
// Direct wrapper to standard RTS sinf function
float __builtin_c29_sinf(float angle);

// Standard cosine function (not a fast approximation)
// Direct wrapper to standard RTS cosf function
float __builtin_c29_cosf(float angle);

2.9.6. Conversion Intrinsics

The C2000 C29x CPU and Instruction Set User’s Guide, which is available through your TI Field Application Engineer, describes the conversion instructions available for C29x processors. For each instruction that has a corresponding intrinsic that can be called from C/C++, the syntax is provided. The conversion intrinsics provided include intrinsics to perform:

  • Convert between 16-bit signed integer and 32-bit float formats

  • Convert between 16-bit unsigned integer and 32-bit float formats

  • Convert between 32-bit signed integer and 64-bit float formats (only available with -mfpu=f64 option set)

  • Convert between 32-bit unsigned integer and 64-bit float formats (only available with -mfpu=f64 option set)

short __builtin_c29_f32_to_i16(float value);

short __builtin_c29_f32_to_i16_round(float value);

unsigned short __builtin_c29_f32_to_ui16(float value);

unsigned short __builtin_c29_f32_to_ui16_round(float value);

int __builtin_c29_f32_to_i32(float value);

int __builtin_c29_f32_to_i32_round(float value);

unsigned int __builtin_c29_f32_to_ui32(float value);

unsigned int __builtin_c29_f32_to_ui32_round(float value);

float __builtin_c29_i16_to_f32(short value);

float __builtin_c29_ui16_to_f32(unsigned short value);

float __builtin_c29_i32_to_f32(int value);

float __builtin_c29_ui32_to_f32(unsigned int value);

int __builtin_c29_f64_to_i32(double value);

unsigned int __builtin_c29_f64_to_ui32(double value);

double __builtin_c29_i32_to_f64(int value);

double __builtin_c29_ui32_to_f64(unsigned int value);

long long __builtin_c29_f64_to_i64(double value);

unsigned long long __builtin_c29_f64_to_ui64(double value);

double __builtin_c29_i64_to_f64(long long value);

double __builtin_c29_ui64_to_f64(unsigned long long value);

double __builtin_c29_f32_to_f64(float value);

float __builtin_c29_f64_to_f32(double value);

2.9.7. Co-Processor Interface (CPI) Intrinsics

The C2000 C29x CPU and Instruction Set User’s Guide, which is available through your TI Field Application Engineer, describes the CPI instructions available for C29x processors. For each instruction that has a corresponding intrinsic function that can be called from C/C++, the syntax is provided. The CPI intrinsics provided include intrinsics to perform:

  • Copy values between registers on the CPU to registers on the CPI Interface port (CIDy)

  • Generate a tag value to be used for data logging.

2.9.8. Other Control Flow Intrinsics

The C2000 C29x CPU and Instruction Set User’s Guide, which is available through your TI Field Application Engineer, describes the control flow instructions available for C29x processors. For each instruction that has a corresponding intrinsic function that can be called from C/C++, the syntax is provided. The control flow intrinsics provided include intrinsics to perform:

  • Copy and conditional copy from register to register

  • Test a bit position in a register

  • Perform integer comparison; set flags based on results

  • Perform floating-point comparison; set flags based on results

2.9.9. Load, Store, and Move Intrinsics

The C2000 C29x CPU and Instruction Set User’s Guide, which is available through your TI Field Application Engineer, describes the load, store, and move instructions available for C29x processors. For each instruction that has a corresponding intrinsic function that can be called from C/C++, the syntax is provided. The load, store, and move intrinsics provided include intrinsics to perform:

  • Load from memory location

  • Store to memory location

  • Copy from memory location to memory location/register

  • Modify memory location

  • Add to memory location and load

  • Subtract from memory location and load

  • Sign extension

  • Zero extension

  • Swap bit(s)

  • Swap byte

  • Split register

  • Zero masking

For split register operations, the following intrinsics return the upper and lower register in *upper* and *lower from the given *input. These functions fall into one of the following variant categories:

  • Q-format upper 16-bit split (upper bits set, lower bits zero extended)

  • Lower signed 16-bit split (lower bits set, upper bits sign extended)

  • Lower unsigned 16-bit split (lower bits set, upper bits zero extended)

// - upper[31:16] = input[31:16] with upper[15:0] = 0
// - lower[31:16] = input[15:0] with lower[15:0] = 0
// - input: The 32-bit value to split
void __builtin_c29_split_q16(unsigned int * upper, unsigned int * lower, unsigned int input);

// - upper[15:0] = input[31:16] with upper[31:16] = sign extension(input[31])
// - lower[15:0] = input[15:0] with lower[31:16] = sign extension(input[15])
// - input: The 32-bit value to split
void __builtin_c29_split_s16(int * upper, int * lower, unsigned int input);

// - upper_part[15:0] = input[31:16] with upper_part[31:16] = 0
// - lower_part[15:0] = input[15:0] with lower_part[31:16] = 0
// - input: The 32-bit value to split
void __builtin_c29_split_u16(unsigned int * upper, unsigned int * lower, unsigned int input);