libdragon
Loading...
Searching...
No Matches
Files | Macros | Enumerations | Functions | Variables

N64 bootup and cache interfaces. More...

Files

file  n64sys.c
 N64 System Interface.
 
file  cop0.h
 N64 COP0 Interface.
 
file  cop1.h
 N64 COP1 Interface.
 
file  n64sys.h
 N64 System Interface.
 

Macros

#define C0_COUNT()
 Read the COP0 Count register (see also TICKS_READ).
 
#define C0_WRITE_COUNT(x)
 Write the COP0 Count register.
 
#define C0_COMPARE()
 Read the COP0 Compare register.
 
#define C0_WRITE_COMPARE(x)
 Write the COP0 Compare register.
 
#define C0_STATUS()
 Read the COP0 Status register.
 
#define C0_WRITE_STATUS(x)
 Write the COP0 Status register.
 
#define C0_CAUSE()
 Returns the COP0 register $13 (Cause Register)
 
#define C0_WRITE_CAUSE(x)
 Write the COP0 register $13 (Cause register)
 
#define C0_BADVADDR()
 Returns the COP0 register $8 (BadVAddr)
 
#define C0_EPC()
 Read the COP0 register $14 (EPC)
 
#define C0_INDEX()
 Read the COP0 INDEX register.
 
#define C0_WRITE_INDEX(x)   asm volatile("mtc0 %0,$0; nop; nop"::"r"(x))
 Write the COP0 INDEX register.
 
#define C0_ENTRYHI()
 Read the COP0 ENTRYHI register.
 
#define C0_WRITE_ENTRYHI(x)   asm volatile("mtc0 %0,$10; nop; nop"::"r"(x))
 Write the COP0 ENTRYHI register.
 
#define C0_ENTRYLO0()
 Read the COP0 ENTRYLO0 register.
 
#define C0_WRITE_ENTRYLO0(x)   asm volatile("mtc0 %0,$2; nop; nop"::"r"(x))
 Write the COP0 ENTRYLO0 register.
 
#define C0_ENTRYLO1()
 Read the COP0 ENTRYLO1 register.
 
#define C0_WRITE_ENTRYLO1(x)   asm volatile("mtc0 %0,$3; nop; nop"::"r"(x))
 Write the COP0 ENTRYLO1 register.
 
#define C0_PAGEMASK()
 Read the COP0 PAGEMASK register.
 
#define C0_WRITE_PAGEMASK(x)   asm volatile("mtc0 %0,$5; nop; nop"::"r"(x))
 Write the COP0 PAGEMASK register.
 
#define C0_WIRED()
 Read the COP0 WIRED register.
 
#define C0_WATCHLO()
 Read the COP0 WATCHLO register.
 
#define C0_WRITE_WATCHLO(x)   asm volatile("mtc0 %0,$18"::"r"(x))
 Write the COP0 WATCHLO register.
 
#define C0_WRITE_WIRED(x)   asm volatile("mtc0 %0,$6; nop; nop"::"r"(x))
 Write the COP0 WIRED register.
 
#define C0_STATUS_IE   0x00000001
 Status: interrupt enable.
 
#define C0_STATUS_EXL   0x00000002
 Status: within exception.
 
#define C0_STATUS_ERL   0x00000004
 Status: within error.
 
#define C0_CAUSE_BD   0x80000000
 Cause: exception triggered in delay slot.
 
#define C0_CAUSE_CE   0x30000000
 Cause: coprocessor exception.
 
#define C0_CAUSE_EXC_CODE   0x0000007C
 Cause: exception code.
 
#define C0_INTERRUPT_0   0x00000100
 Status/Cause: SW interrupt 0.
 
#define C0_INTERRUPT_1   0x00000200
 Status/Cause: SW interrupt 1.
 
#define C0_INTERRUPT_2   0x00000400
 Status/Cause: HW interrupt 2 (RCP)
 
#define C0_INTERRUPT_3   0x00000800
 Status/Cause: HW interrupt 3 (CART)
 
#define C0_INTERRUPT_4   0x00001000
 Status/Cause: HW interrupt 4 (PRENMI)
 
#define C0_INTERRUPT_5   0x00002000
 Status/Cause: HW interrupt 5.
 
#define C0_INTERRUPT_6   0x00004000
 Status/Cause: HW interrupt 6.
 
#define C0_INTERRUPT_7   0x00008000
 Status/Cause: HW interrupt 7 (Timer)
 
