entry.s 5.16 KB
#include "regdef.h"
#include "asm.h"
#include <R4300.h>

BSS(_argc, 4)				
BSS(_argv, 4)				
BSS(_spsave, 4)				

LEAF(_Entry)
	li	v0, SR_BEV|SR_DE
	.set	noreorder
	mtc0	v0,C0_SR		# state unknown on reset
	mtc0	zero,C0_CAUSE		# clear software interrupts
	mtc0	zero,C0_PAGEMASK	# init tlb pgmask
	mtc0	zero,C0_WATCHLO         # clear watchpoint interrupt
	mtc0	zero,C0_WATCHHI

	li	v0,CONFIG_BE|CONFIG_NONCOHRNT|CONFIG_IB
	mtc0	v0,C0_CONFIG
	.set	reorder

	/*
	 * load symmon
	 */
#ifdef _SYMMON
	sw	sp,_spsave
	sw	a0,_argc
	sw	a1,_argv
	la	a2,dbg_start		# location dbgmon will jump back
	jal	_LoadDebugger
dbg_start:
	lw	sp,_spsave		# make sure stack set up
	lw	a0,_argc
	lw	a1,_argv
#endif /* _SYMMON */
	jal	romloader
	END(_Entry)


#define K0_RAMBASE            0x88000000

BSS(icache_size, 4)		# bytes of icache
BSS(dcache_size, 4)		# bytes of dcache
BSS(scache_size, 4)		# bytes of secondary cache

#define	DCACHE_LINESIZE		(4*4)
#define DCACHE_LINEMASK		(DCACHE_LINESIZE-1)

#define	ICACHE_LINESIZE		(8*4)
#define ICACHE_LINEMASK		(ICACHE_LINESIZE-1)

#define	SCACHE_LINESIZE		(32*4)
#define SCACHE_LINEMASK		(SCACHE_LINESIZE-1)

#define	SCACHE_SIZE		(1024*1024)

#define	MIN_CACH_POW2	12

/*
 * _CacheConfigure(void)
 */
LEAF(_CacheConfigure)

	.set	noreorder
	mfc0	t0,C0_CONFIG
	.set reorder

	#
	# Get I-Cache size
	#
	and	t1,t0,CONFIG_IC
	srl	t1,CONFIG_IC_SHFT
	addi	t1,MIN_CACH_POW2
	li	t2,1
	sll	t2,t1
	sw	t2,icache_size

	#
	# Get D-Cache size
	#
	and	t1,t0,CONFIG_DC
	srl	t1,CONFIG_DC_SHFT
	addi	t1,MIN_CACH_POW2
	li	t2,1
	sll	t2,t1
	sw	t2,dcache_size

	#
	# If there is a S-Cache, set size to that of R4000SC
	#
	and	t1,t0,CONFIG_SC
	bnez	t1,1f
	li	t2,SCACHE_SIZE
	sw	t2,scache_size
1:
	j	ra
	END(_CacheConfigure)

/*
 * InvalDCache(void *addr, int nbytes)
 */
LEAF(InvalDCache)
	blez	a1,3f			# If nbytes <= 0, bail
	lw	t3,scache_size
	beqz	t3,6f			# If no S-Cache, just do primary
	bgeu	a1,t3,4f		# Is nbytes >= S-Cache size?
	move	t0,a0
	addu	t1,a0,a1
	bgeu	t0,t1,3f		# (Check for address wrap)
	subu	t1,SCACHE_LINESIZE
	andi	t2,t0,SCACHE_LINEMASK
	beq	t2,zero,1f		# Check if beginning address is aligned
	subu	t0,t2			# If not, back up to cache line address
	.set	noreorder
	cache	CACH_SD|C_HWBINV,0(t0)	# Use hit writeback invalidate on first
	.set	reorder
	bgeu	t0,t1,3f
	addu	t0,SCACHE_LINESIZE
1:
	and	t2,t1,SCACHE_LINEMASK
	beq	t2,zero,2f		# Check if ending address is aligned
	subu	t1,t2
	.set	noreorder
	cache	CACH_SD|C_HWBINV,SCACHE_LINESIZE(t1)
	.set	reorder
	bgtu	t0,t1,3f
2:
	.set	noreorder
	cache	CACH_SD|C_HINV(t0)	# If not, use hit invalidate
	bltu	t0,t1,2b		#  only on given range
	addu	t0,SCACHE_LINESIZE
	.set	reorder
