libdragon
|
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. | |
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.
#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)
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.
#define C0_WRITE_CAUSE | ( | x | ) |
Write the COP0 register $13 (Cause register)
Use this to update it for a custom exception handler.
#define C0_BADVADDR | ( | ) |
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.
#define C0_EPC | ( | ) |
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.
#define C0_INDEX | ( | ) |
Read the COP0 INDEX register.
This register is used during TLB programming. It holds the index of the TLB entry being accessed (0-31).
#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).
#define C0_ENTRYHI | ( | ) |
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.
#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.
#define C0_ENTRYLO0 | ( | ) |
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.
#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.
#define C0_ENTRYLO1 | ( | ) |
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.
#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.
#define C0_PAGEMASK | ( | ) |
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.
#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.
#define C0_WIRED | ( | ) |
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[
#define C0_WATCHLO | ( | ) |
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.
#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.
#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[
#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.
#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.
#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).
#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.
#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.
#define C1_FCR31 | ( | ) |
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.
#define C1_WRITE_FCR31 | ( | x | ) |
Write to the COP1 FCR31 register.
#define UncachedAddr | ( | _addr | ) | ((void *)(((unsigned long)(_addr))|0x20000000)) |
Return the uncached memory address for a given address.
[in] | _addr | Address in RAM to convert to an uncached address |
#define UncachedShortAddr | ( | _addr | ) | ((short *)(((unsigned long)(_addr))|0x20000000)) |
Return the uncached memory address for a given address.
[in] | _addr | Address in RAM to convert to an uncached address |
#define UncachedUShortAddr | ( | _addr | ) | ((unsigned short *)(((unsigned long)(_addr))|0x20000000)) |
Return the uncached memory address for a given address.
[in] | _addr | Address in RAM to convert to an uncached address |
#define UncachedLongAddr | ( | _addr | ) | ((long *)(((unsigned long)(_addr))|0x20000000)) |
Return the uncached memory address for a given address.
[in] | _addr | Address in RAM to convert to an uncached address |
#define UncachedULongAddr | ( | _addr | ) | ((unsigned long *)(((unsigned long)(_addr))|0x20000000)) |
Return the uncached memory address for a given address.
[in] | _addr | Address in RAM to convert to an uncached address |
#define CachedAddr | ( | _addr | ) | ((void *)(((unsigned long)(_addr))&~0x20000000)) |
Return the cached memory address for a given address.
[in] | _addr | Address in RAM to convert to a cached address |
#define PhysicalAddr | ( | _addr | ) |
Return the physical memory address for a given address.
[in] | _addr | Address in RAM to convert to a physical address |
#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.
#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.
#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
#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.
#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.
#define 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.
[in] | addr_ | Pointer to memory in question |
[in] | sz_ | Length in bytes of the data pointed at by addr |
enum tv_type_t |
enum reset_type_t |
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.
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.
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.
void wait_ticks | ( | unsigned long | wait | ) |
Spin wait until the number of ticks have elapsed.
[in] | wait | Number of ticks to wait Maximum accepted value is 0xFFFFFFFF ticks |
void wait_ms | ( | unsigned long | wait_ms | ) |
Spin wait until the number of milliseconds have elapsed.
[in] | wait_ms | Number of milliseconds to wait Maximum accepted value is 91625 ms |
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.
[in] | addr | Pointer to memory in question |
[in] | length | Length in bytes of the data pointed at by addr |
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.
[in] | addr | Pointer to memory in question |
[in] | length | Length in bytes of the data pointed at by addr |
void data_cache_index_writeback_invalidate | ( | volatile void * | addr, |
unsigned long | length | ||
) |
Force a data cache index writeback invalidate over a memory region.
[in] | addr | Pointer to memory in question |
[in] | length | Length in bytes of the data pointed at by addr |
void data_cache_writeback_invalidate_all | ( | void | ) |
Force a data cache writeback invalidate over whole memory.
Also see data_cache_hit_writeback_invalidate
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.
[in] | addr | Pointer to memory in question |
[in] | length | Length in bytes of the data pointed at by addr |
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.
[in] | addr | Pointer to memory in question |
[in] | length | Length in bytes of the data pointed at by addr |
void inst_cache_index_invalidate | ( | volatile void * | addr, |
unsigned long | length | ||
) |
Force an instruction cache index invalidate over a memory region.
[in] | addr | Pointer to memory in question |
[in] | length | Length in bytes of the data pointed at by addr |
void inst_cache_invalidate_all | ( | void | ) |
Force an instruction cache invalidate over whole memory.
Also see inst_cache_hit_invalidate
int get_memory_size | ( | ) |
Get amount of available memory.
bool is_memory_expanded | ( | ) |
Is expansion pak in use.
Checks whether the maximum available memory has been expanded to 8 MiB
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.
[in] | size | The size of the buffer to allocate |
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.
[in] | align | The alignment of the buffer in bytes (eg: 64) |
[in] | size | The size of the buffer to allocate |
void free_uncached | ( | void * | buf | ) |
Free an uncached memory buffer.
This function frees a memory buffer previously allocated via malloc_uncached.
[in] | buf | The buffer to free |
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.
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.