15. Intrinsic functions

This chapter covers predefined intrinsic and built-in functions.

Intrinsics functions appear as ordinary calls but are special compiler constructs, emitting specific instruction sequences. To enable them, include the calypsi/intrinsics6502.h header file.

Built-in functions are similar, but they are not declared in calypsi/intrinsics6502.h.

15.1. Intrinsic functions reference

The calypsi/intrinsics6502.h file appears as follows:

/****************************************************************************
 *
 * Copyright Håkan Thörngren
 *
 * This file is part of the Calypsi C library.
 * Permission to use with the Calypsi tool chain is hereby granted.
 *
 ****************************************************************************/

#ifndef __INTRINSICS_6502_H
#define __INTRINSICS_6502_H

#ifdef __CALYPSI_TARGET_6502__

typedef unsigned char __interrupt_state_t;
typedef void (*__return_address_t)(void);
typedef unsigned short __return_address16_t;

__attribute__((intrinsic)) void __disable_interrupts(void);
__attribute__((intrinsic)) void __enable_interrupts(void);
__attribute__((intrinsic)) __interrupt_state_t __get_interrupt_state(void);
__attribute__((intrinsic)) void __restore_interrupt_state(__interrupt_state_t);

__attribute__((intrinsic)) __return_address_t __get_return_address(void);
__attribute__((intrinsic)) void __set_return_address(__return_address_t);
__attribute__((intrinsic)) void __set_return_address_low16(__return_address16_t);

__attribute__((intrinsic)) void __no_operation(void);

__attribute__((intrinsic)) _Bool __kernel_call_failed(_Bool);

#ifndef __CALYPSI_CORE_65B02__
__attribute__((intrinsic)) void __break_instruction(void);
__attribute__((intrinsic)) void __break_with(unsigned char);
#endif

#ifdef __CALYPSI_CORE_65C02__
__attribute__((intrinsic)) void __wait_for_interrupt(void);
__attribute__((intrinsic)) void __stop_processor(void);
#endif // __CALYPSI_CORE_65C02__

#endif // __CALYPSI_TARGET_6502__

#endif // __INTRINSICS_6502_H

Summary of intrinsic functions

Table 15.1 Intrinsic functions summary

Function name

Description

__disable_interrupts

Disable interrupts

__enable_interrupts

Enable interrupts

__get_interrupt_state

Get the current interrupt state

__restore_interrupt_state

Restore to a previous interrupt state

__get_return_address

Gets the return address of the current function

__set_return_address

Alters the return address of the current function

__break_instruction

Generates a BRK instruction (not available on 65B02)

__break_with

Generates a BRK instruction with an argument

__no_operation

Generates a NOP instruction

__wait_for_interrupt

Waits for an interrupt (65C02 and 65CNR02 cores only)

__stop_processor

Stops the processor (65C02 and 65CNR02 cores only)

__builtin_clz

Counts leading zeroes in an int

__builtin_clzl

Counts leading zeroes in a long

__builtin_clzll

Counts leading zeroes in a long long

__builtin_signbit

Gets the value of the sign bit

__kernel_call_failed

Checks for failure after a system call in a kernel, returning status in the carry flag

Description of intrinsic functions

This section details each intrinsic function.

__disable_interrupts

Emits a machine instruction that disables interrupts.

__enable_interrupts

Emits a machine instruction that enables interrupts.

__get_interrupt_state

Returns the current interrupt state as a __interrupt_state_t value, which can be used as follows:

int global;

void safe_increment () {
  __interrupt_state_t state = __get_interrupt_state();
  __disable_interrupts;
  global++;
  __restore_interrupt_state(state);
}

In the example the current state of interrupts is obtained and saved Returns the current interrupt state as a __interrupt_state_t value, do the real work. Finally, the interrupt state is restored to what it was when the function was entered.

__restore_interrupt_state

Restores to a previous interrupt state, see example above.

__get_return_address

Reads the return address of the current function from its stack frame.

__set_return_address

Replaces the current function return address with the address provided in the argument to __set_return_address().

__no_operation

Emits a NOP machine instruction.

__break_instruction

Emits a machine instruction that causes a break exception.

__break_with

Emits a break exception instruction. This variant takes an opcode argument for the BRK instruction second byte.

__wait_for_interrupt

Emits an instruction that causes the 65C02 (or 65CNR02) to wait for an interrupt. Execution then resumes with the interrupt, followed by normal execution. This functionality is not available on the plain 6502.

__stop_processor

Emits an instruction that causes the 65C02 (or 65CNR02) to halt execution. This functionality is not available on the plain 6502.

__builtin_clz

Count the number of leading zeroes in a provided int value. Returns an undefined result if input is zero.

__builtin_clzl

Count the number of leading zeroes in a provided long value. Returns an undefined result if input is zero.

__builtin_clzll

Count the number of leading zeroes in a provided long long value. Returns an undefined result if input is zero.

__builtin_signbit

Returns the value (0 or 1) of the signbit of its input.

__kernel_call_failed

This intrinsic wraps a Commodore-style kernel system call, testing the carry flag return value. It can be used as follows:

#include <microkernel.h>

void bcd_time() {
  if (__kernel_call_failed(MicroKernelGetTime())) {
    // Handle failure
    ...
  } else {
    // Success
    ...
  }
}

Note

This intrinsic assumes that it surrounds a MicroKernel call expression, if that is not the case the result is unpredictable.