#define C0_INTERRUPT_RCP   C0_INTERRUPT_2
 Status/Cause: HW interrupt 2 (RCP)
 
#define C0_INTERRUPT_CART   C0_INTERRUPT_3
 Status/Cause: HW interrupt 3 (CART)
 
#define C0_INTERRUPT_PRENMI   C0_INTERRUPT_4
 Status/Cause: HW interrupt 4 (PRENMI)
 
#define C0_INTERRUPT_TIMER   C0_INTERRUPT_7
 Status/Cause: HW interrupt 7 (Timer)
 
#define C0_GET_CAUSE_CE(cr)   (((cr) & C0_CAUSE_CE) >> 28)
 Get the CE value from the COP0 status register.
 
#define C0_GET_CAUSE_EXC_CODE(sr)   (((sr) & C0_CAUSE_EXC_CODE) >> 2)
 Get the exception code value from the COP0 status register value.
 
#define C0_ENTRYLO_GLOBAL   (1<<0)
 ENTRYLO: mapping is global (all ASIDs)
 
#define C0_ENTRYLO_VALID   (1<<1)
 ENTRYLO: mapping is active (not disabled)
 
#define C0_ENTRYLO_DIRTY   (1<<2)
 ENTRYLO: mapping is writable.
 
#define C0_INDEX_PROBE_FAILED   (1<<31)
 INDEX: set when a TLBP probe failed to find a match.
 
#define C0_TLBWI()   asm volatile("tlbwi; nop; nop; nop; nop")
 COP0 TLBWI opcode.
 
#define C0_TLBWR()   asm volatile("tlbwr; nop; nop; nop; nop")
 COP0 TLBWR opcode.
 
#define C0_TLBR()   asm volatile("tlbr; nop; nop; nop; nop")
 COP0 TLBR opcode.
 
#define C0_TLBP()   asm volatile("tlbp; nop; nop; nop; nop")
 COP0 TLBP opcode.
 
#define C1_FLAG_INEXACT_OP   0x00000004
 Flag recording inexact operation.
 
#define C1_FLAG_UNDERFLOW   0x00000008
 Flag recording underflow.
 
#define C1_FLAG_OVERFLOW   0x00000010
 Flag recording overflow.
 
#define C1_FLAG_DIV_BY_0   0x00000020
 Flag recording division by zero.
 
#define C1_FLAG_INVALID_OP   0x00000040
 Flag recording invalid operation.
 
#define C1_ENABLE_INEXACT_OP   0x00000080
 Enable inexact operation exception.
 
#define C1_ENABLE_UNDERFLOW   0x00000100
 Enable underflow exception.
 
#define C1_ENABLE_OVERFLOW   0x00000200
 Enable overflow exception.
 
#define C1_ENABLE_DIV_BY_0   0x00000400
 Enable division by zero exception.
 
#define C1_ENABLE_INVALID_OP   0x00000800
 Enable invalid operation exception.
 
#define C1_ENABLE_MASK   0x00000F80
 Mask for all enable bits.
 
#define C1_CAUSE_INEXACT_OP   0x00001000
 Triggered inexact operation exception.
 
#define C1_CAUSE_UNDERFLOW   0x00002000
 Triggered underflow exception.
 
#define C1_CAUSE_OVERFLOW   0x00004000
 Triggered overflow exception.
 
#define C1_CAUSE_DIV_BY_0   0x00008000
 Triggered division by zero exception.
 
#define C1_CAUSE_INVALID_OP   0x00010000
 Triggered invalid operation exception.
 
#define C1_CAUSE_NOT_IMPLEMENTED   0x00020000
 Triggered not implemented exception.
 
#define C1_CAUSE_MASK   0x0003F000
 Mask for all cause bits.
 
#define C1_FCR31_FS   (1<<24)
 Flush denormals to zero/min.
 
#define C1_FCR31()
 Read the COP1 FCR31 register (floating-point control register 31)
 
#define C1_WRITE_FCR31(x)
 Write to the COP1 FCR31 register.
 
#define RCP_FREQUENCY   (__boot_consoletype ? 96000000 : 62500000)
 Frequency of the RCP.
 
#define CPU_FREQUENCY   (__boot_consoletype ? 144000000 : 93750000)
 Frequency of the MIPS R4300 CPU.
 
#define KSEG0_START_ADDR   ((void*)0x80000000)
 void pointer to cached and non-mapped memory start address
 
#define UncachedAddr(_addr)   ((void *)(((unsigned long)(_addr))|0x20000000))
 Return the uncached memory address for a given address.
 
