龙芯pmon汇编学习

MIPS指令集中:
mtc0 - move to c0 和
mfc0 - move from c0
cfc0 - copy from c0
ctc0 - copy to c0呢?

//uart
https://www.cnblogs.com/blogernice/articles/9850920.html
https://blog.csdn.net/qq543716996/article/details/105219398

//勤为本start.s分析
https://blog.csdn.net/caogos/article/details/78984158

https://blog.csdn.net/kzl1996/article/details/82497413?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242
//mmu tlb

//两个是同一个博客,但解释了循环点a0为何没有自加问题
https://blog.csdn.net/cs_yf/article/details/82288935?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.control&dist_request_id=1328626.20999.16154320787743117&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.control
https://blog.csdn.net/cs_yf/article/details/83154622?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-12.control&dist_request_id=1328627.43.16152959946833501&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-12.control
//

https://blog.csdn.net/u010383937/article/details/73217377?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

https://blog.csdn.net/omnispace/article/details/77600687?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-8&spm=1001.2101.3001.4242

good

MIPS CPU一般采用双相相关联存储器实现TLB,即每个TLB表项包含一对相邻的虚拟地址页(虚拟地址空间上连续)对应两个单独的物理地址(物理地址空间上可以不连续)。
该表项表示将虚拟地址0xe000 0000开始的128MB虚拟地址空间,映射到从0x4000 0000开始的64MB物理地址空间,以及从0x4400 0000开始的64MB物理地址空间,每个物理地址段后面的标志位(C2DVG)表示映射模式。
https://www.cnblogs.com/justin-y-lin/p/13818045.html

https://www.cnblogs.com/Melles/p/10714224.html
http://blog.chinaunix.net/uid-26694208-id-4219768.html

存在问题:
用户太、核心态?

#define	PT_ENTRY_NULL	((pt_entry_t *) 0)

#define PG_WIRED	0x80000000	/* SW */
#define PG_RO		0x40000000	/* SW */

#define	PG_SVPN		0xfffff000	/* Software page no mask */
#define	PG_HVPN		0xffffe000	/* Hardware page no mask */
#define	PG_ODDPG	0x00001000	/* Odd even pte entry */
#define	PG_ASID		0x000000ff	/* Address space ID */
#define	PG_G		0x00000001	/* HW */
#define	PG_V		0x00000002
#define	PG_NV		0x00000000
#define	PG_M		0x00000004
#define	PG_ATTR		0x0000003f
#define	PG_UNCACHED	0x00000010
#define	PG_CACHED	0x00000018
#define	PG_CACHEMODE	0x00000038
#define	PG_ROPAGE	(PG_V | PG_RO | PG_CACHED) /* Write protected */
#define	PG_RWPAGE	(PG_V | PG_M | PG_CACHED)  /* Not wr-prot not clean */
#define	PG_CWPAGE	(PG_V | PG_CACHED)	   /* Not wr-prot but clean */
#define	PG_IOPAGE	(PG_G | PG_V | PG_M | PG_UNCACHED)
#define	PG_FRAME	0x3fffffc0
#define PG_SHIFT	6
#define pfn_is_ext(x) ((x) & 0x3c000000)
#define vad_to_pfn(x) (((unsigned)(x) >> PG_SHIFT) & PG_FRAME)
#define vad_to_pfn64(x) (((quad_t)(x) >> PG_SHIFT) & PG_FRAME)
#define pfn_to_pad(x) (((x) & PG_FRAME) << PG_SHIFT)
#define vad_to_vpn(x) ((unsigned)(x) & PG_SVPN)
#define vpn_to_vad(x) ((x) & PG_SVPN)
/* User viritual to pte page entry */
#define uvtopte(adr) (((adr) >> PGSHIFT) & (NPTEPG -1))

#define	PG_SIZE_4K	0x00000000
#define	PG_SIZE_16K	0x00006000
#define	PG_SIZE_64K	0x0001e000
#define	PG_SIZE_256K	0x0007e000
#define	PG_SIZE_1M	0x001fe000
#define	PG_SIZE_4M	0x007fe000
#define	PG_SIZE_16M	0x01ffe000

