libdragon
Loading...
Searching...
No Matches
Files | Data Structures | Macros | Typedefs | 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.
 

Data Structures

struct  heap_stats_t
 Heap statistics. More...
 

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 PhysicalAddr(_addr)
 Return the physical memory address for a given virtual address (pointer)
 
#define VirtualCachedAddr(_addr)   ((void *)(((unsigned long)(_addr))|0x80000000))
 Create a virtual addresses in a cached segment to access a physical address.
 
#define VirtualUncachedAddr(_addr)   ((void *)(((unsigned long)(_addr))|0xA0000000))
 Create a virtual addresses in an uncached segment to access a physical address.
 
#define UncachedAddr(_addr)   ((void *)(((unsigned long)(_addr))|0x20000000))
 Return the uncached memory address for a given virtual 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 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.
 

Typedefs

typedef uint32_t phys_addr_t
 A physical address on the MIPS bus.
 

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 die (void)
 Force a complete halt of all processors.
 
void data_cache_hit_invalidate (volatile void *addr, unsigned long length)
 Force a data cache invalidate over a memory region.
 
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 (void)
 Get amount of available memory.
 
bool is_memory_expanded (void)
 Is expansion pak in use.
 
void assert_memory_expanded (void)
 Assert that the expansion pak is present.
 
void sys_get_heap_stats (heap_stats_t *stats)
 Return information about memory usage of the heap.
 
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 (void)
 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.


Data Structure Documentation

◆ heap_stats_t

struct heap_stats_t

Heap statistics.

Data Fields
int total Total heap size in bytes.
int used Used heap size in bytes.

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.

◆ PhysicalAddr

#define PhysicalAddr (   _addr)
Value:
({ \
const volatile void *_addrp = (_addr); \
(((phys_addr_t)(_addrp))&~0xE0000000); \
})
uint32_t phys_addr_t
A physical address on the MIPS bus.
Definition n64sys.h:75

Return the physical memory address for a given virtual address (pointer)

Parameters
[in]_addrVirtual address to convert to a physical address
Returns
A phys_addr_t containing the physical memory address

◆ VirtualCachedAddr

#define VirtualCachedAddr (   _addr)    ((void *)(((unsigned long)(_addr))|0x80000000))

Create a virtual addresses in a cached segment to access a physical address.

This macro creates a virtual address that can be used to access a physical address in the cached segment of the memory. The cached segment is the segment of memory that is cached by the CPU, and is the default segment for all memory accesses.

The virtual address created by this macro can be used as a pointer in C to access the physical address.

Parameters
[in]_addrPhysical address to convert to a virtual address
Returns
A void pointer to the cached memory address

◆ VirtualUncachedAddr

#define VirtualUncachedAddr (   _addr)    ((void *)(((unsigned long)(_addr))|0xA0000000))

Create a virtual addresses in an uncached segment to access a physical address.

This macro creates a virtual address that can be used to access a physical address in the uncached segment of the memory. The uncached segment is the segment of memory that is not cached by the CPU, and is used for memory that is accessed by hardware devices, like the RCP.

The virtual address created by this macro can be used as a pointer in C to access the physical address.

Parameters
[in]_addrPhysical address to convert to a virtual address
Returns
A void pointer to the uncached memory address

◆ UncachedAddr

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

Return the uncached memory address for a given virtual 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

◆ 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

Typedef Documentation

◆ phys_addr_t

typedef uint32_t phys_addr_t

A physical address on the MIPS bus.

Physical addresses are 32-bit wide, and are used to address the memory space of the MIPS R4300 CPU. The MIPS R4300 CPU has a 32-bit address bus, and can address up to 4 GiB of memory.

Physical addresses are just numbers, they cannot be used as pointers (dereferenced). To access them, you must first convert them virtual addresses using the VirtualCachedAddr or VirtualUncachedAddr macros.

In general, libdragon will try to use phys_addr_t whenever a physical address is expected or returned, and C pointers for virtual addresses. Unfortunately, not all codebase can be changed to follow this convention for backward compatibility reasons.

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

◆ die()

void die ( void  )

Force a complete halt of all processors.

Note
It should occur whenever a reset has been triggered and its past its RESET_TIME_LENGTH grace time period. This function will shut down the RSP and the CPU, blank the VI. Eventually the RDP will flush and complete its work as well. The system will recover after a reset or power cycle.

◆ data_cache_hit_invalidate()

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

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]addrPointer to memory in question
[in]lengthLength in bytes of the data pointed at by addr

◆ 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 ( void  )

Get amount of available memory.

Returns
amount of total available memory in bytes.

◆ is_memory_expanded()

bool is_memory_expanded ( void  )

Is expansion pak in use.

Checks whether the maximum available memory has been expanded to 8 MiB. If your application needs to the use of the expansion pak, you should provide an error message to the user if it is not present. Libdragon offers a function to do this, assert_memory_expanded, which will emit an error

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.

◆ assert_memory_expanded()

void assert_memory_expanded ( void  )

Assert that the expansion pak is present.

This function will emit an error screen if the expansion pak is not present, and will halt the system. It should be called in main() to ensure that the expansion pak is present before proceeding with the rest of the application. This enforces a good pattern to make the application fails early with a proper error message (rather than a crash) if the expansion pak is not present.

If you want to provide your own graphical error screen, use is_memory_expanded instead to check if the expansion pak is present, and then show your own error screen if it is not present.

◆ 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 ( void  )
inline

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.