#define UncachedShortAddr(_addr)   ((short *)(((unsigned long)(_addr))|0x20000000))
 Return the uncached memory address for a given address.
 
#define UncachedUShortAddr(_addr)   ((unsigned short *)(((unsigned long)(_addr))|0x20000000))
 Return the uncached memory address for a given address.
 
#define UncachedLongAddr(_addr)   ((long *)(((unsigned long)(_addr))|0x20000000))
 Return the uncached memory address for a given address.
 
#define UncachedULongAddr(_addr)   ((unsigned long *)(((unsigned long)(_addr))|0x20000000))
 Return the uncached memory address for a given address.
 
#define CachedAddr(_addr)   ((void *)(((unsigned long)(_addr))&~0x20000000))
 Return the cached memory address for a given address.
 
#define PhysicalAddr(_addr)
 Return the physical memory address for a given address.
 
#define HEAP_START_ADDR   ((void*)__bss_end)
 Void pointer to the start of heap memory.
 
#define MEMORY_BARRIER()   asm volatile ("" : : : "memory")
 Memory barrier to ensure in-order execution.
 
#define TICKS_READ()   C0_COUNT()
 Returns the 32-bit hardware tick counter.
 
#define TICKS_PER_SECOND   (CPU_FREQUENCY/2)
 Number of updates to the count register per second.
 
#define TICKS_DISTANCE(from, to)   ((int32_t)((uint32_t)(to) - (uint32_t)(from)))
 Calculate the time passed between two ticks.
 
#define TICKS_SINCE(t0)   TICKS_DISTANCE(t0, TICKS_READ())
 Return how much time has passed since the instant t0.
 
#define TICKS_BEFORE(t1, t2)   ({ TICKS_DISTANCE(t1, t2) > 0; })
 Returns true if "t1" is before "t2".
 
#define TICKS_FROM_MS(val)   (((val) * (TICKS_PER_SECOND / 1000)))
 Returns equivalent count ticks for the given milliseconds.
 
#define TICKS_FROM_US(val)   (((val) * (8 * TICKS_PER_SECOND / 1000000) / 8))
 Returns equivalent count ticks for the given microseconds.
 
#define TICKS_TO_US(val)   (((val) * 8 / (8 * TICKS_PER_SECOND / 1000000)))
 Returns equivalent count ticks for the given microseconds.
 
#define TICKS_TO_MS(val)   (((val) / (TICKS_PER_SECOND / 1000)))
 Returns equivalent count ticks for the given microseconds.
 
#define data_cache_hit_invalidate(addr_, sz_)
 Force a data cache invalidate over a memory region.
 

Enumerations

enum  tv_type_t { TV_PAL = 0 , TV_NTSC = 1 , TV_MPAL = 2 }
 Type of TV video output. More...
 
enum  reset_type_t { RESET_COLD = 0 , RESET_WARM = 1 }
 Reset types. More...
 

Functions

bool sys_bbplayer (void)
 Return true if we are running on a iQue player.
 
uint64_t get_ticks (void)
 Read the number of ticks since system startup.
 
uint64_t get_ticks_us (void)
 Read the number of microseconds since system startup.
 
uint64_t get_ticks_ms (void)
 Read the number of millisecounds since system startup.
 
void wait_ticks (unsigned long wait)
 Spin wait until the number of ticks have elapsed.
 
void wait_ms (unsigned long wait_ms)
 Spin wait until the number of milliseconds have elapsed.
 
void __data_cache_hit_invalidate (volatile void *addr, unsigned long length)
 Underlying implementation of data_cache_hit_invalidate.
 
void data_cache_hit_writeback (volatile const void *, unsigned long)
 Force a data cache writeback over a memory region.
 
void data_cache_hit_writeback_invalidate (volatile void *, unsigned long)
 Force a data cache writeback invalidate over a memory region.
 
void data_cache_index_writeback_invalidate (volatile void *, unsigned long)
 Force a data cache index writeback invalidate over a memory region.
 
void data_cache_writeback_invalidate_all (void)
 Force a data cache writeback invalidate over whole memory.
 
void inst_cache_hit_writeback (volatile const void *, unsigned long)
 Force an instruction cache writeback over a memory region.
 
void inst_cache_hit_invalidate (volatile void *, unsigned long)
 Force an instruction cache invalidate over a memory region.
 
void inst_cache_index_invalidate (volatile void *, unsigned long)
 Force an instruction cache index invalidate over a memory region.
 