#if defined(RM9000)
#define PG_SIZE_64M	0x07ffe000
#define PG_SIZE_256M	0x1fffe000
#endif

##ls1c中TLB初始化代码注释
##ls1c中是将虚拟地址的0xc0000000开始的1G空间映射到物理地址的0xc000 0000中,页面大小设置为16M
##0xc000 0000 以上的物理空间为ddr空间,所以此处映射的是ddr空间。
##为何这段空间要映射?因位mips规定该段地址必须要进行映射才能去使用。。
/*****************
 函数功能:建立映射表,启用MMU
******************/
LEAF(CPU_TLBInit)
	li	a3, 0					   # First TLB index.
	li	a2, PG_SIZE_16M
	MTC0   a2, COP_0_TLB_PG_MASK   # All pages are 16Mb.

1:
	and	a2, a0, PG_SVPN		//PG_SVPN=0xfffff000,所以这里是取a0地址的高20位,舍弃低12位的偏移地址(如果给的地址低位不为零的话),因为后面的EntryHi寄存器需要高位作为虚拟地址
	MTC0   a2, COP_0_TLB_HI	# Set up entry high.

    #设置第一个物理出口地址
	move	a2, a0 		        //再给a2赋值0xc0000000,但是貌似下一句就重新赋值了
	srl	a2, a0, PG_SHIFT  		//PG_SHIFT=6,所以这里是将a0的值逻辑右移6位赋值给a2,a2=0x03000000(这里右移6位目的是将地址高位与EntryLo寄存器的PFN位对齐。需要参考寄存器的定义)
	and	a2, a2, PG_FRAME		//PG_FRAME=0x3fffffc0,这里取a2的值第29-6位,其余位置0,这里实际上a2的值不变(因为EntryLo寄存器的29-6位是PFN,即页帧号,其中29-16位一般作为页帧号的一部分直接写0,不是实际的物理页帧号)
	ori	a2, PG_IOPAGE			//PG_IOPAGE=0x00000017,这里将a2值的第0、1、2、5位置1,所以a2=0x03000017(0000 0011 0000 0000 0000 0000 0001 0111),(这里置1的几位参考寄存器定义,置1表示可用,所以必须这么做)
	MTC0   a2, COP_0_TLB_LO0	# Set up entry low0.		//将a2赋值给EntryLo0寄存器,设置第一个出口物理地址
	
	#设置第二个物理串口地址
	addu	a2, (0x01000000 >> PG_SHIFT)		//0x01000000是16M,右移6位后是0x00040000,这里的a2=0x03040017 (这里为什么要将0x01000000右移6位同样是根据EntryLo寄存器的格式来的,右移六位后,在寄存器的PFN中,代表的同样是0x01000000=16M)
	MTC0   a2, COP_0_TLB_LO1	# Set up entry low1.		//a2赋值给EntryLo1,设置第二个出口物理地址

	mtc0    a3, COP_0_TLB_INDEX	# Set the index.		//设置页号
	addiu	a3, 1			//页号加1,为下次循环准备
	
    #上述映射了两个16M即32M的物理地址,所以下次循环物理地址将偏移32M
	li	a2, 0x02000000		//a2=0x02000000(32M)
	subu	a1, a2		    //a1=0x40000000(1G),所以这里是将1G的空间每次递减,当1G地址空间设置完毕后即可退出
	nop
	tlbwi				# Write the TLB		//写TLB索引号

	bgtz	a1, 1b		//当a1的值大于0的时候,跳转回上一个1处,否则循环结束
	addu	a0, a2		# Step address 32Mb.	//跳转指令结束后,还会执行下一条指令,所以有的地方跳转指令后跟一个nop,这里利用这个特点将虚拟地址空间累加32M,准备下一次的条目设置
	/*******************************************************************
	#此处重点,因为分支延时槽的原因吓一跳指令也会执行。 其实此处也可以写成这样。
	# addu	a0, a2
	# bgtz	a1, 1b
	# nop
	********************************************************************/
	jr	ra		//循环结束后返回
	nop
END(CPU_TLBInit)
posted @ 2021-03-11 17:28  hostid  阅读(376)  评论(0编辑  收藏  举报