3:
	j	ra
4:
	li	t0,K0_RAMBASE
	addu	t1,t0,t3
	subu	t1,SCACHE_LINESIZE
5:
	.set	noreorder
	cache	CACH_SD|C_IWBINV,0(t0)	# If so, use index writeback invalidate
	bltu	t0,t1,5b		#  on entire cache
	addu	t0,SCACHE_LINESIZE
	.set	reorder

	j	ra
6:
	lw	t3,dcache_size
	bgeu	a1,t3,10f		# Is nbytes >= D-Cache size?
	move	t0,a0
	addu	t1,a0,a1
	bgeu	t0,t1,9f		# (Check for address wrap)
	subu	t1,DCACHE_LINESIZE
	andi	t2,t0,DCACHE_LINEMASK
	beq	t2,zero,7f		# Check if beginning address is aligned
	subu	t0,t2			# If not, back up to cache line address
	.set	noreorder
	cache	CACH_PD|C_HWBINV,0(t0)	# Use hit writeback invalidate on first
	.set	reorder
	bgeu	t0,t1,9f
	addu	t0,DCACHE_LINESIZE
7:
	and	t2,t1,DCACHE_LINEMASK
	beq	t2,zero,8f		# Check if ending address is aligned
	subu	t1,t2
	.set	noreorder
	cache	CACH_PD|C_HWBINV,SCACHE_LINESIZE(t1)
	.set	reorder
	bgtu	t0,t1,9f
8:
	.set	noreorder
	cache	CACH_PD|C_HINV,0(t0)	# If not, use hit invalidate
	bltu	t0,t1,8b		#  only on given range
	addu	t0,DCACHE_LINESIZE
	.set	reorder
9:
	j	ra
10:
	li	t0,K0_RAMBASE
	addu	t1,t0,t3
	subu	t1,DCACHE_LINESIZE
11:
	.set	noreorder
	cache	CACH_PD|C_IWBINV,0(t0)	# If so, use index writeback invalidate
	bltu	t0,t1,11b		#  on entire cache
	addu	t0,DCACHE_LINESIZE
	.set	reorder

	j	ra
	END(InvalDCache)
/*
 * InvalICache(void *addr, int nbytes)
 */
LEAF(InvalICache)
	blez	a1,2f			# If nbytes <= 0, bail
	lw	t3,scache_size
	beqz	t3,5f			# If no S-Cache, just do primary
	bgeu	a1,t3,3f		# Is nbytes >= S-Cache size?
	move	t0,a0
	addu	t1,a0,a1
	bgeu	t0,t1,2f		# (Check for address wrap)
	subu	t1,SCACHE_LINESIZE
	andi	t2,t0,SCACHE_LINEMASK
	subu	t0,t2
1:
	.set	noreorder
	cache	CACH_SD|C_HWBINV,0(t0)	# If not, use hit writeback invalidate
	bltu	t0,t1,1b		#  only on given range
	addu	t0,SCACHE_LINESIZE
	.set	reorder
2:
	j	ra
3:
	li	t0,K0_RAMBASE
	addu	t1,t0,t3
	subu	t1,SCACHE_LINESIZE
4:
	.set	noreorder
	cache	CACH_SD|C_IWBINV,0(t0)	# If so, use index invalidate
	bltu	t0,t1,4b		#  on entire cache
	addu	t0,SCACHE_LINESIZE
	.set	reorder

	j	ra
5:
	lw	t3,icache_size
	bgeu	a1,t3,8f		# Is nbytes >= I-Cache size?
	move	t0,a0
	addu	t1,a0,a1
	bgeu	t0,t1,7f		# (Check for address wrap)
	subu	t1,ICACHE_LINESIZE
	andi	t2,t0,ICACHE_LINEMASK
	subu	t0,t2
6:
	.set	noreorder
	cache	CACH_PI|C_HINV,0(t0)	# If not, use hit invalidate
	bltu	t0,t1,6b		#  only on given range
	addu	t0,ICACHE_LINESIZE
	.set	reorder
7:
	j	ra
8:
	li	t0,K0_RAMBASE
	addu	t1,t0,t3
	subu	t1,ICACHE_LINESIZE
9:
	.set	noreorder
	cache	CACH_PI|C_IINV,0(t0)	# If so, use index invalidate on
	bltu	t0,t1,9b		#  entire cache
	addu	t0,ICACHE_LINESIZE
	.set	reorder

	j	ra
	END(InvalICache)