Skip to content

libagbabi

Felix Jones edited this page Jan 14, 2021 · 1 revision

libagbabi provides GBA optimized functions for some common, handy operations.

It was originally created as an optional utility library for gba-toolchain projects, where it is still available with the CMake function gba_target_link_agb_abi.

The library

Fast division

__aeabi_idivmod, __aeabi_idiv

Replaces the GNU arm-eabi signed integer division/modulo with a fast, IWRAM, ARM assembly optimized division.

This is faster than the default GNU division operator for several reasons, but it is also faster than the BIOS provided division functions (Div, DivArm).

__aeabi_idiv is an alias for __aeabi_idivmod.

Example

signed int a, b;
signed int c = a % b; // Replaces the modulo operator
c = __aeabi_idivmod( a, b ); // Performs a division, leaving modulo in r1

__aeabi_uidivmod, __aeabi_uidiv

Replaces the GNU arm-eabi unsigned integer division/modulo with a fast, IWRAM, ARM assembly optimized division.

This is faster than the default GNU division operator for several reasons, but it is also faster than the BIOS provided division functions (Div, DivArm).

__aeabi_uidiv is an alias for __aeabi_uidivmod.

Example

unsigned int a, b;
unsigned int c = a % b; // Replaces the modulo operator
c = __aeabi_uidivmod( a, b ); // Performs a division, leaving modulo in r1

__agbabi_unsafe_uidiv

The same as __aeabi_uidivmod, but after a divide-by-zero check.

It is entirely up to the caller to protect against divide-by-zero.

Example

unsigned int a, b;
unsigned int c = a % b; // Replaces the modulo operator
c = __agbabi_unsafe_uidiv( a, b ); // Performs a division, leaving modulo in r1

IRQ handlers

__agbabi_irq_empty

An empty IRQ implementation that acknowledges any raised IRQs and returns.

This is useful if you don't want an IRQ handler, but still want to use BIOS functions that require IRQs to be acknowledged, such as the BIOS halt functions.

Example

typedef void( * handler_t )( void );
*( volatile handler_t * )0x03007FFC = __agbabi_irq_empty;

__agbabi_irq_user

IRQ implementation that further calls a function pointed to by __agbabi_irq_uproc.

This IRQ calls __agbabi_irq_uproc in CPU user-mode with the raise IRQs disabled and IME disabled. IME can be re-enabled to allow nested IRQs.

Example

void my_handler( int );

typedef void( * handler_t )( void );
*( volatile handler_t * )0x03007FFC = __agbabi_irq_user;
__agbabi_irq_uproc = my_handler;

__agbabi_irq_uproc

Used by __agbabi_irq_user.

__agbabi_irq_uproc has the raised IRQ flags passed to it, allowing for the implementing IRQ handling switchboards.

Example

void my_handler( int irqFlags ) {
  if ( irqFlags & 1 ) {
    // Handle VBlank
  }
}
__agbabi_irq_uproc = my_handler;


typedef void( * handler_t )( void );
*( volatile handler_t * )0x03007FFC = __agbabi_irq_user;

Context switching

__agbabi_getcontext

Partial implementation of UNIX-like getcontext.

Example

#include <sys/ucontext.h>
ucontext_t ctx;
__agbabi_getcontext( &ctx );

__agbabi_setcontext

Partial implementation of UNIX-like setcontext.

Example

#include <sys/ucontext.h>
ucontext_t ctx;
__agbabi_getcontext( &ctx );
// Other stuff
__agbabi_setcontext( &ctx ); // Returns up to where __agbabi_getcontext was called

__agbabi_makecontext

Partial implementation of UNIX-like makecontext.

Example

#include <sys/ucontext.h>
void my_context_function( int a, int b ) {}
static int ctx_stack[200] {};
ucontext_t link_ctx;

ucontext_t ctx;
ctx.uc_stack.ss_sp = ctx_stack;
ctx.uc_stack.ss_size = sizeof( ctx_stack );
ctx.uc_link = &link_ctx;
__agbabi_makecontext( &ctx, my_context_function, 2, 3, 6 ); // Create context that calls my_context_function with args 3 and 6

__agbabi_swapcontext

Partial implementation of UNIX-like swapcontext.

Example

#include <sys/ucontext.h>
void my_context_function() {}
static int ctx_stack[200] {};
ucontext_t link_ctx;

ucontext_t ctx;
ctx.uc_stack.ss_sp = ctx_stack;
ctx.uc_stack.ss_size = sizeof( ctx_stack );
ctx.uc_link = &link_ctx;
__agbabi_makecontext( &ctx, my_context_function, 0 );

__agbabi_swapcontext( &link_ctx, &ctx ); // Swap from link_ctx to ctx

__agbabi_ctx_start

Assigned to the stored context's link register by __agbabi_makecontext. Used to return to the parent context.

Not recommended to ever call directly.