void inst_cache_invalidate_all (void)
 Force an instruction cache invalidate over whole memory.
 
int get_memory_size ()
 Get amount of available memory.
 
bool is_memory_expanded ()
 Is expansion pak in use.
 
void * malloc_uncached (size_t size)
 Allocate a buffer that will be accessed as uncached memory.
 
void * malloc_uncached_aligned (int align, size_t size)
 Allocate a buffer that will be accessed as uncached memory, specifying alignment.
 
void free_uncached (void *buf)
 Free an uncached memory buffer.
 
tv_type_t get_tv_type ()
 Is system NTSC/PAL/MPAL.
 
reset_type_t sys_reset_type (void)
 Get reset type.
 

Variables

char __libdragon_text_start []
 Symbol at the start of code (start of ROM contents after header)
 
char __rom_end []
 Symbol at the end of code, data, and sdata (set by the linker)
 
char __bss_end []
 Symbol at the end of code, data, sdata, and bss (set by the linker)
 

Detailed Description

N64 bootup and cache interfaces.

The N64 system interface provides a way for code to interact with the memory setup on the system. This includes cache operations to invalidate or flush regions and the ability to set the boot CIC. The newlib Interface Hooks use the knowledge of the boot CIC to properly determine if the expansion pak is present, giving 4 MiB of additional memory. Aside from this, the MIPS r4300 uses a manual cache management strategy, where SW that requires passing buffers to and from hardware components using DMA controllers needs to ensure that cache and RDRAM are in sync. A set of operations to invalidate and/or write back cache is provided for both instruction cache and data cache.

Macro Definition Documentation

◆ C0_COUNT

#define C0_COUNT ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$9":"=r"(x)); \
x; \
})

Read the COP0 Count register (see also TICKS_READ).

◆ C0_WRITE_COUNT

#define C0_WRITE_COUNT (   x)
Value:
({ \
asm volatile("mtc0 %0,$9"::"r"(x)); \
})

Write the COP0 Count register.

◆ C0_COMPARE

#define C0_COMPARE ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$11":"=r"(x)); \
x; \
})

Read the COP0 Compare register.

◆ C0_WRITE_COMPARE

#define C0_WRITE_COMPARE (   x)
Value:
({ \
asm volatile("mtc0 %0,$11"::"r"(x)); \
})

Write the COP0 Compare register.

◆ C0_STATUS

#define C0_STATUS ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$12":"=r"(x)); \
x; \
})

Read the COP0 Status register.

◆ C0_WRITE_STATUS

#define C0_WRITE_STATUS (   x)
Value:
({ \
asm volatile("mtc0 %0,$12"::"r"(x)); \
})

Write the COP0 Status register.

◆ C0_CAUSE

#define C0_CAUSE ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$13" : "=r" (x) : ); \
x; \
})

Returns the COP0 register $13 (Cause Register)

The coprocessor 0 (system control coprocessor - COP0) register $13 is a read write register keeping pending interrupts, exception code, coprocessor unit number referenced for a coprocessor unusable exception.

See also
C0_GET_CAUSE_EXC_CODE, C0_GET_CAUSE_CE and C0_CAUSE_BD

◆ C0_WRITE_CAUSE

#define C0_WRITE_CAUSE (   x)
Value:
({ \
asm volatile("mtc0 %0,$13"::"r"(x)); \
})

Write the COP0 register $13 (Cause register)

Use this to update it for a custom exception handler.

◆ C0_BADVADDR

#define C0_BADVADDR ( )
Value:
({ \
uint64_t x; \
asm volatile("dmfc0 %0,$8" : "=r" (x) : ); \
x; \
})

Returns the COP0 register $8 (BadVAddr)

The coprocessor 0 (system control coprocessor - COP0) register $8 is a read only register holding the last virtual address to be translated which became invalid, or a virtual address for which an addressing error occurred.

◆ C0_EPC

#define C0_EPC ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$14" : "=r" (x) : ); \
x; \
})

Read the COP0 register $14 (EPC)

The coprocessor 0 (system control coprocessor - COP0) register $14 is the return from exception program counter. For asynchronous exceptions it points to the place to continue execution whereas for synchronous (caused by code) exceptions, point to the instruction causing the fault condition, which needs correction in the exception handler. This macro is for reading its value.

◆ C0_INDEX

#define C0_INDEX ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$0":"=r"(x)); \
x; \
})

Read the COP0 INDEX register.

This register is used during TLB programming. It holds the index of the TLB entry being accessed (0-31).

