📄 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, Ralph Campbell, Sony Corp and * Kazumasa Utashiro of Software Research Associates, Inc. * * 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.3 (Berkeley) 9/23/93 *//* * 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 <machine/adrsmap.h>#include "assym.h"/* #include <machine/endian.h> *//* common endian.h includes function declarations */#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */#define BYTE_ORDER BIG_ENDIAN/* * Amount to take off of the stack for the benefit of the debugger. */#define START_FRAME ((4 * 4) + 4 + 4).text .globl startstart: .set noreorder li t1, MACH_SR_COP_1_BIT # Enable CP1 mtc0 t1, MACH_COP_0_STATUS_REG nop nop ctc1 zero, MACH_FPC_CSR # Clear exceptions of CP1 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. li sp, MACH_CODE_START - START_FRAME la gp, _gp sw zero, START_FRAME - 4(sp) # Zero out old ra for debugger#ifdef news3400 /* a0: bootsw */ /* a1: boot dev */ /* a2: ??? */ /* a3: maxmemory */#endif 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() nop/* proc[1] == /etc/init now running here; run icode */ li v0, PSL_USERSET mtc0 v0, MACH_COP_0_STATUS_REG # switch to user mode li v0, VM_MIN_ADDRESS j v0 # jump to icode rfe .set reorder/* * GCC2 seems to want to call __main in main() for some reason. */LEAF(__main) j raEND(__main)/* * This code is copied to user data space as the first program to run. * Basically, it just calls execve(); */ .globl icodeicode: .set noreorder li a1, VM_MIN_ADDRESS + (9 * 4) # address of 'icode_argv' addu a0, a1, (3 * 4) # address of 'icode_fname' move a2, zero # no environment li v0, SYS_execve # code for execve system call syscall li v0, SYS_exit # code for exit system call syscall # execve failed: call exit()1: b 1b # loop if exit returns nop .set reordericode_argv: .word VM_MIN_ADDRESS + (12 * 4) # address of 'icode_fname' .word VM_MIN_ADDRESS + (15 * 4) # address of 'icodeEnd' .word 0icode_fname: .asciiz "/sbin/init" # occupies 3 words .align 2 .globl icodeEndicodeEnd: .sdata .align 2 .globl szicodeszicode: .word (9 + 3 + 3) * 4 # compute icodeEnd - icode .text/* * 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 sw v0, UADDR+U_PCB_ONFAULT sw zero, badaddr_flag bne a1, 1, 2f lbu v0, (a0) b 5f2: bne a1, 2, 4f lhu v0, (a0) b 5f4: lw v0, (a0)5: sw zero, UADDR+U_PCB_ONFAULT lw v0, badaddr_flag # set by interrupt handler j ra /* * This onfault table entry is not necessary for single processor * machine. But dual processor machine causes exception when * data is loaded from bad address. Onfault table index is also * used to determine if the access is occured during bad address * check. This should be changed to better way. K.U. */baderr: li v0, 1 # trap sends us here j raEND(badaddr)#if BYTE_ORDER == LITTLE_ENDIAN/* * 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 or v0, v0, v1 j raEND(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 or v0, v0, v1 j raEND(htons)#endif/* * bit = ffs(value) */#ifdef NOTDEFLEAF(ffs) move v0, zero beq a0, zero, 2f1: and v1, a0, 1 # bit set? addu v0, v0, 1 srl a0, a0, 1 beq v1, zero, 1b # no, continue2: j raEND(ffs)#endif /* NOTDEF *//* * 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 subu v0, a0, v1 # compute length - 1 for '\0' char j raEND(strlen)/* * strcmp(s1, s2) * 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? bne t0, t1, NotEq lbu t0, 1(a0) # unroll loop lbu t1, 1(a1) add a0, a0, 2 beq t0, zero, LessOrEq # end of first string? add a1, a1, 2 beq t0, t1, 1bNotEq: subu v0, t0, t1 j raLessOrEq: subu v0, zero, t1 j raEND(strcmp)/* * strcmp(s1, s2, length) * NOTE: this version assumes unsigned chars in order to be "8 bit clean". */LEAF(strncmp)1: beq a2, zero, 3f # end of len lbu t0, 0(a0) # get two bytes and compare them lbu t1, 0(a1) beq t0, zero, 2f # end of first string? bne t0, t1, 1f sub a2, a2, 1 beq a2, zero, 3f # end of len lbu t0, 1(a0) # unroll loop lbu t1, 1(a1) add a0, a0, 2 beq t0, zero, 2f # end of first string? add a1, a1, 2 sub a2, a2, 1 beq t0, t1, 1b1: # NotEq subu v0, t0, t1 j ra2: # LessOrEq subu v0, zero, t1 j ra3: # Eq move v0, zero j raEND(strcmp)#if BYTE_ORDER == LITTLE_ENDIAN# define LWHI lwr# define LWLO lwl# define SWHI swr# define SWLO swl#endif#if BYTE_ORDER == BIG_ENDIAN# define LWHI lwl# define LWLO lwr# define SWHI swl# define SWLO swr#endif/* * bzero(s1, n) */LEAF(bzero)ALEAF(blkclr) .set noreorder 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 SWHI 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 doesn't help sw zero, -4(a0) # since we're 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 nop .set reorderEND(bzero)/* * bcmp(s1, s2, n) */LEAF(bcmp) .set noreorder 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 LWHI v0, 0(a0) # read 1, 2, or 3 bytes LWHI 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: LWHI v0, 0(a0) # compare words a0 unaligned, a1 aligned LWLO 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, 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -