📄 locore.s
字号:
/* * 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 + -