◆ C0_WRITE_INDEX

#define C0_WRITE_INDEX (   x)    asm volatile("mtc0 %0,$0; nop; nop"::"r"(x))

Write the COP0 INDEX register.

This register is used during TLB programming. It holds the index of the TLB entry being accessed (0-31).

◆ C0_ENTRYHI

#define C0_ENTRYHI ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$10":"=r"(x)); \
x; \
})

Read the COP0 ENTRYHI register.

This register is used during TLB programming. It holds the configuration of the virtual memory entry for the TLB slot being accessed.

◆ C0_WRITE_ENTRYHI

#define C0_WRITE_ENTRYHI (   x)    asm volatile("mtc0 %0,$10; nop; nop"::"r"(x))

Write the COP0 ENTRYHI register.

This register is used during TLB programming.

◆ C0_ENTRYLO0

#define C0_ENTRYLO0 ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$2":"=r"(x)); \
x; \
})

Read the COP0 ENTRYLO0 register.

This register is used during TLB programming. It holds the configuration of the physical memory entry (even bank) for the TLB slot being accessed.

◆ C0_WRITE_ENTRYLO0

#define C0_WRITE_ENTRYLO0 (   x)    asm volatile("mtc0 %0,$2; nop; nop"::"r"(x))

Write the COP0 ENTRYLO0 register.

This register is used during TLB programming. It holds the configuration of the physical memory entry (even bank) for the TLB slot being accessed.

◆ C0_ENTRYLO1

#define C0_ENTRYLO1 ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$3":"=r"(x)); \
x; \
})

Read the COP0 ENTRYLO1 register.

This register is used during TLB programming. It holds the configuration of the physical memory entry (odd bank) for the TLB slot being accessed.

◆ C0_WRITE_ENTRYLO1

#define C0_WRITE_ENTRYLO1 (   x)    asm volatile("mtc0 %0,$3; nop; nop"::"r"(x))

Write the COP0 ENTRYLO1 register.

This register is used during TLB programming. It holds the configuration of the physical memory entry (even bank) for the TLB slot being accessed.

◆ C0_PAGEMASK

#define C0_PAGEMASK ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$5":"=r"(x)); \
x; \
})

Read the COP0 PAGEMASK register.

This register is used during TLB programming. It holds the bitmask that configures the page size of the TLB slot being accessed.

◆ C0_WRITE_PAGEMASK

#define C0_WRITE_PAGEMASK (   x)    asm volatile("mtc0 %0,$5; nop; nop"::"r"(x))

Write the COP0 PAGEMASK register.

This register is used during TLB programming. It holds the bitmask that configures the page size of the TLB slot being accessed.

◆ C0_WIRED

#define C0_WIRED ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$6":"=r"(x)); \
x; \
})

Read the COP0 WIRED register.

