mirror of
https://github.com/zeldaret/mm.git
synced 2026-05-23 06:54:14 -04:00
Handwritten asm: OS functions, libm_vals (#1821)
* Handwritten asm: OS functions, libm_vals * rm hardware_regs.ld * andi -> and, addiu -> addu * CACHE macro
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
|
||||
.rdata
|
||||
|
||||
DATA(__libm_qnan_f)
|
||||
.word 0x7F810000
|
||||
ENDDATA(__libm_qnan_f)
|
||||
@@ -22,13 +22,13 @@ LEAF(osGetIntMask)
|
||||
.set noreorder
|
||||
/* Extract interrupt enable bits from current SR */
|
||||
mfc0 v0, C0_SR
|
||||
andi v0, v0, (SR_IMASK | SR_IE)
|
||||
and v0, v0, (SR_IMASK | SR_IE)
|
||||
/* Get value of __OSGlobalIntMask */
|
||||
la t0, __OSGlobalIntMask
|
||||
lw t1, (t0)
|
||||
/* Bitwise-OR in the disabled CPU bits of __OSGlobalIntMask */
|
||||
xor t0, t1, ~0
|
||||
andi t0, t0, SR_IMASK
|
||||
and t0, t0, SR_IMASK
|
||||
or v0, v0, t0
|
||||
/* Fetch MI_INTR_MASK_REG */
|
||||
lw t1, PHYS_TO_K1(MI_INTR_MASK_REG)
|
||||
@@ -40,7 +40,7 @@ LEAF(osGetIntMask)
|
||||
/* Bitwise-OR in the disabled RCP bits of __OSGlobalIntMask */
|
||||
srl t0, t0, RCP_IMASKSHIFT
|
||||
xor t0, t0, ~0
|
||||
andi t0, t0, (RCP_IMASK >> RCP_IMASKSHIFT)
|
||||
and t0, t0, (RCP_IMASK >> RCP_IMASKSHIFT)
|
||||
or t1, t1, t0
|
||||
1:
|
||||
/* Shift the RCP bits to not conflict with the CPU bits */
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
#include "PR/os_thread.h"
|
||||
|
||||
.text
|
||||
|
||||
LEAF(__osDisableInt)
|
||||
la t2, __OSGlobalIntMask
|
||||
lw t3, (t2)
|
||||
and t3, t3, SR_IMASK
|
||||
MFC0( t0, C0_SR)
|
||||
and t1, t0, ~SR_IE
|
||||
MTC0( t1, C0_SR)
|
||||
and v0, t0, SR_IE
|
||||
lw t0, (t2)
|
||||
and t0, t0, SR_IMASK
|
||||
.set noreorder
|
||||
beq t0, t3, No_Change_Global_Int
|
||||
/*! @bug this la should be lw, it may never come up in practice as to reach this code
|
||||
*! the CPU bits of __OSGlobalIntMask must have changed while this function is running.
|
||||
*/
|
||||
la t2, __osRunningThread
|
||||
lw t1, THREAD_SR(t2)
|
||||
and t2, t1, SR_IMASK
|
||||
and t2, t2, t0
|
||||
.set reorder
|
||||
and t1, t1, ~SR_IMASK
|
||||
or t1, t1, t2
|
||||
and t1, t1, ~SR_IE
|
||||
MTC0( t1, C0_SR)
|
||||
NOP
|
||||
NOP
|
||||
No_Change_Global_Int:
|
||||
jr ra
|
||||
END(__osDisableInt)
|
||||
|
||||
LEAF(__osRestoreInt)
|
||||
MFC0( t0, C0_SR)
|
||||
or t0, t0, a0
|
||||
MTC0( t0, C0_SR)
|
||||
NOP
|
||||
NOP
|
||||
jr ra
|
||||
END(__osRestoreInt)
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
|
||||
.text
|
||||
|
||||
/**
|
||||
* void osInvalDCache(void* vaddr, s32 nbytes);
|
||||
*
|
||||
* Invalidates the CPU Data Cache for `nbytes` at `vaddr`.
|
||||
* The cache is not automatically synced with physical memory, so cache
|
||||
* lines must be invalidated to ensure old data is not used in place of
|
||||
* newly available data supplied by an external agent in a DMA operation.
|
||||
*
|
||||
* If `vaddr` is not aligned to a cache line boundary, or nbytes is not a
|
||||
* multiple of the data cache line size (16 bytes) a larger region is
|
||||
* invalidated.
|
||||
*
|
||||
* If the amount to invalidate is at least the data cache size (DCACHE_SIZE),
|
||||
* the entire data cache is invalidated.
|
||||
*/
|
||||
LEAF(osInvalDCache)
|
||||
/* If the amount to invalidate is less than or equal to 0, return immediately */
|
||||
blez a1, 3f
|
||||
/* If the amount to invalidate is as large as or larger than
|
||||
* the data cache size, invalidate all */
|
||||
li t3, DCACHE_SIZE
|
||||
bgeu a1, t3, 4f
|
||||
/* Ensure end address doesn't wrap around and end up smaller
|
||||
* than the start address */
|
||||
move t0, a0
|
||||
addu t1, a0, a1
|
||||
bgeu t0, t1, 3f
|
||||
/* Mask start with cache line */
|
||||
addu t1, t1, -DCACHE_LINESIZE
|
||||
and t2, t0, DCACHE_LINEMASK
|
||||
/* If mask is not zero, the start is not cache aligned */
|
||||
beqz t2, 1f
|
||||
/* Subtract mask result to align to cache line */
|
||||
subu t0, t0, t2
|
||||
/* Hit-Writeback-Invalidate unaligned part */
|
||||
CACHE( (CACH_PD | C_HWBINV), (t0))
|
||||
/* If that's all there is to do, return early */
|
||||
bgeu t0, t1, 3f
|
||||
addu t0, t0, DCACHE_LINESIZE
|
||||
1:
|
||||
/* Mask end with cache line */
|
||||
and t2, t1, DCACHE_LINEMASK
|
||||
/* If mask is not zero, the end is not cache aligned */
|
||||
beqz t2, 2f
|
||||
/* Subtract mask result to align to cache line */
|
||||
subu t1, t1, t2
|
||||
/* Hit-Writeback-Invalidate unaligned part */
|
||||
CACHE( (CACH_PD | C_HWBINV), DCACHE_LINESIZE(t1))
|
||||
/* If that's all there is to do, return early */
|
||||
bltu t1, t0, 3f
|
||||
/* Invalidate the rest */
|
||||
2:
|
||||
/* Hit-Invalidate */
|
||||
CACHE( (CACH_PD | C_HINV), (t0))
|
||||
.set noreorder
|
||||
bltu t0, t1, 2b
|
||||
addu t0, t0, DCACHE_LINESIZE
|
||||
.set reorder
|
||||
3:
|
||||
jr ra
|
||||
|
||||
4:
|
||||
li t0, K0BASE
|
||||
addu t1, t0, t3
|
||||
addu t1, t1, -DCACHE_LINESIZE
|
||||
5:
|
||||
/* Index-Writeback-Invalidate */
|
||||
CACHE( (CACH_PD | C_IWBINV), (t0))
|
||||
.set noreorder
|
||||
bltu t0, t1, 5b
|
||||
addu t0, DCACHE_LINESIZE
|
||||
.set reorder
|
||||
jr ra
|
||||
END(osInvalDCache)
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
|
||||
.text
|
||||
|
||||
LEAF(osInvalICache)
|
||||
/* If the amount to invalidate is less than or equal to 0, return immediately */
|
||||
blez a1, 2f
|
||||
/* If the amount to invalidate is as large as or larger than */
|
||||
/* the instruction cache size, invalidate all */
|
||||
li t3, ICACHE_SIZE
|
||||
bgeu a1, t3, 3f
|
||||
/* ensure end address doesn't wrap around and end up smaller */
|
||||
/* than the start address */
|
||||
move t0, a0
|
||||
addu t1, a0, a1
|
||||
bgeu t0, t1, 2f
|
||||
/* Mask and subtract to align to cache line */
|
||||
addu t1, t1, -ICACHE_LINESIZE
|
||||
and t2, t0, ICACHE_LINEMASK
|
||||
subu t0, t0, t2
|
||||
1:
|
||||
CACHE( (CACH_PI | C_HINV), (t0))
|
||||
.set noreorder
|
||||
bltu t0, t1, 1b
|
||||
addu t0, t0, ICACHE_LINESIZE
|
||||
.set reorder
|
||||
2:
|
||||
jr ra
|
||||
|
||||
3:
|
||||
li t0, K0BASE
|
||||
addu t1, t0, t3
|
||||
addu t1, t1, -ICACHE_LINESIZE
|
||||
4:
|
||||
CACHE( (CACH_PI | C_IINV), (t0))
|
||||
.set noreorder
|
||||
bltu t0, t1, 4b
|
||||
addu t0, ICACHE_LINESIZE
|
||||
.set reorder
|
||||
jr ra
|
||||
.set reorder
|
||||
END(osInvalICache)
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
#include "PR/rdb.h"
|
||||
|
||||
.text
|
||||
|
||||
LEAF(osMapTLBRdb)
|
||||
MFC0( t0, C0_ENTRYHI)
|
||||
li t1, NTLBENTRIES
|
||||
MTC0( t1, C0_INX)
|
||||
MTC0( zero, C0_PAGEMASK)
|
||||
li t2, (TLBLO_UNCACHED | TLBLO_D | TLBLO_V | TLBLO_G)
|
||||
li t1, (RDB_BASE_REG & TLBHI_VPN2MASK)
|
||||
MTC0( t1, C0_ENTRYHI)
|
||||
/* Possible bug? Virtual address instead of physical address set as page frame number */
|
||||
li t1, RDB_BASE_VIRTUAL_ADDR
|
||||
srl t3, t1, TLBLO_PFNSHIFT
|
||||
or t3, t3, t2
|
||||
MTC0( t3, C0_ENTRYLO0)
|
||||
li t1, TLBLO_G
|
||||
MTC0( t1, C0_ENTRYLO1)
|
||||
NOP
|
||||
TLBWI
|
||||
NOP
|
||||
NOP
|
||||
NOP
|
||||
NOP
|
||||
MTC0( t0, C0_ENTRYHI)
|
||||
jr ra
|
||||
END(osMapTLBRdb)
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
|
||||
.text
|
||||
|
||||
/**
|
||||
* u32 __osProbeTLB(void* vaddr);
|
||||
*
|
||||
* Searches the TLB for the physical address associated with
|
||||
* the virtual address `vaddr`.
|
||||
*
|
||||
* Returns the physical address if found, or -1 if not found.
|
||||
*/
|
||||
LEAF(__osProbeTLB)
|
||||
.set noreorder
|
||||
/* Set C0_ENTRYHI based on supplied vaddr */
|
||||
mfc0 t0, C0_ENTRYHI
|
||||
and t1, t0, TLBHI_PIDMASK
|
||||
and t2, a0, TLBHI_VPN2MASK
|
||||
or t1, t1, t2
|
||||
mtc0 t1, C0_ENTRYHI
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
/* TLB probe, sets C0_INX to a value matching C0_ENTRYHI. */
|
||||
/* If no match is found the TLBINX_PROBE bit is set to indicate this. */
|
||||
tlbp
|
||||
nop
|
||||
nop
|
||||
/* Read result */
|
||||
mfc0 t3, C0_INX
|
||||
and t3, t3, TLBINX_PROBE
|
||||
/* Branch if no match was found */
|
||||
bnez t3, 3f
|
||||
nop
|
||||
|
||||
/* Read TLB, sets C0_ENTRYHI, C0_ENTRYLO0, C0_ENTRYLO1 and C0_PAGEMASK for the TLB */
|
||||
/* entry indicated by C0_INX */
|
||||
tlbr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
/* Calculate page size = (page mask + 0x2000) >> 1 */
|
||||
mfc0 t3, C0_PAGEMASK
|
||||
add t3, t3, 0x2000
|
||||
srl t3, t3, 1
|
||||
/* & with vaddr */
|
||||
and t4, t3, a0
|
||||
/* Select C0_ENTRYLO0 or C0_ENTRYLO1 */
|
||||
bnez t4, 1f
|
||||
add t3, t3, -1 /* make bitmask out of page size */
|
||||
mfc0 v0, C0_ENTRYLO0
|
||||
b 2f
|
||||
nop
|
||||
1:
|
||||
mfc0 v0, C0_ENTRYLO1
|
||||
2:
|
||||
/* Check valid bit and branch if not valid */
|
||||
and t5, v0, TLBLO_V
|
||||
beqz t5, 3f
|
||||
nop
|
||||
|
||||
/* Extract the Page Frame Number from the entry */
|
||||
and v0, v0, TLBLO_PFNMASK
|
||||
sll v0, v0, TLBLO_PFNSHIFT
|
||||
/* Mask vaddr with page size mask */
|
||||
and t5, a0, t3
|
||||
/* Add masked vaddr to pfn to obtain the physical address */
|
||||
add v0, v0, t5
|
||||
b 4f
|
||||
nop
|
||||
3:
|
||||
/* No physical address for the supplied virtual address was found, */
|
||||
/* return -1 */
|
||||
li v0, -1
|
||||
4:
|
||||
/* Restore original C0_ENTRYHI value before returning */
|
||||
mtc0 t0, C0_ENTRYHI
|
||||
jr ra
|
||||
nop
|
||||
.set reorder
|
||||
END(__osProbeTLB)
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
|
||||
.text
|
||||
|
||||
LEAF(osUnmapTLBAll)
|
||||
MFC0( t0, C0_ENTRYHI)
|
||||
li t1, (NTLBENTRIES - 1)
|
||||
li t2, (K0BASE & TLBHI_VPN2MASK)
|
||||
MTC0( t2, C0_ENTRYHI)
|
||||
MTC0( zero, C0_ENTRYLO0)
|
||||
MTC0( zero, C0_ENTRYLO1)
|
||||
1:
|
||||
MTC0( t1, C0_INX)
|
||||
NOP
|
||||
TLBWI
|
||||
NOP
|
||||
NOP
|
||||
addi t1, t1, -1
|
||||
bgez t1, 1b
|
||||
|
||||
MTC0( t0, C0_ENTRYHI)
|
||||
jr ra
|
||||
END(osUnmapTLBAll)
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
|
||||
.text
|
||||
|
||||
/**
|
||||
* void osWritebackDCache(void* vaddr, s32 nbytes);
|
||||
*
|
||||
* Writes back the contents of the data cache to main memory for `nbytes` at `vaddr`.
|
||||
* If `nbytes` is as large as or larger than the data cache size, the entire cache is
|
||||
* written back.
|
||||
*/
|
||||
LEAF(osWritebackDCache)
|
||||
/* If the amount to write back is less than or equal to 0, return immediately */
|
||||
blez a1, 2f
|
||||
|
||||
/* If the amount to write back is as large as or larger than */
|
||||
/* the data cache size, write back all */
|
||||
li t3, DCACHE_SIZE
|
||||
bgeu a1, t3, 3f
|
||||
|
||||
/* ensure end address doesn't wrap around and end up smaller */
|
||||
/* than the start address */
|
||||
move t0, a0
|
||||
addu t1, a0, a1
|
||||
bgeu t0, t1, 2f
|
||||
|
||||
/* Mask and subtract to align to cache line */
|
||||
addu t1, t1, -DCACHE_LINESIZE
|
||||
and t2, t0, DCACHE_LINEMASK
|
||||
subu t0, t0, t2
|
||||
1:
|
||||
CACHE( (CACH_PD | C_HWB), (t0))
|
||||
.set noreorder
|
||||
bltu t0, t1, 1b
|
||||
addu t0, t0, DCACHE_LINESIZE
|
||||
.set reorder
|
||||
2:
|
||||
jr ra
|
||||
|
||||
/* same as osWritebackDCacheAll in operation */
|
||||
3:
|
||||
li t0, K0BASE
|
||||
addu t1, t0, t3
|
||||
addu t1, t1, -DCACHE_LINESIZE
|
||||
4:
|
||||
CACHE( (CACH_PD | C_IWBINV), (t0))
|
||||
.set noreorder
|
||||
bltu t0, t1, 4b
|
||||
addu t0, DCACHE_LINESIZE
|
||||
.set reorder
|
||||
jr ra
|
||||
END(osWritebackDCache)
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
|
||||
.text
|
||||
|
||||
LEAF(osWritebackDCacheAll)
|
||||
li t0, K0BASE
|
||||
li t2, DCACHE_SIZE
|
||||
addu t1, t0, t2
|
||||
addu t1, t1, -DCACHE_LINESIZE
|
||||
1:
|
||||
CACHE( (CACH_PD | C_IWBINV), (t0))
|
||||
.set noreorder
|
||||
bltu t0, t1, 1b
|
||||
addu t0, DCACHE_LINESIZE
|
||||
.set reorder
|
||||
jr ra
|
||||
END(osWritebackDCacheAll)
|
||||
Reference in New Issue
Block a user