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

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Digital Equipment Corporation and Ralph Campbell. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Copyright (C) 1989 Digital Equipment Corporation. * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appears in all copies. * Digital Equipment Corporation makes no representations about the * suitability of this software for any purpose.  It is provided "as is" * without express or implied warranty. * * from: $Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, *	v 1.1 89/07/11 17:55:04 nelson Exp $ SPRITE (DECWRL) * from: $Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, *	v 9.2 90/01/29 18:00:39 shirriff Exp $ SPRITE (DECWRL) * from: $Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, *	v 1.1 89/07/10 14:27:41 nelson Exp $ SPRITE (DECWRL) * *	@(#)locore.s	8.5 (Berkeley) 1/4/94 *//* *	Contains code that is the first executed at boot time plus *	assembly language support routines. */#include <sys/errno.h>#include <sys/syscall.h>#include <machine/param.h>#include <machine/psl.h>#include <machine/reg.h>#include <machine/machAsmDefs.h>#include <machine/pte.h>#include "assym.h"	.set	noreorder/* * Amount to take off of the stack for the benefit of the debugger. */#define START_FRAME	((4 * 4) + 4 + 4)	.globl	startstart:	mtc0	zero, MACH_COP_0_STATUS_REG	# Disable interrupts	li	t1, MACH_CACHED_MEMORY_ADDR	# invalid address	mtc0	t1, MACH_COP_0_TLB_HI		# Mark entry high as invalid	mtc0	zero, MACH_COP_0_TLB_LOW	# Zero out low entry./* * Clear the TLB (just to be safe). * Align the starting value (t1), the increment (t2) and the upper bound (t3). */	move	t1, zero	li	t2, 1 << VMMACH_TLB_INDEX_SHIFT	li	t3, VMMACH_NUM_TLB_ENTRIES << VMMACH_TLB_INDEX_SHIFT1:	mtc0	t1, MACH_COP_0_TLB_INDEX	# Set the index register.	addu	t1, t1, t2			# Increment index.	bne	t1, t3, 1b			# NB: always executes next	tlbwi					# Write the TLB entry.	la	sp, start - START_FRAME #	la	gp, _gp	sw	zero, START_FRAME - 4(sp)	# Zero out old ra for debugger	jal	mach_init			# mach_init(argc, argv, envp)	sw	zero, START_FRAME - 8(sp)	# Zero out old fp for debugger	li	t0, MACH_SR_COP_1_BIT		# Disable interrupts and	mtc0	t0, MACH_COP_0_STATUS_REG	#   enable the coprocessor	li	sp, KERNELSTACK - START_FRAME	# switch to standard stack	mfc0	t0, MACH_COP_0_PRID		# read processor ID register	cfc1	t1, MACH_FPC_ID			# read FPU ID register	sw	t0, cpu				# save PRID register	sw	t1, fpu				# save FPU ID register	jal	main				# main(regs)	move	a0, zero/* * proc[1] == /etc/init now running here. * Restore user registers and return. */	.set	noat	li	v0, PSL_USERSET	mtc0	v0, MACH_COP_0_STATUS_REG	# switch to user mode	lw	a0, UADDR+U_PCB_REGS+(SR * 4)	lw	t0, UADDR+U_PCB_REGS+(MULLO * 4)	lw	t1, UADDR+U_PCB_REGS+(MULHI * 4)	mtlo	t0	mthi	t1	lw	k0, UADDR+U_PCB_REGS+(PC * 4)	lw	AT, UADDR+U_PCB_REGS+(AST * 4)	lw	v0, UADDR+U_PCB_REGS+(V0 * 4)	lw	v1, UADDR+U_PCB_REGS+(V1 * 4)	lw	a0, UADDR+U_PCB_REGS+(A0 * 4)	lw	a1, UADDR+U_PCB_REGS+(A1 * 4)	lw	a2, UADDR+U_PCB_REGS+(A2 * 4)	lw	a3, UADDR+U_PCB_REGS+(A3 * 4)	lw	t0, UADDR+U_PCB_REGS+(T0 * 4)	lw	t1, UADDR+U_PCB_REGS+(T1 * 4)	lw	t2, UADDR+U_PCB_REGS+(T2 * 4)	lw	t3, UADDR+U_PCB_REGS+(T3 * 4)	lw	t4, UADDR+U_PCB_REGS+(T4 * 4)	lw	t5, UADDR+U_PCB_REGS+(T5 * 4)	lw	t6, UADDR+U_PCB_REGS+(T6 * 4)	lw	t7, UADDR+U_PCB_REGS+(T7 * 4)	lw	s0, UADDR+U_PCB_REGS+(S0 * 4)	lw	s1, UADDR+U_PCB_REGS+(S1 * 4)	lw	s2, UADDR+U_PCB_REGS+(S2 * 4)	lw	s3, UADDR+U_PCB_REGS+(S3 * 4)	lw	s4, UADDR+U_PCB_REGS+(S4 * 4)	lw	s5, UADDR+U_PCB_REGS+(S5 * 4)	lw	s6, UADDR+U_PCB_REGS+(S6 * 4)	lw	s7, UADDR+U_PCB_REGS+(S7 * 4)	lw	t8, UADDR+U_PCB_REGS+(T8 * 4)	lw	t9, UADDR+U_PCB_REGS+(T9 * 4)	lw	gp, UADDR+U_PCB_REGS+(GP * 4)	lw	sp, UADDR+U_PCB_REGS+(SP * 4)	lw	s8, UADDR+U_PCB_REGS+(S8 * 4)	lw	ra, UADDR+U_PCB_REGS+(RA * 4)	j	k0	rfe	.set	at/* * GCC2 seems to want to call __main in main() for some reason. */LEAF(__main)	j	ra	nopEND(__main)/* * This code is copied the user's stack for returning from signal handlers * (see sendsig() and sigreturn()). We have to compute the address * of the sigcontext struct for the sigreturn call. */	.globl	sigcodesigcode:	addu	a0, sp, 16		# address of sigcontext	li	v0, SYS_sigreturn	# sigreturn(scp)	syscall	break	0			# just in case sigreturn fails	.globl	esigcodeesigcode:/* * Primitives *//* * This table is indexed by u.u_pcb.pcb_onfault in trap(). * The reason for using this table rather than storing an address in * u.u_pcb.pcb_onfault is simply to make the code faster. */	.globl	onfault_table	.data	.align	2onfault_table:	.word	0		# invalid index number#define BADERR		1	.word	baderr#define COPYERR		2	.word	copyerr#define FSWBERR		3	.word	fswberr#define FSWINTRBERR	4	.word	fswintrberr#ifdef KADB#define KADBERR		5	.word	kadberr#endif	.text/* * See if access to addr with a len type instruction causes a machine check. * len is length of access (1=byte, 2=short, 4=long) * * badaddr(addr, len) *	char *addr; *	int len; */LEAF(badaddr)	li	v0, BADERR	bne	a1, 1, 2f	sw	v0, UADDR+U_PCB_ONFAULT	b	5f	lbu	v0, (a0)2:	bne	a1, 2, 4f	nop	b	5f	lhu	v0, (a0)4:	lw	v0, (a0)5:	sw	zero, UADDR+U_PCB_ONFAULT	j	ra	move	v0, zero		# made it w/o errorsbaderr:	j	ra	li	v0, 1			# trap sends us hereEND(badaddr)/* * netorder = htonl(hostorder) * hostorder = ntohl(netorder) */LEAF(htonl)				# a0 = 0x11223344, return 0x44332211ALEAF(ntohl)	srl	v1, a0, 24		# v1 = 0x00000011	sll	v0, a0, 24		# v0 = 0x44000000	or	v0, v0, v1	and	v1, a0, 0xff00	sll	v1, v1, 8		# v1 = 0x00330000	or	v0, v0, v1	srl	v1, a0, 8	and	v1, v1, 0xff00		# v1 = 0x00002200	j	ra	or	v0, v0, v1END(htonl)/* * netorder = htons(hostorder) * hostorder = ntohs(netorder) */LEAF(htons)ALEAF(ntohs)	srl	v0, a0, 8	and	v0, v0, 0xff	sll	v1, a0, 8	and	v1, v1, 0xff00	j	ra	or	v0, v0, v1END(htons)/* * bit = ffs(value) */LEAF(ffs)	beq	a0, zero, 2f	move	v0, zero1:	and	v1, a0, 1		# bit set?	addu	v0, v0, 1	beq	v1, zero, 1b		# no, continue	srl	a0, a0, 12:	j	ra	nopEND(ffs)/* * strlen(str) */LEAF(strlen)	addu	v1, a0, 11:	lb	v0, 0(a0)		# get byte from string	addu	a0, a0, 1		# increment pointer	bne	v0, zero, 1b		# continue if not end	nop	j	ra	subu	v0, a0, v1		# compute length - 1 for '\0' charEND(strlen)/* * NOTE: this version assumes unsigned chars in order to be "8 bit clean". */LEAF(strcmp)1:	lbu	t0, 0(a0)		# get two bytes and compare them	lbu	t1, 0(a1)	beq	t0, zero, LessOrEq	# end of first string?	nop	bne	t0, t1, NotEq	nop	lbu	t0, 1(a0)		# unroll loop	lbu	t1, 1(a1)	beq	t0, zero, LessOrEq	# end of first string?	addu	a0, a0, 2	beq	t0, t1, 1b	addu	a1, a1, 2NotEq:	j	ra	subu	v0, t0, t1LessOrEq:	j	ra	subu	v0, zero, t1END(strcmp)/* * bzero(s1, n) */LEAF(bzero)ALEAF(blkclr)	blt	a1, 12, smallclr	# small amount to clear?	subu	a3, zero, a0		# compute # bytes to word align address	and	a3, a3, 3	beq	a3, zero, 1f		# skip if word aligned	subu	a1, a1, a3		# subtract from remaining count	swr	zero, 0(a0)		# clear 1, 2, or 3 bytes to align	addu	a0, a0, a31:	and	v0, a1, 3		# compute number of words left	subu	a3, a1, v0	move	a1, v0	addu	a3, a3, a0		# compute ending address2:	addu	a0, a0, 4		# clear words	bne	a0, a3, 2b		#  unrolling loop does not help	sw	zero, -4(a0)		#  since we are limited by memory speedsmallclr:	ble	a1, zero, 2f	addu	a3, a1, a0		# compute ending address1:	addu	a0, a0, 1		# clear bytes	bne	a0, a3, 1b	sb	zero, -1(a0)2:	j	ra	nopEND(bzero)/* * bcmp(s1, s2, n) */LEAF(bcmp)	blt	a2, 16, smallcmp	# is it worth any trouble?	xor	v0, a0, a1		# compare low two bits of addresses	and	v0, v0, 3	subu	a3, zero, a1		# compute # bytes to word align address	bne	v0, zero, unalignedcmp	# not possible to align addresses	and	a3, a3, 3	beq	a3, zero, 1f	subu	a2, a2, a3		# subtract from remaining count	move	v0, v1			# init v0,v1 so unmodified bytes match	lwr	v0, 0(a0)		# read 1, 2, or 3 bytes	lwr	v1, 0(a1)	addu	a1, a1, a3	bne	v0, v1, nomatch	addu	a0, a0, a31:	and	a3, a2, ~3		# compute number of whole words left	subu	a2, a2, a3		#   which has to be >= (16-3) & ~3	addu	a3, a3, a0		# compute ending address2:	lw	v0, 0(a0)		# compare words	lw	v1, 0(a1)	addu	a0, a0, 4	bne	v0, v1, nomatch	addu	a1, a1, 4	bne	a0, a3, 2b	nop	b	smallcmp		# finish remainder	nopunalignedcmp:	beq	a3, zero, 2f	subu	a2, a2, a3		# subtract from remaining count	addu	a3, a3, a0		# compute ending address1:	lbu	v0, 0(a0)		# compare bytes until a1 word aligned	lbu	v1, 0(a1)	addu	a0, a0, 1	bne	v0, v1, nomatch	addu	a1, a1, 1	bne	a0, a3, 1b	nop2:	and	a3, a2, ~3		# compute number of whole words left	subu	a2, a2, a3		#   which has to be >= (16-3) & ~3	addu	a3, a3, a0		# compute ending address3:	lwr	v0, 0(a0)		# compare words a0 unaligned, a1 aligned	lwl	v0, 3(a0)	lw	v1, 0(a1)	addu	a0, a0, 4	bne	v0, v1, nomatch	addu	a1, a1, 4	bne	a0, a3, 3b	nopsmallcmp:	ble	a2, zero, match	addu	a3, a2, a0		# compute ending address1:	lbu	v0, 0(a0)	lbu	v1, 0(a1)	addu	a0, a0, 1	bne	v0, v1, nomatch	addu	a1, a1, 1	bne	a0, a3, 1b	nopmatch:	j	ra	move	v0, zeronomatch:	j	ra	li	v0, 1END(bcmp)/* * memcpy(to, from, len) * {ov}bcopy(from, to, len) */LEAF(memcpy)	move	v0, a0			# swap from and to	move	a0, a1	move	a1, v0ALEAF(bcopy)ALEAF(ovbcopy)	addu	t0, a0, a2		# t0 = end of s1 region	sltu	t1, a1, t0	sltu	t2, a0, a1	and	t1, t1, t2		# t1 = true if from < to < (from+len)	beq	t1, zero, forward	# non overlapping, do forward copy	slt	t2, a2, 12		# check for small copy	ble	a2, zero, 2f	addu	t1, a1, a2		# t1 = end of to region1:	lb	v1, -1(t0)		# copy bytes backwards,	subu	t0, t0, 1		#   doesnt happen often so do slow way	subu	t1, t1, 1	bne	t0, a0, 1b	sb	v1, 0(t1)2:	j	ra	nopforward:	bne	t2, zero, smallcpy	# do a small bcopy	xor	v1, a0, a1		# compare low two bits of addresses	and	v1, v1, 3	subu	a3, zero, a1		# compute # bytes to word align address	beq	v1, zero, aligned	# addresses can be word aligned	and	a3, a3, 3	beq	a3, zero, 1f	subu	a2, a2, a3		# subtract from remaining count	lwr	v1, 0(a0)		# get next 4 bytes (unaligned)	lwl	v1, 3(a0)	addu	a0, a0, a3	swr	v1, 0(a1)		# store 1, 2, or 3 bytes to align a1	addu	a1, a1, a31:	and	v1, a2, 3		# compute number of words left	subu	a3, a2, v1	move	a2, v1	addu	a3, a3, a0		# compute ending address2:	lwr	v1, 0(a0)		# copy words a0 unaligned, a1 aligned	lwl	v1, 3(a0)	addu	a0, a0, 4	addu	a1, a1, 4	bne	a0, a3, 2b	sw	v1, -4(a1)	b	smallcpy	nopaligned:

⌨️ 快捷键说明

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