This register is used during TLB programming. It allows to partition TLB slots between fixed slots and random slots. The fixed slot pool is the range [0..WIRED[ and the random pool is the range [WIRED..32[

◆ C0_WATCHLO

#define C0_WATCHLO ( )
Value:
({ \
uint32_t x; \
asm volatile("mfc0 %0,$18":"=r"(x)); \
x; \
})

Read the COP0 WATCHLO register.

This register is used during watchpoint programming. It allows to trigger an exception when a memory access occurs on a specific memory location.

◆ C0_WRITE_WATCHLO

#define C0_WRITE_WATCHLO (   x)    asm volatile("mtc0 %0,$18"::"r"(x))

Write the COP0 WATCHLO register.

This register is used during watchpoint programming. It allows to trigger an exception when a memory access occurs on a specific memory location.

◆ C0_WRITE_WIRED

#define C0_WRITE_WIRED (   x)    asm volatile("mtc0 %0,$6; nop; nop"::"r"(x))

Write the COP0 WIRED register.

This register is used during TLB programming. It allows to partition TLB slots between fixed slots and random slots. The fixed slot pool is the range [0..WIRED[ and the random pool is the range [WIRED..32[

◆ C0_GET_CAUSE_CE

#define C0_GET_CAUSE_CE (   cr)    (((cr) & C0_CAUSE_CE) >> 28)

Get the CE value from the COP0 status register.

Gets the Coprocessor unit number referenced by a coprocessor unusable exception from the given COP0 Status register value.

◆ C0_TLBWI

#define C0_TLBWI ( )    asm volatile("tlbwi; nop; nop; nop; nop")

COP0 TLBWI opcode.

This opcode is used during TLB programming. It writes the TLB slot referenced by INDEX with the contents of PAGEMASK, ENTRYHI, ENTRYLO0, ENTRYLO1.

◆ C0_TLBWR

#define C0_TLBWR ( )    asm volatile("tlbwr; nop; nop; nop; nop")

COP0 TLBWR opcode.

This opcode is used during TLB programming. It writes a random TLB slot with the contents of PAGEMASK, ENTRYHI, ENTRYLO0, ENTRYLO1. THe slot is selected in the random pool (slots in the range from WIRED to 31).

◆ C0_TLBR

#define C0_TLBR ( )    asm volatile("tlbr; nop; nop; nop; nop")

COP0 TLBR opcode.

This opcode is used during TLB programming. It reads the contents of the TLB slot referenced by INDEX into the registers PAGEMASK, ENTRYHI, ENTRYLO0 and ENTRYLO1.

◆ C0_TLBP

#define C0_TLBP ( )    asm volatile("tlbp; nop; nop; nop; nop")

COP0 TLBP opcode.

This opcode is used during TLB programming. It probes the current TLB slots using ENTRYHI (virtual address) to find a matching slot. If it finds, it loads its index into INDEX. Otherwise, it sets the C0_INDEX_PROBE_FAILED bit in INDEX.

◆ C1_FCR31

#define C1_FCR31 ( )
Value:
({ \
uint32_t x; \
asm volatile("cfc1 %0,$f31":"=r"(x)); \
x; \
})

Read the COP1 FCR31 register (floating-point control register 31)

FCR31 is also known as the Control/Status register. It keeps control and status data for the FPU.

◆ C1_WRITE_FCR31

#define C1_WRITE_FCR31 (   x)
Value:
({ \
asm volatile("ctc1 %0,$f31"::"r"(x)); \
})

Write to the COP1 FCR31 register.

◆ UncachedAddr

#define UncachedAddr (   _addr)    ((void *)(((unsigned long)(_addr))|0x20000000))

Return the uncached memory address for a given address.

Parameters
[in]_addrAddress in RAM to convert to an uncached address
Returns
A void pointer to the uncached memory address in RAM

◆ UncachedShortAddr

#define UncachedShortAddr (   _addr)    ((short *)(((unsigned long)(_addr))|0x20000000))

Return the uncached memory address for a given address.

Parameters
[in]_addrAddress in RAM to convert to an uncached address
Returns
A short pointer to the uncached memory address in RAM

◆ UncachedUShortAddr

#define UncachedUShortAddr (   _addr)    ((unsigned short *)(((unsigned long)(_addr))|0x20000000))

Return the uncached memory address for a given address.

Parameters
[in]_addrAddress in RAM to convert to an uncached address
Returns
An unsigned short pointer to the uncached memory address in RAM

◆ UncachedLongAddr

#define UncachedLongAddr (   _addr)    ((long *)(((unsigned long)(_addr))|0x20000000))

Return the uncached memory address for a given address.

Parameters
[in]_addrAddress in RAM to convert to an uncached address
Returns
A long pointer to the uncached memory address in RAM

◆ UncachedULongAddr

#define UncachedULongAddr (   _addr)    ((unsigned long *)(((unsigned long)(_addr))|0x20000000))

Return the uncached memory address for a given address.

Parameters
[in]_addrAddress in RAM to convert to an uncached address
Returns
An unsigned long pointer to the uncached memory address in RAM

◆ CachedAddr

#define CachedAddr (   _addr)    ((void *)(((unsigned long)(_addr))&~0x20000000))

Return the cached memory address for a given address.

Parameters
[in]_addrAddress in RAM to convert to a cached address
Returns
A void pointer to the cached memory address in RAM

◆ PhysicalAddr

#define PhysicalAddr (   _addr)
Value:
({ \
const volatile void *_addrp = (_addr); \
(((unsigned long)(_addrp))&~0xE0000000); \
})

Return the physical memory address for a given address.

Parameters
[in]_addrAddress in RAM to convert to a physical address
Returns
A void pointer to the physical memory address in RAM

◆ MEMORY_BARRIER

#define MEMORY_BARRIER ( )    asm volatile ("" : : : "memory")

Memory barrier to ensure in-order execution.

Since GCC seems to reorder volatile at -O2, a memory barrier is required to ensure that DMA setup is done in the correct order. Otherwise, the library is useless at higher optimization levels.

◆ TICKS_READ

#define TICKS_READ ( )    C0_COUNT()

Returns the 32-bit hardware tick counter.

This macro returns the current value of the hardware tick counter, present in the CPU coprocessor 0. The counter increments at half of the processor clock speed (see TICKS_PER_SECOND), and overflows every 91.625 seconds.

It is fine to use this hardware counter for measuring small time intervals, as long as TICKS_DISTANCE or TICKS_BEFORE are used to compare different counter reads, as those macros correctly handle overflows.

Most users might find more convenient to use get_ticks(), a similar function that returns a 64-bit counter with the same frequency that never overflows.

See also
TICKS_BEFORE
TICKS_DISTANCE
get_ticks

◆ TICKS_PER_SECOND

#define TICKS_PER_SECOND   (CPU_FREQUENCY/2)

Number of updates to the count register per second.

Every second, this many counts will have passed in the count register

◆ TICKS_DISTANCE

#define TICKS_DISTANCE (   from,
  to 
)    ((int32_t)((uint32_t)(to) - (uint32_t)(from)))

Calculate the time passed between two ticks.

If "from" is before "to", the distance in time is positive, otherwise it is negative.

◆ TICKS_BEFORE

#define TICKS_BEFORE (   t1,
  t2 
)    ({ TICKS_DISTANCE(t1, t2) > 0; })

Returns true if "t1" is before "t2".

This is similar to t1 < t2, but it correctly handles timer overflows which are very frequent. Notice that the hardware counter overflows every ~91 seconds, so it's not possible to compare times that are more than ~45 seconds apart.

Use get_ticks() to get a 64-bit counter that never overflows.

See also
get_ticks

◆ data_cache_hit_invalidate

#define data_cache_hit_invalidate (   addr_,
  sz_ 
)
Value:
({ \
void *addr = (addr_); unsigned long sz = (sz_); \
assert(((uint32_t)addr % 16) == 0 && (sz % 16) == 0); \
__data_cache_hit_invalidate(addr, sz); \
})

Force a data cache invalidate over a memory region.

Use this to force the N64 to update cache from RDRAM.

The cache is made by cachelines of 16 bytes. If a memory region is invalidated and the memory region is not fully aligned to cachelines, a larger area than that requested will be invalidated; depending on the arrangement of the data segments and/or heap, this might make data previously written by the CPU in regular memory locations to be unexpectedly discarded, causing bugs.

For this reason, this function must only be called with an address aligned to 16 bytes, and with a length which is an exact multiple of 16 bytes; it will assert otherwise.

As an alternative, consider using data_cache_hit_writeback_invalidate, that first writebacks the affected cachelines to RDRAM, guaranteeing integrity of memory areas that share cachelines with the region that must be invalidated.

Parameters
[in]addr_Pointer to memory in question
[in]sz_Length in bytes of the data pointed at by addr

Enumeration Type Documentation

◆ tv_type_t

enum tv_type_t

Type of TV video output.

Enumerator
TV_PAL 

Video output is PAL.

TV_NTSC 

Video output is NTSC.

TV_MPAL 

Video output is M-PAL.

◆ reset_type_t

Reset types.

Enumerator
RESET_COLD 

Cold reset (power on)

RESET_WARM 

Warm reset (reset button)

Function Documentation

◆ get_ticks()

uint64_t get_ticks ( void  )

Read the number of ticks since system startup.

The frequency of this counter is TICKS_PER_SECOND. The counter will never overflow, being a 64-bit number.

Returns
The number of ticks since system startup

◆ get_ticks_us()

uint64_t get_ticks_us ( void  )

Read the number of microseconds since system startup.

This is similar to get_ticks, but converts the result in integer microseconds for convenience.

Returns
The number of microseconds since system startup

◆ get_ticks_ms()

uint64_t get_ticks_ms ( void  )

Read the number of millisecounds since system startup.

This is similar to get_ticks, but converts the result in integer milliseconds for convenience.

Returns
The number of millisecounds since system startup

◆ wait_ticks()

void wait_ticks ( unsigned long  wait)

Spin wait until the number of ticks have elapsed.

Parameters
[in]waitNumber of ticks to wait Maximum accepted value is 0xFFFFFFFF ticks

◆ wait_ms()

void wait_ms ( unsigned long  wait_ms)

Spin wait until the number of milliseconds have elapsed.

Parameters
[in]wait_msNumber of milliseconds to wait Maximum accepted value is 91625 ms

◆ data_cache_hit_writeback()

void data_cache_hit_writeback ( volatile const void *  addr,
unsigned long  length 
)

Force a data cache writeback over a memory region.

Use this to force cached memory to be written to RDRAM.

Parameters
[in]addrPointer to memory in question
[in]lengthLength in bytes of the data pointed at by addr

◆ data_cache_hit_writeback_invalidate()

void data_cache_hit_writeback_invalidate ( volatile void *  addr,
unsigned long  length 
)

Force a data cache writeback invalidate over a memory region.

Use this to force cached memory to be written to RDRAM and then invalidate the corresponding cache lines.

Parameters
[in]addrPointer to memory in question
[in]lengthLength in bytes of the data pointed at by addr

◆ data_cache_index_writeback_invalidate()

void data_cache_index_writeback_invalidate ( volatile void *  addr,
unsigned long  length 
)

Force a data cache index writeback invalidate over a memory region.

Parameters
[in]addrPointer to memory in question
[in]lengthLength in bytes of the data pointed at by addr

◆ data_cache_writeback_invalidate_all()

void data_cache_writeback_invalidate_all ( void  )

Force a data cache writeback invalidate over whole memory.

Also see data_cache_hit_writeback_invalidate

◆ inst_cache_hit_writeback()

void inst_cache_hit_writeback ( volatile const void *  addr,
unsigned long  length 
)

Force an instruction cache writeback over a memory region.

Use this to force cached memory to be written to RDRAM.

Parameters
[in]addrPointer to memory in question
[in]lengthLength in bytes of the data pointed at by addr

◆ inst_cache_hit_invalidate()

void inst_cache_hit_invalidate ( volatile void *  addr,
unsigned long  length 
)

Force an instruction cache invalidate over a memory region.

Use this to force the N64 to update cache from RDRAM.

Parameters
[in]addrPointer to memory in question
[in]lengthLength in bytes of the data pointed at by addr

◆ inst_cache_index_invalidate()

void inst_cache_index_invalidate ( volatile void *  addr,
unsigned long  length 
)

Force an instruction cache index invalidate over a memory region.

Parameters
[in]addrPointer to memory in question
[in]lengthLength in bytes of the data pointed at by addr

◆ inst_cache_invalidate_all()

void inst_cache_invalidate_all ( void  )

Force an instruction cache invalidate over whole memory.

Also see inst_cache_hit_invalidate

◆ get_memory_size()

int get_memory_size ( )

Get amount of available memory.

Returns
amount of total available memory in bytes.

◆ is_memory_expanded()

bool is_memory_expanded ( )

Is expansion pak in use.

Checks whether the maximum available memory has been expanded to 8 MiB

Returns
true if expansion pak detected, false otherwise.
Note
On iQue, this function returns true only if the game has been assigned exactly 8 MiB of RAM.

◆ malloc_uncached()

void * malloc_uncached ( size_t  size)

Allocate a buffer that will be accessed as uncached memory.

This function allocates a memory buffer that can be safely read and written through uncached memory accesses only. It makes sure that that the buffer does not share any cacheline with other buffers in the heap, and returns a pointer in the uncached segment (0xA0000000).

The buffer contents are uninitialized.

To free the buffer, use free_uncached.

Parameters
[in]sizeThe size of the buffer to allocate
Returns
a pointer to the start of the buffer (in the uncached segment)
See also
free_uncached

◆ malloc_uncached_aligned()

void * malloc_uncached_aligned ( int  align,
size_t  size 
)

Allocate a buffer that will be accessed as uncached memory, specifying alignment.

This function is similar to malloc_uncached, but allows to force a higher alignment to the buffer (just like memalign does). See malloc_uncached for reference.

Parameters
[in]alignThe alignment of the buffer in bytes (eg: 64)
[in]sizeThe size of the buffer to allocate
Returns
a pointer to the start of the buffer (in the uncached segment)
See also
malloc_uncached

◆ free_uncached()

void free_uncached ( void *  buf)

Free an uncached memory buffer.

This function frees a memory buffer previously allocated via malloc_uncached.

Parameters
[in]bufThe buffer to free
See also
malloc_uncached

◆ get_tv_type()

tv_type_t get_tv_type ( )

Is system NTSC/PAL/MPAL.

Checks enum hard-coded in PIF BootROM to indicate the tv type of the system.

Returns
enum value indicating PAL, NTSC or MPAL

◆ sys_reset_type()

reset_type_t sys_reset_type ( void  )

Get reset type.

This function returns the reset type, that can be used to differentiate a cold boot from a warm boot (that is, after pressing the reset button).

For instance, a game might want to skip mandatory intros (eg: logos) on a warm boot.