⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vr4300.s

📁 俄罗斯高人Mamaich的Pocket gcc编译器(运行在PocketPC上)的全部源代码。
💻 S
字号:
/* * vr4300.S -- CPU specific support routines * * Copyright (c) 1995,1996 Cygnus Support * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. */#ifndef __mips64	.set mips3#endif#ifdef __mips16/* This file contains 32 bit assembly code.  */	.set nomips16#endif#include "regs.S"	.text	.align	2	# Taken from "R4300 Preliminary RISC Processor Specification	# Revision 2.0 January 1995" page 39: "The Count	# register... increments at a constant rate... at one-half the	# PClock speed."	# We can use this fact to provide small polled delays.	.globl	__cpu_timer_poll	.ent	__cpu_timer_poll__cpu_timer_poll:	.set	noreorder	# in:	a0 = (unsigned int) number of PClock ticks to wait for	# out:	void	# The Vr4300 counter updates at half PClock, so divide by 2 to	# get counter delta:	bnezl	a0, 1f		# continue if delta non-zero	srl	a0, a0, 1	# divide ticks by 2		{DELAY SLOT}	# perform a quick return to the caller:	j	ra	nop			#				{DELAY SLOT}1:	mfc0	v0, $9		# C0_COUNT:  get current counter value	nop	nop	# We cannot just do the simple test, of adding our delta onto	# the current value (ignoring overflow) and then checking for	# equality. The counter is incrementing every two PClocks,	# which means the counter value can change between	# instructions, making it hard to sample at the exact value	# desired.	# However, we do know that our entry delta value is less than	# half the number space (since we divide by 2 on entry). This	# means we can use a difference in signs to indicate timer	# overflow.	addu	a0, v0, a0	# unsigned add (ignore overflow)	# We know have our end value (which will have been	# sign-extended to fill the 64bit register value).2:	# get current counter value:	mfc0	v0, $9	# C0_COUNT	nop	nop	# This is an unsigned 32bit subtraction:	subu	v0, a0, v0	# delta = (end - now)		{DELAY SLOT}	bgtzl	v0, 2b		# looping back is most likely	nop	# We have now been delayed (in the foreground) for AT LEAST	# the required number of counter ticks.	j	ra		# return to caller	nop			#				{DELAY SLOT}	.set	reorder	.end	__cpu_timer_poll	# Flush the processor caches to memory:	.globl	__cpu_flush	.ent	__cpu_flush__cpu_flush:	.set	noreorder	# NOTE: The Vr4300 *CANNOT* have any secondary cache (bit 17	# of the CONFIG registered is hard-wired to 1). We just	# provide code to flush the Data and Instruction caches.	# Even though the Vr4300 has hard-wired cache and cache line	# sizes, we still interpret the relevant Config register	# bits. This allows this code to be used for other conforming	# MIPS architectures if desired.	# Get the config register	mfc0	a0, C0_CONFIG	nop	nop	li	a1, 1		# a useful constant	#	srl	a2, a0, 9	# bits 11..9 for instruction cache size	andi	a2, a2, 0x7	# 3bits of information	add	a2, a2, 12	# get full power-of-2 value	sllv	a2, a1, a2	# instruction cache size	#	srl	a3, a0, 6	# bits 8..6 for data cache size	andi	a3, a3, 0x7	# 3bits of information	add	a3, a3, 12	# get full power-of-2 value	sllv	a3, a1, a3	# data cache size	#	li	a1, (1 << 5)	# check IB (instruction cache line size)	and	a1, a0, a1	# mask against the CONFIG register value	beqz	a1, 1f		# branch on result of delay slot operation	nop	li	a1, 32		# non-zero, then 32bytes	j	2f		# continue	nop1:	li	a1, 16		# 16bytes2:	#	li	t0, (1 << 4)	# check DB (data cache line size)	and	a0, a0, t0	# mask against the CONFIG register value	beqz	a0, 3f		# branch on result of delay slot operation	nop	li	a0, 32		# non-zero, then 32bytes	j	4f		# continue	nop3:	li	a0, 16		# 16bytes4:	#	# a0 = data cache line size	# a1 = instruction cache line size	# a2 = instruction cache size	# a3 = data cache size	#	lui	t0, ((K0BASE >> 16) & 0xFFFF)	ori	t0, t0, (K0BASE & 0xFFFF)	addu	t1, t0, a2	# end cache address	subu	t2, a1, 1	# line size mask	not	t2		# invert the mask	and	t3, t0, t2	# get start address	addu	t1, -1	and	t1, t2		# get end address5:	cache	INDEX_INVALIDATE_I,0(t3)	bne	t3, t1, 5b	addu	t3, a1	#	addu	t1, t0, a3	# end cache address	subu	t2, a0, 1	# line size mask	not	t2		# invert the mask	and	t3, t0, t2	# get start address	addu	t1, -1	and	t1, t2		# get end address6:	cache	INDEX_WRITEBACK_INVALIDATE_D,0(t3)	bne	t3, t1, 6b	addu	t3, a0	#	j	ra	# return to the caller	nop	.set	reorder	.end	__cpu_flush	# NOTE: This variable should *NOT* be addressed relative to	# the $gp register since this code is executed before $gp is	# initialised... hence we leave it in the text area. This will	# cause problems if this routine is ever ROMmed:	.globl	__buserr_cnt__buserr_cnt:	.word	0	.align	3__k1_save:	.word	0	.word	0	.align	2        .ent __buserr        .globl __buserr__buserr:        .set noat	.set noreorder	# k0 and k1 available for use:	mfc0	k0,C0_CAUSE	nop	nop	andi	k0,k0,0x7c	sub	k0,k0,7 << 2	beq	k0,$0,__buserr_do	nop	# call the previous handler	la	k0,__previous	jr	k0	nop	#__buserr_do:	# TODO: check that the cause is indeed a bus error	# - if not then just jump to the previous handler	la	k0,__k1_save	sd	k1,0(k0)	#        la      k1,__buserr_cnt        lw      k0,0(k1)        # increment counter        addu    k0,1        sw      k0,0(k1)	#	la	k0,__k1_save	ld	k1,0(k0)	#        mfc0    k0,C0_EPC	nop	nop        addu    k0,k0,4		# skip offending instruction	mtc0	k0,C0_EPC	# update EPC	nop	nop	eret#        j       k0#        rfe        .set reorder        .set at        .end __buserr__exception_code:	.set noreorder	lui	k0,%hi(__buserr)	daddiu	k0,k0,%lo(__buserr)	jr	k0	nop	.set reorder__exception_code_end:	.data__previous:	.space	(__exception_code_end - __exception_code)	# This subtracting two addresses is working	# but is not garenteed to continue working.	# The assemble reserves the right to put these	# two labels into different frags, and then	# cant take their difference.	.text	.ent	__default_buserr_handler	.globl	__default_buserr_handler__default_buserr_handler:        .set noreorder	# attach our simple bus error handler:	# in:  void	# out: void	mfc0	a0,C0_SR	nop	li	a1,SR_BEV	and	a1,a1,a0	beq	a1,$0,baseaddr	lui	a0,0x8000	# delay slot	lui	a0,0xbfc0	daddiu	a0,a0,0x0200baseaddr:	daddiu	a0,a0,0x0180	# a0 = base vector table address	la	a1,__exception_code_end	la	a2,__exception_code	subu	a1,a1,a2	la	a3,__previous	# there must be a better way of doing this????copyloop:	lw	v0,0(a0)	sw	v0,0(a3)	lw	v0,0(a2)	sw	v0,0(a0)	daddiu	a0,a0,4	daddiu	a2,a2,4	daddiu	a3,a3,4	subu	a1,a1,4	bne	a1,$0,copyloop	nop        la      a0,__buserr_cnt	sw	$0,0(a0)	j	ra	nop        .set reorder	.end	__default_buserr_handler	.ent	__restore_buserr_handler	.globl	__restore_buserr_handler__restore_buserr_handler:        .set noreorder	# restore original (monitor) bus error handler	# in:  void	# out: void	mfc0	a0,C0_SR	nop	li	a1,SR_BEV	and	a1,a1,a0	beq	a1,$0,res_baseaddr	lui	a0,0x8000	# delay slot	lui	a0,0xbfc0	daddiu	a0,a0,0x0200res_baseaddr:	daddiu	a0,a0,0x0180	# a0 = base vector table address	la	a1,__exception_code_end	la	a3,__exception_code	subu	a1,a1,a3	la	a3,__previous	# there must be a better way of doing this????res_copyloop:	lw	v0,0(a3)	sw	v0,0(a0)	daddiu	a0,a0,4	daddiu	a3,a3,4	subu	a1,a1,4	bne	a1,$0,res_copyloop	nop	j	ra	nop        .set reorder	.end	__restore_buserr_handler	.ent	__buserr_count	.globl	__buserr_count__buserr_count:        .set noreorder	# restore original (monitor) bus error handler	# in:  void	# out: unsigned int __buserr_cnt        la      v0,__buserr_cnt	lw	v0,0(v0)	j	ra	nop        .set reorder	.end	__buserr_count/* EOF vr4300.S */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -