From 479e34aa413b33082abe4f0de5e3b984e4685163 Mon Sep 17 00:00:00 2001 From: soda Date: Sun, 23 Jan 2000 20:45:01 +0000 Subject: [PATCH] merge to NetBSD-current (DeskStation and Algor support is currently broken) --- sys/arch/arc/arc/cpu_exec.c | 112 - sys/arch/arc/arc/fp.S | 3611 ------------------------ sys/arch/arc/arc/genassym.cf | 57 - sys/arch/arc/arc/locore.S | 4178 ---------------------------- sys/arch/arc/arc/mem.c | 182 -- sys/arch/arc/arc/pmap.c | 1615 ----------- sys/arch/arc/arc/process_machdep.c | 116 - sys/arch/arc/arc/swapgeneric.c | 61 - sys/arch/arc/arc/sys_machdep.c | 128 - sys/arch/arc/arc/trap.c | 1741 ------------ sys/arch/arc/arc/vm_machdep.c | 468 ---- sys/arch/arc/compile/.cvsignore | 5 - sys/arch/arc/conf/ld.script | 74 - sys/arch/arc/include/dlfcn.h | 42 - sys/arch/arc/include/ecoff.h | 94 - sys/arch/arc/include/elf_abi.h | 58 - sys/arch/arc/include/exec.h | 56 - sys/arch/arc/include/frame.h | 0 sys/arch/arc/include/link.h | 125 - sys/arch/arc/include/memconf.h | 50 - 20 files changed, 12773 deletions(-) delete mode 100644 sys/arch/arc/arc/cpu_exec.c delete mode 100644 sys/arch/arc/arc/fp.S delete mode 100644 sys/arch/arc/arc/genassym.cf delete mode 100644 sys/arch/arc/arc/locore.S delete mode 100644 sys/arch/arc/arc/mem.c delete mode 100644 sys/arch/arc/arc/pmap.c delete mode 100644 sys/arch/arc/arc/process_machdep.c delete mode 100644 sys/arch/arc/arc/swapgeneric.c delete mode 100644 sys/arch/arc/arc/sys_machdep.c delete mode 100644 sys/arch/arc/arc/trap.c delete mode 100644 sys/arch/arc/arc/vm_machdep.c delete mode 100644 sys/arch/arc/compile/.cvsignore delete mode 100644 sys/arch/arc/conf/ld.script delete mode 100644 sys/arch/arc/include/dlfcn.h delete mode 100644 sys/arch/arc/include/ecoff.h delete mode 100644 sys/arch/arc/include/elf_abi.h delete mode 100644 sys/arch/arc/include/exec.h delete mode 100644 sys/arch/arc/include/frame.h delete mode 100644 sys/arch/arc/include/link.h delete mode 100644 sys/arch/arc/include/memconf.h diff --git a/sys/arch/arc/arc/cpu_exec.c b/sys/arch/arc/arc/cpu_exec.c deleted file mode 100644 index 8d7087e349d7..000000000000 --- a/sys/arch/arc/arc/cpu_exec.c +++ /dev/null @@ -1,112 +0,0 @@ -/* $OpenBSD: cpu_exec.c,v 1.4 1997/04/19 17:19:41 pefo Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by 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. - * - * @(#)machdep.c 8.3 (Berkeley) 1/12/94 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#if defined(_KERN_DO_ECOFF) -void cpu_exec_ecoff_setregs __P((struct proc *, struct exec_package *, - u_long, register_t *)); -#endif -/* - * cpu_exec_aout_makecmds(): - * cpu-dependent a.out format hook for execve(). - * - * Determine of the given exec package refers to something which we - * understand and, if so, set up the vmcmds for it. - * - */ -int -cpu_exec_aout_makecmds(p, epp) - struct proc *p; - struct exec_package *epp; -{ - return ENOEXEC; -} - - -#if defined(_KERN_DO_ECOFF) -void -cpu_exec_ecoff_setregs(p, pack, stack, retval) - struct proc *p; - struct exec_package *pack; - u_long stack; - register_t *retval; -{ - struct ecoff_aouthdr *eap; - - setregs(p, pack, stack, retval); - eap = (struct ecoff_aouthdr *) - ((caddr_t)pack->ep_hdr + sizeof(struct ecoff_filehdr)); - p->p_md.md_regs[GP] = eap->ea_gp_value; -} - -/* - * cpu_exec_ecoff_hook(): - * cpu-dependent ECOFF format hook for execve(). - * - * Do any machine-dependent diddling of the exec package when doing ECOFF. - * - */ -int -cpu_exec_ecoff_hook(p, epp) - struct proc *p; - struct exec_package *epp; -{ -#ifdef COMPAT_ULTRIX - extern struct emul emul_ultrix; -#endif - -#if defined(COMPAT_ULTRIX) - epp->ep_emul = &emul_ultrix; -#endif - return 0; -} - -#endif /* _KERN_DO_ECOFF */ diff --git a/sys/arch/arc/arc/fp.S b/sys/arch/arc/arc/fp.S deleted file mode 100644 index a164eaa45602..000000000000 --- a/sys/arch/arc/arc/fp.S +++ /dev/null @@ -1,3611 +0,0 @@ -/* $OpenBSD: fp.S,v 1.1.1.1 1996/06/24 09:07:20 pefo Exp $ */ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * 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. - * - * from: @(#)fp.s 8.1 (Berkeley) 6/10/93 - * $Id: fp.S,v 1.1.1.1 2000/01/23 20:24:24 soda Exp $ - */ - -/* - * Standard header stuff. - */ - -#include -#include -#include - -#include "assym.h" - -#define SEXP_INF 0xff -#define DEXP_INF 0x7ff -#define SEXP_BIAS 127 -#define DEXP_BIAS 1023 -#define SEXP_MIN -126 -#define DEXP_MIN -1022 -#define SEXP_MAX 127 -#define DEXP_MAX 1023 -#define WEXP_MAX 30 /* maximum unbiased exponent for int */ -#define WEXP_MIN -1 /* minimum unbiased exponent for int */ -#define SFRAC_BITS 23 -#define DFRAC_BITS 52 -#define SIMPL_ONE 0x00800000 -#define DIMPL_ONE 0x00100000 -#define SLEAD_ZEROS 31 - 23 -#define DLEAD_ZEROS 31 - 20 -#define STICKYBIT 1 -#define GUARDBIT 0x80000000 -#define SSIGNAL_NAN 0x00400000 -#define DSIGNAL_NAN 0x00080000 -#define SQUIET_NAN 0x003fffff -#define DQUIET_NAN0 0x0007ffff -#define DQUIET_NAN1 0xffffffff -#define INT_MIN 0x80000000 -#define INT_MAX 0x7fffffff - -#define COND_UNORDERED 0x1 -#define COND_EQUAL 0x2 -#define COND_LESS 0x4 -#define COND_SIGNAL 0x8 - -/*---------------------------------------------------------------------------- - * - * MachEmulateFP -- - * - * Emulate unimplemented floating point operations. - * This routine should only be called by MachFPInterrupt(). - * - * MachEmulateFP(instr) - * unsigned instr; - * - * Results: - * None. - * - * Side effects: - * Floating point registers are modified according to instruction. - * - *---------------------------------------------------------------------------- - */ -NON_LEAF(MachEmulateFP, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - sw ra, STAND_RA_OFFSET(sp) -/* - * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0). - */ - srl v0, a0, 21 - 2 # get FMT field - and v0, v0, 0xF << 2 # mask FMT field - and v1, a0, 0x3F # mask FUNC field - sll v1, v1, 5 # align for table lookup - bgt v0, 4 << 2, ill # illegal format - - or v1, v1, v0 - cfc1 a1, FPC_CSR # get exception register - lw a3, func_fmt_tbl(v1) # switch on FUNC & FMT - and a1, a1, ~FPC_EXCEPTION_UNIMPL # clear exception - ctc1 a1, FPC_CSR - j a3 - - .rdata -func_fmt_tbl: - .word add_s # 0 - .word add_d # 0 - .word ill # 0 - .word ill # 0 - .word ill # 0 - .word ill # 0 - .word ill # 0 - .word ill # 0 - .word sub_s # 1 - .word sub_d # 1 - .word ill # 1 - .word ill # 1 - .word ill # 1 - .word ill # 1 - .word ill # 1 - .word ill # 1 - .word mul_s # 2 - .word mul_d # 2 - .word ill # 2 - .word ill # 2 - .word ill # 2 - .word ill # 2 - .word ill # 2 - .word ill # 2 - .word div_s # 3 - .word div_d # 3 - .word ill # 3 - .word ill # 3 - .word ill # 3 - .word ill # 3 - .word ill # 3 - .word ill # 3 - .word ill # 4 - .word ill # 4 - .word ill # 4 - .word ill # 4 - .word ill # 4 - .word ill # 4 - .word ill # 4 - .word ill # 4 - .word abs_s # 5 - .word abs_d # 5 - .word ill # 5 - .word ill # 5 - .word ill # 5 - .word ill # 5 - .word ill # 5 - .word ill # 5 - .word mov_s # 6 - .word mov_d # 6 - .word ill # 6 - .word ill # 6 - .word ill # 6 - .word ill # 6 - .word ill # 6 - .word ill # 6 - .word neg_s # 7 - .word neg_d # 7 - .word ill # 7 - .word ill # 7 - .word ill # 7 - .word ill # 7 - .word ill # 7 - .word ill # 7 - .word ill # 8 - .word ill # 8 - .word ill # 8 - .word ill # 8 - .word ill # 8 - .word ill # 8 - .word ill # 8 - .word ill # 8 - .word ill # 9 - .word ill # 9 - .word ill # 9 - .word ill # 9 - .word ill # 9 - .word ill # 9 - .word ill # 9 - .word ill # 9 - .word ill # 10 - .word ill # 10 - .word ill # 10 - .word ill # 10 - .word ill # 10 - .word ill # 10 - .word ill # 10 - .word ill # 10 - .word ill # 11 - .word ill # 11 - .word ill # 11 - .word ill # 11 - .word ill # 11 - .word ill # 11 - .word ill # 11 - .word ill # 11 - .word ill # 12 - .word ill # 12 - .word ill # 12 - .word ill # 12 - .word ill # 12 - .word ill # 12 - .word ill # 12 - .word ill # 12 - .word ill # 13 - .word ill # 13 - .word ill # 13 - .word ill # 13 - .word ill # 13 - .word ill # 13 - .word ill # 13 - .word ill # 13 - .word ill # 14 - .word ill # 14 - .word ill # 14 - .word ill # 14 - .word ill # 14 - .word ill # 14 - .word ill # 14 - .word ill # 14 - .word ill # 15 - .word ill # 15 - .word ill # 15 - .word ill # 15 - .word ill # 15 - .word ill # 15 - .word ill # 15 - .word ill # 15 - .word ill # 16 - .word ill # 16 - .word ill # 16 - .word ill # 16 - .word ill # 16 - .word ill # 16 - .word ill # 16 - .word ill # 16 - .word ill # 17 - .word ill # 17 - .word ill # 17 - .word ill # 17 - .word ill # 17 - .word ill # 17 - .word ill # 17 - .word ill # 17 - .word ill # 18 - .word ill # 18 - .word ill # 18 - .word ill # 18 - .word ill # 18 - .word ill # 18 - .word ill # 18 - .word ill # 18 - .word ill # 19 - .word ill # 19 - .word ill # 19 - .word ill # 19 - .word ill # 19 - .word ill # 19 - .word ill # 19 - .word ill # 19 - .word ill # 20 - .word ill # 20 - .word ill # 20 - .word ill # 20 - .word ill # 20 - .word ill # 20 - .word ill # 20 - .word ill # 20 - .word ill # 21 - .word ill # 21 - .word ill # 21 - .word ill # 21 - .word ill # 21 - .word ill # 21 - .word ill # 21 - .word ill # 21 - .word ill # 22 - .word ill # 22 - .word ill # 22 - .word ill # 22 - .word ill # 22 - .word ill # 22 - .word ill # 22 - .word ill # 22 - .word ill # 23 - .word ill # 23 - .word ill # 23 - .word ill # 23 - .word ill # 23 - .word ill # 23 - .word ill # 23 - .word ill # 23 - .word ill # 24 - .word ill # 24 - .word ill # 24 - .word ill # 24 - .word ill # 24 - .word ill # 24 - .word ill # 24 - .word ill # 24 - .word ill # 25 - .word ill # 25 - .word ill # 25 - .word ill # 25 - .word ill # 25 - .word ill # 25 - .word ill # 25 - .word ill # 25 - .word ill # 26 - .word ill # 26 - .word ill # 26 - .word ill # 26 - .word ill # 26 - .word ill # 26 - .word ill # 26 - .word ill # 26 - .word ill # 27 - .word ill # 27 - .word ill # 27 - .word ill # 27 - .word ill # 27 - .word ill # 27 - .word ill # 27 - .word ill # 27 - .word ill # 28 - .word ill # 28 - .word ill # 28 - .word ill # 28 - .word ill # 28 - .word ill # 28 - .word ill # 28 - .word ill # 28 - .word ill # 29 - .word ill # 29 - .word ill # 29 - .word ill # 29 - .word ill # 29 - .word ill # 29 - .word ill # 29 - .word ill # 29 - .word ill # 30 - .word ill # 30 - .word ill # 30 - .word ill # 30 - .word ill # 30 - .word ill # 30 - .word ill # 30 - .word ill # 30 - .word ill # 31 - .word ill # 31 - .word ill # 31 - .word ill # 31 - .word ill # 31 - .word ill # 31 - .word ill # 31 - .word ill # 31 - .word ill # 32 - .word cvt_s_d # 32 - .word ill # 32 - .word ill # 32 - .word cvt_s_w # 32 - .word ill # 32 - .word ill # 32 - .word ill # 32 - .word cvt_d_s # 33 - .word ill # 33 - .word ill # 33 - .word ill # 33 - .word cvt_d_w # 33 - .word ill # 33 - .word ill # 33 - .word ill # 33 - .word ill # 34 - .word ill # 34 - .word ill # 34 - .word ill # 34 - .word ill # 34 - .word ill # 34 - .word ill # 34 - .word ill # 34 - .word ill # 35 - .word ill # 35 - .word ill # 35 - .word ill # 35 - .word ill # 35 - .word ill # 35 - .word ill # 35 - .word ill # 35 - .word cvt_w_s # 36 - .word cvt_w_d # 36 - .word ill # 36 - .word ill # 36 - .word ill # 36 - .word ill # 36 - .word ill # 36 - .word ill # 36 - .word ill # 37 - .word ill # 37 - .word ill # 37 - .word ill # 37 - .word ill # 37 - .word ill # 37 - .word ill # 37 - .word ill # 37 - .word ill # 38 - .word ill # 38 - .word ill # 38 - .word ill # 38 - .word ill # 38 - .word ill # 38 - .word ill # 38 - .word ill # 38 - .word ill # 39 - .word ill # 39 - .word ill # 39 - .word ill # 39 - .word ill # 39 - .word ill # 39 - .word ill # 39 - .word ill # 39 - .word ill # 40 - .word ill # 40 - .word ill # 40 - .word ill # 40 - .word ill # 40 - .word ill # 40 - .word ill # 40 - .word ill # 40 - .word ill # 41 - .word ill # 41 - .word ill # 41 - .word ill # 41 - .word ill # 41 - .word ill # 41 - .word ill # 41 - .word ill # 41 - .word ill # 42 - .word ill # 42 - .word ill # 42 - .word ill # 42 - .word ill # 42 - .word ill # 42 - .word ill # 42 - .word ill # 42 - .word ill # 43 - .word ill # 43 - .word ill # 43 - .word ill # 43 - .word ill # 43 - .word ill # 43 - .word ill # 43 - .word ill # 43 - .word ill # 44 - .word ill # 44 - .word ill # 44 - .word ill # 44 - .word ill # 44 - .word ill # 44 - .word ill # 44 - .word ill # 44 - .word ill # 45 - .word ill # 45 - .word ill # 45 - .word ill # 45 - .word ill # 45 - .word ill # 45 - .word ill # 45 - .word ill # 45 - .word ill # 46 - .word ill # 46 - .word ill # 46 - .word ill # 46 - .word ill # 46 - .word ill # 46 - .word ill # 46 - .word ill # 46 - .word ill # 47 - .word ill # 47 - .word ill # 47 - .word ill # 47 - .word ill # 47 - .word ill # 47 - .word ill # 47 - .word ill # 47 - .word cmp_s # 48 - .word cmp_d # 48 - .word ill # 48 - .word ill # 48 - .word ill # 48 - .word ill # 48 - .word ill # 48 - .word ill # 48 - .word cmp_s # 49 - .word cmp_d # 49 - .word ill # 49 - .word ill # 49 - .word ill # 49 - .word ill # 49 - .word ill # 49 - .word ill # 49 - .word cmp_s # 50 - .word cmp_d # 50 - .word ill # 50 - .word ill # 50 - .word ill # 50 - .word ill # 50 - .word ill # 50 - .word ill # 50 - .word cmp_s # 51 - .word cmp_d # 51 - .word ill # 51 - .word ill # 51 - .word ill # 51 - .word ill # 51 - .word ill # 51 - .word ill # 51 - .word cmp_s # 52 - .word cmp_d # 52 - .word ill # 52 - .word ill # 52 - .word ill # 52 - .word ill # 52 - .word ill # 52 - .word ill # 52 - .word cmp_s # 53 - .word cmp_d # 53 - .word ill # 53 - .word ill # 53 - .word ill # 53 - .word ill # 53 - .word ill # 53 - .word ill # 53 - .word cmp_s # 54 - .word cmp_d # 54 - .word ill # 54 - .word ill # 54 - .word ill # 54 - .word ill # 54 - .word ill # 54 - .word ill # 54 - .word cmp_s # 55 - .word cmp_d # 55 - .word ill # 55 - .word ill # 55 - .word ill # 55 - .word ill # 55 - .word ill # 55 - .word ill # 55 - .word cmp_s # 56 - .word cmp_d # 56 - .word ill # 56 - .word ill # 56 - .word ill # 56 - .word ill # 56 - .word ill # 56 - .word ill # 56 - .word cmp_s # 57 - .word cmp_d # 57 - .word ill # 57 - .word ill # 57 - .word ill # 57 - .word ill # 57 - .word ill # 57 - .word ill # 57 - .word cmp_s # 58 - .word cmp_d # 58 - .word ill # 58 - .word ill # 58 - .word ill # 58 - .word ill # 58 - .word ill # 58 - .word ill # 58 - .word cmp_s # 59 - .word cmp_d # 59 - .word ill # 59 - .word ill # 59 - .word ill # 59 - .word ill # 59 - .word ill # 59 - .word ill # 59 - .word cmp_s # 60 - .word cmp_d # 60 - .word ill # 60 - .word ill # 60 - .word ill # 60 - .word ill # 60 - .word ill # 60 - .word ill # 60 - .word cmp_s # 61 - .word cmp_d # 61 - .word ill # 61 - .word ill # 61 - .word ill # 61 - .word ill # 61 - .word ill # 61 - .word ill # 61 - .word cmp_s # 62 - .word cmp_d # 62 - .word ill # 62 - .word ill # 62 - .word ill # 62 - .word ill # 62 - .word ill # 62 - .word ill # 62 - .word cmp_s # 63 - .word cmp_d # 63 - .word ill # 63 - .word ill # 63 - .word ill # 63 - .word ill # 63 - .word ill # 63 - .word ill # 63 - .text - -/* - * Single precision subtract. - */ -sub_s: - jal get_ft_fs_s - xor t4, t4, 1 # negate FT sign bit - b add_sub_s -/* - * Single precision add. - */ -add_s: - jal get_ft_fs_s -add_sub_s: - bne t1, SEXP_INF, 1f # is FS an infinity? - bne t5, SEXP_INF, result_fs_s # if FT is not inf, result=FS - bne t2, zero, result_fs_s # if FS is NAN, result is FS - bne t6, zero, result_ft_s # if FT is NAN, result is FT - bne t0, t4, invalid_s # both infinities same sign? - b result_fs_s # result is in FS -1: - beq t5, SEXP_INF, result_ft_s # if FT is inf, result=FT - bne t1, zero, 4f # is FS a denormalized num? - beq t2, zero, 3f # is FS zero? - bne t5, zero, 2f # is FT a denormalized num? - beq t6, zero, result_fs_s # FT is zero, result=FS - jal renorm_fs_s - jal renorm_ft_s - b 5f -2: - jal renorm_fs_s - subu t5, t5, SEXP_BIAS # unbias FT exponent - or t6, t6, SIMPL_ONE # set implied one bit - b 5f -3: - bne t5, zero, result_ft_s # if FT != 0, result=FT - bne t6, zero, result_ft_s - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - bne v0, FPC_ROUND_RM, 1f # round to -infinity? - or t0, t0, t4 # compute result sign - b result_fs_s -1: - and t0, t0, t4 # compute result sign - b result_fs_s -4: - bne t5, zero, 2f # is FT a denormalized num? - beq t6, zero, result_fs_s # FT is zero, result=FS - subu t1, t1, SEXP_BIAS # unbias FS exponent - or t2, t2, SIMPL_ONE # set implied one bit - jal renorm_ft_s - b 5f -2: - subu t1, t1, SEXP_BIAS # unbias FS exponent - or t2, t2, SIMPL_ONE # set implied one bit - subu t5, t5, SEXP_BIAS # unbias FT exponent - or t6, t6, SIMPL_ONE # set implied one bit -/* - * Perform the addition. - */ -5: - move t8, zero # no shifted bits (sticky reg) - beq t1, t5, 4f # no shift needed - subu v0, t1, t5 # v0 = difference of exponents - move v1, v0 # v1 = abs(difference) - bge v0, zero, 1f - negu v1 -1: - ble v1, SFRAC_BITS+2, 2f # is difference too great? - li t8, STICKYBIT # set the sticky bit - bge v0, zero, 1f # check which exp is larger - move t1, t5 # result exp is FTs - move t2, zero # FSs fraction shifted is zero - b 4f -1: - move t6, zero # FTs fraction shifted is zero - b 4f -2: - li t9, 32 # compute 32 - abs(exp diff) - subu t9, t9, v1 - bgt v0, zero, 3f # if FS > FT, shift FTs frac - move t1, t5 # FT > FS, result exp is FTs - sll t8, t2, t9 # save bits shifted out - srl t2, t2, v1 # shift FSs fraction - b 4f -3: - sll t8, t6, t9 # save bits shifted out - srl t6, t6, v1 # shift FTs fraction -4: - bne t0, t4, 1f # if signs differ, subtract - addu t2, t2, t6 # add fractions - b norm_s -1: - blt t2, t6, 3f # subtract larger from smaller - bne t2, t6, 2f # if same, result=0 - move t1, zero # result=0 - move t2, zero - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - bne v0, FPC_ROUND_RM, 1f # round to -infinity? - or t0, t0, t4 # compute result sign - b result_fs_s -1: - and t0, t0, t4 # compute result sign - b result_fs_s -2: - sltu t9, zero, t8 # compute t2:zero - t6:t8 - subu t8, zero, t8 - subu t2, t2, t6 # subtract fractions - subu t2, t2, t9 # subtract barrow - b norm_s -3: - move t0, t4 # sign of result = FTs - sltu t9, zero, t8 # compute t6:zero - t2:t8 - subu t8, zero, t8 - subu t2, t6, t2 # subtract fractions - subu t2, t2, t9 # subtract barrow - b norm_s - -/* - * Double precision subtract. - */ -sub_d: - jal get_ft_fs_d - xor t4, t4, 1 # negate sign bit - b add_sub_d -/* - * Double precision add. - */ -add_d: - jal get_ft_fs_d -add_sub_d: - bne t1, DEXP_INF, 1f # is FS an infinity? - bne t5, DEXP_INF, result_fs_d # if FT is not inf, result=FS - bne t2, zero, result_fs_d # if FS is NAN, result is FS - bne t3, zero, result_fs_d - bne t6, zero, result_ft_d # if FT is NAN, result is FT - bne t7, zero, result_ft_d - bne t0, t4, invalid_d # both infinities same sign? - b result_fs_d # result is in FS -1: - beq t5, DEXP_INF, result_ft_d # if FT is inf, result=FT - bne t1, zero, 4f # is FS a denormalized num? - bne t2, zero, 1f # is FS zero? - beq t3, zero, 3f -1: - bne t5, zero, 2f # is FT a denormalized num? - bne t6, zero, 1f - beq t7, zero, result_fs_d # FT is zero, result=FS -1: - jal renorm_fs_d - jal renorm_ft_d - b 5f -2: - jal renorm_fs_d - subu t5, t5, DEXP_BIAS # unbias FT exponent - or t6, t6, DIMPL_ONE # set implied one bit - b 5f -3: - bne t5, zero, result_ft_d # if FT != 0, result=FT - bne t6, zero, result_ft_d - bne t7, zero, result_ft_d - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - bne v0, FPC_ROUND_RM, 1f # round to -infinity? - or t0, t0, t4 # compute result sign - b result_fs_d -1: - and t0, t0, t4 # compute result sign - b result_fs_d -4: - bne t5, zero, 2f # is FT a denormalized num? - bne t6, zero, 1f - beq t7, zero, result_fs_d # FT is zero, result=FS -1: - subu t1, t1, DEXP_BIAS # unbias FS exponent - or t2, t2, DIMPL_ONE # set implied one bit - jal renorm_ft_d - b 5f -2: - subu t1, t1, DEXP_BIAS # unbias FS exponent - or t2, t2, DIMPL_ONE # set implied one bit - subu t5, t5, DEXP_BIAS # unbias FT exponent - or t6, t6, DIMPL_ONE # set implied one bit -/* - * Perform the addition. - */ -5: - move t8, zero # no shifted bits (sticky reg) - beq t1, t5, 4f # no shift needed - subu v0, t1, t5 # v0 = difference of exponents - move v1, v0 # v1 = abs(difference) - bge v0, zero, 1f - negu v1 -1: - ble v1, DFRAC_BITS+2, 2f # is difference too great? - li t8, STICKYBIT # set the sticky bit - bge v0, zero, 1f # check which exp is larger - move t1, t5 # result exp is FTs - move t2, zero # FSs fraction shifted is zero - move t3, zero - b 4f -1: - move t6, zero # FTs fraction shifted is zero - move t7, zero - b 4f -2: - li t9, 32 - bge v0, zero, 3f # if FS > FT, shift FTs frac - move t1, t5 # FT > FS, result exp is FTs - blt v1, t9, 1f # shift right by < 32? - subu v1, v1, t9 - subu t9, t9, v1 - sll t8, t2, t9 # save bits shifted out - sltu t9, zero, t3 # dont lose any one bits - or t8, t8, t9 # save sticky bit - srl t3, t2, v1 # shift FSs fraction - move t2, zero - b 4f -1: - subu t9, t9, v1 - sll t8, t3, t9 # save bits shifted out - srl t3, t3, v1 # shift FSs fraction - sll t9, t2, t9 # save bits shifted out of t2 - or t3, t3, t9 # and put into t3 - srl t2, t2, v1 - b 4f -3: - blt v1, t9, 1f # shift right by < 32? - subu v1, v1, t9 - subu t9, t9, v1 - sll t8, t6, t9 # save bits shifted out - srl t7, t6, v1 # shift FTs fraction - move t6, zero - b 4f -1: - subu t9, t9, v1 - sll t8, t7, t9 # save bits shifted out - srl t7, t7, v1 # shift FTs fraction - sll t9, t6, t9 # save bits shifted out of t2 - or t7, t7, t9 # and put into t3 - srl t6, t6, v1 -4: - bne t0, t4, 1f # if signs differ, subtract - addu t3, t3, t7 # add fractions - sltu t9, t3, t7 # compute carry - addu t2, t2, t6 # add fractions - addu t2, t2, t9 # add carry - b norm_d -1: - blt t2, t6, 3f # subtract larger from smaller - bne t2, t6, 2f - bltu t3, t7, 3f - bne t3, t7, 2f # if same, result=0 - move t1, zero # result=0 - move t2, zero - move t3, zero - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - bne v0, FPC_ROUND_RM, 1f # round to -infinity? - or t0, t0, t4 # compute result sign - b result_fs_d -1: - and t0, t0, t4 # compute result sign - b result_fs_d -2: - beq t8, zero, 1f # compute t2:t3:zero - t6:t7:t8 - subu t8, zero, t8 - sltu v0, t3, 1 # compute barrow out - subu t3, t3, 1 # subtract barrow - subu t2, t2, v0 -1: - sltu v0, t3, t7 - subu t3, t3, t7 # subtract fractions - subu t2, t2, t6 # subtract fractions - subu t2, t2, v0 # subtract barrow - b norm_d -3: - move t0, t4 # sign of result = FTs - beq t8, zero, 1f # compute t6:t7:zero - t2:t3:t8 - subu t8, zero, t8 - sltu v0, t7, 1 # compute barrow out - subu t7, t7, 1 # subtract barrow - subu t6, t6, v0 -1: - sltu v0, t7, t3 - subu t3, t7, t3 # subtract fractions - subu t2, t6, t2 # subtract fractions - subu t2, t2, v0 # subtract barrow - b norm_d - -/* - * Single precision multiply. - */ -mul_s: - jal get_ft_fs_s - xor t0, t0, t4 # compute sign of result - move t4, t0 - bne t1, SEXP_INF, 2f # is FS an infinity? - bne t2, zero, result_fs_s # if FS is a NAN, result=FS - bne t5, SEXP_INF, 1f # FS is inf, is FT an infinity? - bne t6, zero, result_ft_s # if FT is a NAN, result=FT - b result_fs_s # result is infinity -1: - bne t5, zero, result_fs_s # inf * zero? if no, result=FS - bne t6, zero, result_fs_s - b invalid_s # infinity * zero is invalid -2: - bne t5, SEXP_INF, 1f # FS != inf, is FT an infinity? - bne t1, zero, result_ft_s # zero * inf? if no, result=FT - bne t2, zero, result_ft_s - bne t6, zero, result_ft_s # if FT is a NAN, result=FT - b invalid_s # zero * infinity is invalid -1: - bne t1, zero, 1f # is FS zero? - beq t2, zero, result_fs_s # result is zero - jal renorm_fs_s - b 2f -1: - subu t1, t1, SEXP_BIAS # unbias FS exponent - or t2, t2, SIMPL_ONE # set implied one bit -2: - bne t5, zero, 1f # is FT zero? - beq t6, zero, result_ft_s # result is zero - jal renorm_ft_s - b 2f -1: - subu t5, t5, SEXP_BIAS # unbias FT exponent - or t6, t6, SIMPL_ONE # set implied one bit -2: - addu t1, t1, t5 # compute result exponent - addu t1, t1, 9 # account for binary point - multu t2, t6 # multiply fractions - mflo t8 - mfhi t2 - b norm_s - -/* - * Double precision multiply. - */ -mul_d: - jal get_ft_fs_d - xor t0, t0, t4 # compute sign of result - move t4, t0 - bne t1, DEXP_INF, 2f # is FS an infinity? - bne t2, zero, result_fs_d # if FS is a NAN, result=FS - bne t3, zero, result_fs_d - bne t5, DEXP_INF, 1f # FS is inf, is FT an infinity? - bne t6, zero, result_ft_d # if FT is a NAN, result=FT - bne t7, zero, result_ft_d - b result_fs_d # result is infinity -1: - bne t5, zero, result_fs_d # inf * zero? if no, result=FS - bne t6, zero, result_fs_d - bne t7, zero, result_fs_d - b invalid_d # infinity * zero is invalid -2: - bne t5, DEXP_INF, 1f # FS != inf, is FT an infinity? - bne t1, zero, result_ft_d # zero * inf? if no, result=FT - bne t2, zero, result_ft_d # if FS is a NAN, result=FS - bne t3, zero, result_ft_d - bne t6, zero, result_ft_d # if FT is a NAN, result=FT - bne t7, zero, result_ft_d - b invalid_d # zero * infinity is invalid -1: - bne t1, zero, 2f # is FS zero? - bne t2, zero, 1f - beq t3, zero, result_fs_d # result is zero -1: - jal renorm_fs_d - b 3f -2: - subu t1, t1, DEXP_BIAS # unbias FS exponent - or t2, t2, DIMPL_ONE # set implied one bit -3: - bne t5, zero, 2f # is FT zero? - bne t6, zero, 1f - beq t7, zero, result_ft_d # result is zero -1: - jal renorm_ft_d - b 3f -2: - subu t5, t5, DEXP_BIAS # unbias FT exponent - or t6, t6, DIMPL_ONE # set implied one bit -3: - addu t1, t1, t5 # compute result exponent - addu t1, t1, 12 # ??? - multu t3, t7 # multiply fractions (low * low) - move t4, t2 # free up t2,t3 for result - move t5, t3 - mflo a3 # save low order bits - mfhi t8 - not v0, t8 - multu t4, t7 # multiply FS(high) * FT(low) - mflo v1 - mfhi t3 # init low result - sltu v0, v0, v1 # compute carry - addu t8, v1 - multu t5, t6 # multiply FS(low) * FT(high) - addu t3, t3, v0 # add carry - not v0, t8 - mflo v1 - mfhi t2 - sltu v0, v0, v1 - addu t8, v1 - multu t4, t6 # multiply FS(high) * FT(high) - addu t3, v0 - not v1, t3 - sltu v1, v1, t2 - addu t3, t2 - not v0, t3 - mfhi t2 - addu t2, v1 - mflo v1 - sltu v0, v0, v1 - addu t2, v0 - addu t3, v1 - sltu a3, zero, a3 # reduce t8,a3 to just t8 - or t8, a3 - b norm_d - -/* - * Single precision divide. - */ -div_s: - jal get_ft_fs_s - xor t0, t0, t4 # compute sign of result - move t4, t0 - bne t1, SEXP_INF, 1f # is FS an infinity? - bne t2, zero, result_fs_s # if FS is NAN, result is FS - bne t5, SEXP_INF, result_fs_s # is FT an infinity? - bne t6, zero, result_ft_s # if FT is NAN, result is FT - b invalid_s # infinity/infinity is invalid -1: - bne t5, SEXP_INF, 1f # is FT an infinity? - bne t6, zero, result_ft_s # if FT is NAN, result is FT - move t1, zero # x / infinity is zero - move t2, zero - b result_fs_s -1: - bne t1, zero, 2f # is FS zero? - bne t2, zero, 1f - bne t5, zero, result_fs_s # FS=zero, is FT zero? - beq t6, zero, invalid_s # 0 / 0 - b result_fs_s # result = zero -1: - jal renorm_fs_s - b 3f -2: - subu t1, t1, SEXP_BIAS # unbias FS exponent - or t2, t2, SIMPL_ONE # set implied one bit -3: - bne t5, zero, 2f # is FT zero? - bne t6, zero, 1f - or a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0 - and v0, a1, FPC_ENABLE_DIV0 # trap enabled? - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - li t1, SEXP_INF # result is infinity - move t2, zero - b result_fs_s -1: - jal renorm_ft_s - b 3f -2: - subu t5, t5, SEXP_BIAS # unbias FT exponent - or t6, t6, SIMPL_ONE # set implied one bit -3: - subu t1, t1, t5 # compute exponent - subu t1, t1, 3 # compensate for result position - li v0, SFRAC_BITS+3 # number of bits to divide - move t8, t2 # init dividend - move t2, zero # init result -1: - bltu t8, t6, 3f # is dividend >= divisor? -2: - subu t8, t8, t6 # subtract divisor from dividend - or t2, t2, 1 # remember that we did - bne t8, zero, 3f # if not done, continue - sll t2, t2, v0 # shift result to final position - b norm_s -3: - sll t8, t8, 1 # shift dividend - sll t2, t2, 1 # shift result - subu v0, v0, 1 # are we done? - bne v0, zero, 1b # no, continue - b norm_s - -/* - * Double precision divide. - */ -div_d: - jal get_ft_fs_d - xor t0, t0, t4 # compute sign of result - move t4, t0 - bne t1, DEXP_INF, 1f # is FS an infinity? - bne t2, zero, result_fs_d # if FS is NAN, result is FS - bne t3, zero, result_fs_d - bne t5, DEXP_INF, result_fs_d # is FT an infinity? - bne t6, zero, result_ft_d # if FT is NAN, result is FT - bne t7, zero, result_ft_d - b invalid_d # infinity/infinity is invalid -1: - bne t5, DEXP_INF, 1f # is FT an infinity? - bne t6, zero, result_ft_d # if FT is NAN, result is FT - bne t7, zero, result_ft_d - move t1, zero # x / infinity is zero - move t2, zero - move t3, zero - b result_fs_d -1: - bne t1, zero, 2f # is FS zero? - bne t2, zero, 1f - bne t3, zero, 1f - bne t5, zero, result_fs_d # FS=zero, is FT zero? - bne t6, zero, result_fs_d - beq t7, zero, invalid_d # 0 / 0 - b result_fs_d # result = zero -1: - jal renorm_fs_d - b 3f -2: - subu t1, t1, DEXP_BIAS # unbias FS exponent - or t2, t2, DIMPL_ONE # set implied one bit -3: - bne t5, zero, 2f # is FT zero? - bne t6, zero, 1f - bne t7, zero, 1f - or a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0 - and v0, a1, FPC_ENABLE_DIV0 # trap enabled? - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # Save exceptions - li t1, DEXP_INF # result is infinity - move t2, zero - move t3, zero - b result_fs_d -1: - jal renorm_ft_d - b 3f -2: - subu t5, t5, DEXP_BIAS # unbias FT exponent - or t6, t6, DIMPL_ONE # set implied one bit -3: - subu t1, t1, t5 # compute exponent - subu t1, t1, 3 # compensate for result position - li v0, DFRAC_BITS+3 # number of bits to divide - move t8, t2 # init dividend - move t9, t3 - move t2, zero # init result - move t3, zero -1: - bltu t8, t6, 3f # is dividend >= divisor? - bne t8, t6, 2f - bltu t9, t7, 3f -2: - sltu v1, t9, t7 # subtract divisor from dividend - subu t9, t9, t7 - subu t8, t8, t6 - subu t8, t8, v1 - or t3, t3, 1 # remember that we did - bne t8, zero, 3f # if not done, continue - bne t9, zero, 3f - li v1, 32 # shift result to final position - blt v0, v1, 2f # shift < 32 bits? - subu v0, v0, v1 # shift by > 32 bits - sll t2, t3, v0 # shift upper part - move t3, zero - b norm_d -2: - subu v1, v1, v0 # shift by < 32 bits - sll t2, t2, v0 # shift upper part - srl t9, t3, v1 # save bits shifted out - or t2, t2, t9 # and put into upper part - sll t3, t3, v0 - b norm_d -3: - sll t8, t8, 1 # shift dividend - srl v1, t9, 31 # save bit shifted out - or t8, t8, v1 # and put into upper part - sll t9, t9, 1 - sll t2, t2, 1 # shift result - srl v1, t3, 31 # save bit shifted out - or t2, t2, v1 # and put into upper part - sll t3, t3, 1 - subu v0, v0, 1 # are we done? - bne v0, zero, 1b # no, continue - sltu v0, zero, t9 # be sure to save any one bits - or t8, t8, v0 # from the lower remainder - b norm_d - -/* - * Single precision absolute value. - */ -abs_s: - jal get_fs_s - move t0, zero # set sign positive - b result_fs_s - -/* - * Double precision absolute value. - */ -abs_d: - jal get_fs_d - move t0, zero # set sign positive - b result_fs_d - -/* - * Single precision move. - */ -mov_s: - jal get_fs_s - b result_fs_s - -/* - * Double precision move. - */ -mov_d: - jal get_fs_d - b result_fs_d - -/* - * Single precision negate. - */ -neg_s: - jal get_fs_s - xor t0, t0, 1 # reverse sign - b result_fs_s - -/* - * Double precision negate. - */ -neg_d: - jal get_fs_d - xor t0, t0, 1 # reverse sign - b result_fs_d - -/* - * Convert double to single. - */ -cvt_s_d: - jal get_fs_d - bne t1, DEXP_INF, 1f # is FS an infinity? - li t1, SEXP_INF # convert to single - sll t2, t2, 3 # convert D fraction to S - srl t8, t3, 32 - 3 - or t2, t2, t8 - b result_fs_s -1: - bne t1, zero, 2f # is FS zero? - bne t2, zero, 1f - beq t3, zero, result_fs_s # result=0 -1: - jal renorm_fs_d - subu t1, t1, 3 # correct exp for shift below - b 3f -2: - subu t1, t1, DEXP_BIAS # unbias exponent - or t2, t2, DIMPL_ONE # add implied one bit -3: - sll t2, t2, 3 # convert D fraction to S - srl t8, t3, 32 - 3 - or t2, t2, t8 - sll t8, t3, 3 - b norm_noshift_s - -/* - * Convert integer to single. - */ -cvt_s_w: - jal get_fs_int - bne t2, zero, 1f # check for zero - move t1, zero - b result_fs_s -/* - * Find out how many leading zero bits are in t2 and put in t9. - */ -1: - move v0, t2 - move t9, zero - srl v1, v0, 16 - bne v1, zero, 1f - addu t9, 16 - sll v0, 16 -1: - srl v1, v0, 24 - bne v1, zero, 1f - addu t9, 8 - sll v0, 8 -1: - srl v1, v0, 28 - bne v1, zero, 1f - addu t9, 4 - sll v0, 4 -1: - srl v1, v0, 30 - bne v1, zero, 1f - addu t9, 2 - sll v0, 2 -1: - srl v1, v0, 31 - bne v1, zero, 1f - addu t9, 1 -/* - * Now shift t2 the correct number of bits. - */ -1: - subu t9, t9, SLEAD_ZEROS # dont count leading zeros - li t1, 23 # init exponent - subu t1, t1, t9 # compute exponent - beq t9, zero, 1f - li v0, 32 - blt t9, zero, 2f # if shift < 0, shift right - subu v0, v0, t9 - sll t2, t2, t9 # shift left -1: - add t1, t1, SEXP_BIAS # bias exponent - and t2, t2, ~SIMPL_ONE # clear implied one bit - b result_fs_s -2: - negu t9 # shift right by t9 - subu v0, v0, t9 - sll t8, t2, v0 # save bits shifted out - srl t2, t2, t9 - b norm_noshift_s - -/* - * Convert single to double. - */ -cvt_d_s: - jal get_fs_s - move t3, zero - bne t1, SEXP_INF, 1f # is FS an infinity? - li t1, DEXP_INF # convert to double - b result_fs_d -1: - bne t1, zero, 2f # is FS denormalized or zero? - beq t2, zero, result_fs_d # is FS zero? - jal renorm_fs_s - move t8, zero - b norm_d -2: - addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly - sll t3, t2, 32 - 3 # convert S fraction to D - srl t2, t2, 3 - b result_fs_d - -/* - * Convert integer to double. - */ -cvt_d_w: - jal get_fs_int - bne t2, zero, 1f # check for zero - move t1, zero # result=0 - move t3, zero - b result_fs_d -/* - * Find out how many leading zero bits are in t2 and put in t9. - */ -1: - move v0, t2 - move t9, zero - srl v1, v0, 16 - bne v1, zero, 1f - addu t9, 16 - sll v0, 16 -1: - srl v1, v0, 24 - bne v1, zero, 1f - addu t9, 8 - sll v0, 8 -1: - srl v1, v0, 28 - bne v1, zero, 1f - addu t9, 4 - sll v0, 4 -1: - srl v1, v0, 30 - bne v1, zero, 1f - addu t9, 2 - sll v0, 2 -1: - srl v1, v0, 31 - bne v1, zero, 1f - addu t9, 1 -/* - * Now shift t2 the correct number of bits. - */ -1: - subu t9, t9, DLEAD_ZEROS # dont count leading zeros - li t1, DEXP_BIAS + 20 # init exponent - subu t1, t1, t9 # compute exponent - beq t9, zero, 1f - li v0, 32 - blt t9, zero, 2f # if shift < 0, shift right - subu v0, v0, t9 - sll t2, t2, t9 # shift left -1: - and t2, t2, ~DIMPL_ONE # clear implied one bit - move t3, zero - b result_fs_d -2: - negu t9 # shift right by t9 - subu v0, v0, t9 - sll t3, t2, v0 - srl t2, t2, t9 - and t2, t2, ~DIMPL_ONE # clear implied one bit - b result_fs_d - -/* - * Convert single to integer. - */ -cvt_w_s: - jal get_fs_s - bne t1, SEXP_INF, 1f # is FS an infinity? - bne t2, zero, invalid_w # invalid conversion -1: - bne t1, zero, 1f # is FS zero? - beq t2, zero, result_fs_w # result is zero - move t2, zero # result is an inexact zero - b inexact_w -1: - subu t1, t1, SEXP_BIAS # unbias exponent - or t2, t2, SIMPL_ONE # add implied one bit - sll t3, t2, 32 - 3 # convert S fraction to D - srl t2, t2, 3 - b cvt_w - -/* - * Convert double to integer. - */ -cvt_w_d: - jal get_fs_d - bne t1, DEXP_INF, 1f # is FS an infinity? - bne t2, zero, invalid_w # invalid conversion - bne t3, zero, invalid_w # invalid conversion -1: - bne t1, zero, 2f # is FS zero? - bne t2, zero, 1f - beq t3, zero, result_fs_w # result is zero -1: - move t2, zero # result is an inexact zero - b inexact_w -2: - subu t1, t1, DEXP_BIAS # unbias exponent - or t2, t2, DIMPL_ONE # add implied one bit -cvt_w: - blt t1, WEXP_MIN, underflow_w # is exponent too small? - li v0, WEXP_MAX+1 - bgt t1, v0, overflow_w # is exponent too large? - bne t1, v0, 1f # special check for INT_MIN - beq t0, zero, overflow_w # if positive, overflow - bne t2, DIMPL_ONE, overflow_w - bne t3, zero, overflow_w - li t2, INT_MIN # result is INT_MIN - b result_fs_w -1: - subu v0, t1, 20 # compute amount to shift - beq v0, zero, 2f # is shift needed? - li v1, 32 - blt v0, zero, 1f # if shift < 0, shift right - subu v1, v1, v0 # shift left - sll t2, t2, v0 - srl t9, t3, v1 # save bits shifted out of t3 - or t2, t2, t9 # and put into t2 - sll t3, t3, v0 # shift FSs fraction - b 2f -1: - negu v0 # shift right by v0 - subu v1, v1, v0 - sll t8, t3, v1 # save bits shifted out - sltu t8, zero, t8 # dont lose any ones - srl t3, t3, v0 # shift FSs fraction - or t3, t3, t8 - sll t9, t2, v1 # save bits shifted out of t2 - or t3, t3, t9 # and put into t3 - srl t2, t2, v0 -/* - * round result (t0 is sign, t2 is integer part, t3 is fractional part). - */ -2: - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, 3f # round to nearest - beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate) - beq v0, FPC_ROUND_RP, 1f # round to +infinity - beq t0, zero, 5f # if sign is positive, truncate - b 2f -1: - bne t0, zero, 5f # if sign is negative, truncate -2: - beq t3, zero, 5f # if no fraction bits, continue - addu t2, t2, 1 # add rounding bit - blt t2, zero, overflow_w # overflow? - b 5f -3: - li v0, GUARDBIT # load guard bit for rounding - addu v0, v0, t3 # add remainder - sltu v1, v0, t3 # compute carry out - beq v1, zero, 4f # if no carry, continue - addu t2, t2, 1 # add carry to result - blt t2, zero, overflow_w # overflow? -4: - bne v0, zero, 5f # if rounded remainder is zero - and t2, t2, ~1 # clear LSB (round to nearest) -5: - beq t0, zero, 1f # result positive? - negu t2 # convert to negative integer -1: - beq t3, zero, result_fs_w # is result exact? -/* - * Handle inexact exception. - */ -inexact_w: - or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT - and v0, a1, FPC_ENABLE_INEXACT - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - b result_fs_w - -/* - * Conversions to integer which overflow will trap (if enabled), - * or generate an inexact trap (if enabled), - * or generate an invalid exception. - */ -overflow_w: - or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW - and v0, a1, FPC_ENABLE_OVERFLOW - bne v0, zero, fpe_trap - and v0, a1, FPC_ENABLE_INEXACT - bne v0, zero, inexact_w # inexact traps enabled? - b invalid_w - -/* - * Conversions to integer which underflow will trap (if enabled), - * or generate an inexact trap (if enabled), - * or generate an invalid exception. - */ -underflow_w: - or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW - and v0, a1, FPC_ENABLE_UNDERFLOW - bne v0, zero, fpe_trap - and v0, a1, FPC_ENABLE_INEXACT - bne v0, zero, inexact_w # inexact traps enabled? - b invalid_w - -/* - * Compare single. - */ -cmp_s: - jal get_cmp_s - bne t1, SEXP_INF, 1f # is FS an infinity? - bne t2, zero, unordered # FS is a NAN -1: - bne t5, SEXP_INF, 2f # is FT an infinity? - bne t6, zero, unordered # FT is a NAN -2: - sll t1, t1, 23 # reassemble exp & frac - or t1, t1, t2 - sll t5, t5, 23 # reassemble exp & frac - or t5, t5, t6 - beq t0, zero, 1f # is FS positive? - negu t1 -1: - beq t4, zero, 1f # is FT positive? - negu t5 -1: - li v0, COND_LESS - blt t1, t5, test_cond # is FS < FT? - li v0, COND_EQUAL - beq t1, t5, test_cond # is FS == FT? - move v0, zero # FS > FT - b test_cond - -/* - * Compare double. - */ -cmp_d: - jal get_cmp_d - bne t1, DEXP_INF, 1f # is FS an infinity? - bne t2, zero, unordered - bne t3, zero, unordered # FS is a NAN -1: - bne t5, DEXP_INF, 2f # is FT an infinity? - bne t6, zero, unordered - bne t7, zero, unordered # FT is a NAN -2: - sll t1, t1, 20 # reassemble exp & frac - or t1, t1, t2 - sll t5, t5, 20 # reassemble exp & frac - or t5, t5, t6 - beq t0, zero, 1f # is FS positive? - not t3 # negate t1,t3 - not t1 - addu t3, t3, 1 - seq v0, t3, zero # compute carry - addu t1, t1, v0 -1: - beq t4, zero, 1f # is FT positive? - not t7 # negate t5,t7 - not t5 - addu t7, t7, 1 - seq v0, t7, zero # compute carry - addu t5, t5, v0 -1: - li v0, COND_LESS - blt t1, t5, test_cond # is FS(MSW) < FT(MSW)? - move v0, zero - bne t1, t5, test_cond # is FS(MSW) > FT(MSW)? - li v0, COND_LESS - bltu t3, t7, test_cond # is FS(LSW) < FT(LSW)? - li v0, COND_EQUAL - beq t3, t7, test_cond # is FS(LSW) == FT(LSW)? - move v0, zero # FS > FT -test_cond: - and v0, v0, a0 # condition match instruction? -set_cond: - bne v0, zero, 1f - and a1, a1, ~FPC_COND_BIT # clear condition bit - b 2f -1: - or a1, a1, FPC_COND_BIT # set condition bit -2: - ctc1 a1, FPC_CSR # save condition bit - b done - -unordered: - and v0, a0, COND_UNORDERED # this cmp match unordered? - bne v0, zero, 1f - and a1, a1, ~FPC_COND_BIT # clear condition bit - b 2f -1: - or a1, a1, FPC_COND_BIT # set condition bit -2: - and v0, a0, COND_SIGNAL - beq v0, zero, 1f # is this a signaling cmp? - or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID - and v0, a1, FPC_ENABLE_INVALID - bne v0, zero, fpe_trap -1: - ctc1 a1, FPC_CSR # save condition bit - b done - -/* - * Determine the amount to shift the fraction in order to restore the - * normalized position. After that, round and handle exceptions. - */ -norm_s: - move v0, t2 - move t9, zero # t9 = num of leading zeros - bne t2, zero, 1f - move v0, t8 - addu t9, 32 -1: - srl v1, v0, 16 - bne v1, zero, 1f - addu t9, 16 - sll v0, 16 -1: - srl v1, v0, 24 - bne v1, zero, 1f - addu t9, 8 - sll v0, 8 -1: - srl v1, v0, 28 - bne v1, zero, 1f - addu t9, 4 - sll v0, 4 -1: - srl v1, v0, 30 - bne v1, zero, 1f - addu t9, 2 - sll v0, 2 -1: - srl v1, v0, 31 - bne v1, zero, 1f - addu t9, 1 -/* - * Now shift t2,t8 the correct number of bits. - */ -1: - subu t9, t9, SLEAD_ZEROS # dont count leading zeros - subu t1, t1, t9 # adjust the exponent - beq t9, zero, norm_noshift_s - li v1, 32 - blt t9, zero, 1f # if shift < 0, shift right - subu v1, v1, t9 - sll t2, t2, t9 # shift t2,t8 left - srl v0, t8, v1 # save bits shifted out - or t2, t2, v0 - sll t8, t8, t9 - b norm_noshift_s -1: - negu t9 # shift t2,t8 right by t9 - subu v1, v1, t9 - sll v0, t8, v1 # save bits shifted out - sltu v0, zero, v0 # be sure to save any one bits - srl t8, t8, t9 - or t8, t8, v0 - sll v0, t2, v1 # save bits shifted out - or t8, t8, v0 - srl t2, t2, t9 -norm_noshift_s: - move t5, t1 # save unrounded exponent - move t6, t2 # save unrounded fraction - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, 3f # round to nearest - beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate) - beq v0, FPC_ROUND_RP, 1f # round to +infinity - beq t0, zero, 5f # if sign is positive, truncate - b 2f -1: - bne t0, zero, 5f # if sign is negative, truncate -2: - beq t8, zero, 5f # if exact, continue - addu t2, t2, 1 # add rounding bit - bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent? - addu t1, t1, 1 # adjust exponent - srl t2, t2, 1 # renormalize fraction - b 5f -3: - li v0, GUARDBIT # load guard bit for rounding - addu v0, v0, t8 # add remainder - sltu v1, v0, t8 # compute carry out - beq v1, zero, 4f # if no carry, continue - addu t2, t2, 1 # add carry to result - bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent? - addu t1, t1, 1 # adjust exponent - srl t2, t2, 1 # renormalize fraction -4: - bne v0, zero, 5f # if rounded remainder is zero - and t2, t2, ~1 # clear LSB (round to nearest) -5: - bgt t1, SEXP_MAX, overflow_s # overflow? - blt t1, SEXP_MIN, underflow_s # underflow? - bne t8, zero, inexact_s # is result inexact? - addu t1, t1, SEXP_BIAS # bias exponent - and t2, t2, ~SIMPL_ONE # clear implied one bit - b result_fs_s - -/* - * Handle inexact exception. - */ -inexact_s: - addu t1, t1, SEXP_BIAS # bias exponent - and t2, t2, ~SIMPL_ONE # clear implied one bit -inexact_nobias_s: - jal set_fd_s # save result - or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT - and v0, a1, FPC_ENABLE_INEXACT - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - b done - -/* - * Overflow will trap (if enabled), - * or generate an inexact trap (if enabled), - * or generate an infinity. - */ -overflow_s: - or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW - and v0, a1, FPC_ENABLE_OVERFLOW - beq v0, zero, 1f - subu t1, t1, 192 # bias exponent - and t2, t2, ~SIMPL_ONE # clear implied one bit - jal set_fd_s # save result - b fpe_trap -1: - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, 3f # round to nearest - beq v0, FPC_ROUND_RZ, 1f # round to zero (truncate) - beq v0, FPC_ROUND_RP, 2f # round to +infinity - bne t0, zero, 3f -1: - li t1, SEXP_MAX # result is max finite - li t2, 0x007fffff - b inexact_s -2: - bne t0, zero, 1b -3: - li t1, SEXP_MAX + 1 # result is infinity - move t2, zero - b inexact_s - -/* - * In this implementation, "tininess" is detected "after rounding" and - * "loss of accuracy" is detected as "an inexact result". - */ -underflow_s: - and v0, a1, FPC_ENABLE_UNDERFLOW - beq v0, zero, 1f -/* - * Underflow is enabled so compute the result and trap. - */ - addu t1, t1, 192 # bias exponent - and t2, t2, ~SIMPL_ONE # clear implied one bit - jal set_fd_s # save result - or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW - b fpe_trap -/* - * Underflow is not enabled so compute the result, - * signal inexact result (if it is) and trap (if enabled). - */ -1: - move t1, t5 # get unrounded exponent - move t2, t6 # get unrounded fraction - li t9, SEXP_MIN # compute shift amount - subu t9, t9, t1 # shift t2,t8 right by t9 - blt t9, SFRAC_BITS+2, 3f # shift all the bits out? - move t1, zero # result is inexact zero - move t2, zero - or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW -/* - * Now round the zero result. - * Only need to worry about rounding to +- infinity when the sign matches. - */ - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, inexact_nobias_s # round to nearest - beq v0, FPC_ROUND_RZ, inexact_nobias_s # round to zero - beq v0, FPC_ROUND_RP, 1f # round to +infinity - beq t0, zero, inexact_nobias_s # if sign is positive, truncate - b 2f -1: - bne t0, zero, inexact_nobias_s # if sign is negative, truncate -2: - addu t2, t2, 1 # add rounding bit - b inexact_nobias_s -3: - li v1, 32 - subu v1, v1, t9 - sltu v0, zero, t8 # be sure to save any one bits - sll t8, t2, v1 # save bits shifted out - or t8, t8, v0 # include sticky bits - srl t2, t2, t9 -/* - * Now round the denormalized result. - */ - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, 3f # round to nearest - beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate) - beq v0, FPC_ROUND_RP, 1f # round to +infinity - beq t0, zero, 5f # if sign is positive, truncate - b 2f -1: - bne t0, zero, 5f # if sign is negative, truncate -2: - beq t8, zero, 5f # if exact, continue - addu t2, t2, 1 # add rounding bit - b 5f -3: - li v0, GUARDBIT # load guard bit for rounding - addu v0, v0, t8 # add remainder - sltu v1, v0, t8 # compute carry out - beq v1, zero, 4f # if no carry, continue - addu t2, t2, 1 # add carry to result -4: - bne v0, zero, 5f # if rounded remainder is zero - and t2, t2, ~1 # clear LSB (round to nearest) -5: - move t1, zero # denorm or zero exponent - jal set_fd_s # save result - beq t8, zero, done # check for exact result - or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW - or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT - and v0, a1, FPC_ENABLE_INEXACT - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - b done - -/* - * Determine the amount to shift the fraction in order to restore the - * normalized position. After that, round and handle exceptions. - */ -norm_d: - move v0, t2 - move t9, zero # t9 = num of leading zeros - bne t2, zero, 1f - move v0, t3 - addu t9, 32 - bne t3, zero, 1f - move v0, t8 - addu t9, 32 -1: - srl v1, v0, 16 - bne v1, zero, 1f - addu t9, 16 - sll v0, 16 -1: - srl v1, v0, 24 - bne v1, zero, 1f - addu t9, 8 - sll v0, 8 -1: - srl v1, v0, 28 - bne v1, zero, 1f - addu t9, 4 - sll v0, 4 -1: - srl v1, v0, 30 - bne v1, zero, 1f - addu t9, 2 - sll v0, 2 -1: - srl v1, v0, 31 - bne v1, zero, 1f - addu t9, 1 -/* - * Now shift t2,t3,t8 the correct number of bits. - */ -1: - subu t9, t9, DLEAD_ZEROS # dont count leading zeros - subu t1, t1, t9 # adjust the exponent - beq t9, zero, norm_noshift_d - li v1, 32 - blt t9, zero, 2f # if shift < 0, shift right - blt t9, v1, 1f # shift by < 32? - subu t9, t9, v1 # shift by >= 32 - subu v1, v1, t9 - sll t2, t3, t9 # shift left by t9 - srl v0, t8, v1 # save bits shifted out - or t2, t2, v0 - sll t3, t8, t9 - move t8, zero - b norm_noshift_d -1: - subu v1, v1, t9 - sll t2, t2, t9 # shift left by t9 - srl v0, t3, v1 # save bits shifted out - or t2, t2, v0 - sll t3, t3, t9 - srl v0, t8, v1 # save bits shifted out - or t3, t3, v0 - sll t8, t8, t9 - b norm_noshift_d -2: - negu t9 # shift right by t9 - subu v1, v1, t9 # (known to be < 32 bits) - sll v0, t8, v1 # save bits shifted out - sltu v0, zero, v0 # be sure to save any one bits - srl t8, t8, t9 - or t8, t8, v0 - sll v0, t3, v1 # save bits shifted out - or t8, t8, v0 - srl t3, t3, t9 - sll v0, t2, v1 # save bits shifted out - or t3, t3, v0 - srl t2, t2, t9 -norm_noshift_d: - move t5, t1 # save unrounded exponent - move t6, t2 # save unrounded fraction (MS) - move t7, t3 # save unrounded fraction (LS) - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, 3f # round to nearest - beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate) - beq v0, FPC_ROUND_RP, 1f # round to +infinity - beq t0, zero, 5f # if sign is positive, truncate - b 2f -1: - bne t0, zero, 5f # if sign is negative, truncate -2: - beq t8, zero, 5f # if exact, continue - addu t3, t3, 1 # add rounding bit - bne t3, zero, 5f # branch if no carry - addu t2, t2, 1 # add carry - bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent? - addu t1, t1, 1 # adjust exponent - srl t2, t2, 1 # renormalize fraction - b 5f -3: - li v0, GUARDBIT # load guard bit for rounding - addu v0, v0, t8 # add remainder - sltu v1, v0, t8 # compute carry out - beq v1, zero, 4f # branch if no carry - addu t3, t3, 1 # add carry - bne t3, zero, 4f # branch if no carry - addu t2, t2, 1 # add carry to result - bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent? - addu t1, t1, 1 # adjust exponent - srl t2, t2, 1 # renormalize fraction -4: - bne v0, zero, 5f # if rounded remainder is zero - and t3, t3, ~1 # clear LSB (round to nearest) -5: - bgt t1, DEXP_MAX, overflow_d # overflow? - blt t1, DEXP_MIN, underflow_d # underflow? - bne t8, zero, inexact_d # is result inexact? - addu t1, t1, DEXP_BIAS # bias exponent - and t2, t2, ~DIMPL_ONE # clear implied one bit - b result_fs_d - -/* - * Handle inexact exception. - */ -inexact_d: - addu t1, t1, DEXP_BIAS # bias exponent - and t2, t2, ~DIMPL_ONE # clear implied one bit -inexact_nobias_d: - jal set_fd_d # save result - or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT - and v0, a1, FPC_ENABLE_INEXACT - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - b done - -/* - * Overflow will trap (if enabled), - * or generate an inexact trap (if enabled), - * or generate an infinity. - */ -overflow_d: - or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW - and v0, a1, FPC_ENABLE_OVERFLOW - beq v0, zero, 1f - subu t1, t1, 1536 # bias exponent - and t2, t2, ~DIMPL_ONE # clear implied one bit - jal set_fd_d # save result - b fpe_trap -1: - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, 3f # round to nearest - beq v0, FPC_ROUND_RZ, 1f # round to zero (truncate) - beq v0, FPC_ROUND_RP, 2f # round to +infinity - bne t0, zero, 3f -1: - li t1, DEXP_MAX # result is max finite - li t2, 0x000fffff - li t3, 0xffffffff - b inexact_d -2: - bne t0, zero, 1b -3: - li t1, DEXP_MAX + 1 # result is infinity - move t2, zero - move t3, zero - b inexact_d - -/* - * In this implementation, "tininess" is detected "after rounding" and - * "loss of accuracy" is detected as "an inexact result". - */ -underflow_d: - and v0, a1, FPC_ENABLE_UNDERFLOW - beq v0, zero, 1f -/* - * Underflow is enabled so compute the result and trap. - */ - addu t1, t1, 1536 # bias exponent - and t2, t2, ~DIMPL_ONE # clear implied one bit - jal set_fd_d # save result - or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW - b fpe_trap -/* - * Underflow is not enabled so compute the result, - * signal inexact result (if it is) and trap (if enabled). - */ -1: - move t1, t5 # get unrounded exponent - move t2, t6 # get unrounded fraction (MS) - move t3, t7 # get unrounded fraction (LS) - li t9, DEXP_MIN # compute shift amount - subu t9, t9, t1 # shift t2,t8 right by t9 - blt t9, DFRAC_BITS+2, 3f # shift all the bits out? - move t1, zero # result is inexact zero - move t2, zero - move t3, zero - or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW -/* - * Now round the zero result. - * Only need to worry about rounding to +- infinity when the sign matches. - */ - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, inexact_nobias_d # round to nearest - beq v0, FPC_ROUND_RZ, inexact_nobias_d # round to zero - beq v0, FPC_ROUND_RP, 1f # round to +infinity - beq t0, zero, inexact_nobias_d # if sign is positive, truncate - b 2f -1: - bne t0, zero, inexact_nobias_d # if sign is negative, truncate -2: - addu t3, t3, 1 # add rounding bit - b inexact_nobias_d -3: - li v1, 32 - blt t9, v1, 1f # shift by < 32? - subu t9, t9, v1 # shift right by >= 32 - subu v1, v1, t9 - sltu v0, zero, t8 # be sure to save any one bits - sll t8, t2, v1 # save bits shifted out - or t8, t8, v0 # include sticky bits - srl t3, t2, t9 - move t2, zero - b 2f -1: - subu v1, v1, t9 # shift right by t9 - sltu v0, zero, t8 # be sure to save any one bits - sll t8, t3, v1 # save bits shifted out - or t8, t8, v0 # include sticky bits - srl t3, t3, t9 - sll v0, t2, v1 # save bits shifted out - or t3, t3, v0 - srl t2, t2, t9 -/* - * Now round the denormalized result. - */ -2: - and v0, a1, FPC_ROUNDING_BITS # get rounding mode - beq v0, FPC_ROUND_RN, 3f # round to nearest - beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate) - beq v0, FPC_ROUND_RP, 1f # round to +infinity - beq t0, zero, 5f # if sign is positive, truncate - b 2f -1: - bne t0, zero, 5f # if sign is negative, truncate -2: - beq t8, zero, 5f # if exact, continue - addu t3, t3, 1 # add rounding bit - bne t3, zero, 5f # if no carry, continue - addu t2, t2, 1 # add carry - b 5f -3: - li v0, GUARDBIT # load guard bit for rounding - addu v0, v0, t8 # add remainder - sltu v1, v0, t8 # compute carry out - beq v1, zero, 4f # if no carry, continue - addu t3, t3, 1 # add rounding bit - bne t3, zero, 4f # if no carry, continue - addu t2, t2, 1 # add carry -4: - bne v0, zero, 5f # if rounded remainder is zero - and t3, t3, ~1 # clear LSB (round to nearest) -5: - move t1, zero # denorm or zero exponent - jal set_fd_d # save result - beq t8, zero, done # check for exact result - or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW - or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT - and v0, a1, FPC_ENABLE_INEXACT - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - b done - -/* - * Signal an invalid operation if the trap is enabled; otherwise, - * the result is a quiet NAN. - */ -invalid_s: # trap invalid operation - or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID - and v0, a1, FPC_ENABLE_INVALID - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - move t0, zero # result is a quiet NAN - li t1, SEXP_INF - li t2, SQUIET_NAN - jal set_fd_s # save result (in t0,t1,t2) - b done - -/* - * Signal an invalid operation if the trap is enabled; otherwise, - * the result is a quiet NAN. - */ -invalid_d: # trap invalid operation - or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID - and v0, a1, FPC_ENABLE_INVALID - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - move t0, zero # result is a quiet NAN - li t1, DEXP_INF - li t2, DQUIET_NAN0 - li t3, DQUIET_NAN1 - jal set_fd_d # save result (in t0,t1,t2,t3) - b done - -/* - * Signal an invalid operation if the trap is enabled; otherwise, - * the result is INT_MAX or INT_MIN. - */ -invalid_w: # trap invalid operation - or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID - and v0, a1, FPC_ENABLE_INVALID - bne v0, zero, fpe_trap - ctc1 a1, FPC_CSR # save exceptions - bne t0, zero, 1f - li t2, INT_MAX # result is INT_MAX - b result_fs_w -1: - li t2, INT_MIN # result is INT_MIN - b result_fs_w - -/* - * Trap if the hardware should have handled this case. - */ -fpe_trap: - move a2, a1 # code = FP CSR - ctc1 a1, FPC_CSR # save exceptions - break 0 - -/* - * Send an illegal instruction signal to the current process. - */ -ill: - ctc1 a1, FPC_CSR # save exceptions - move a2, a0 # code = FP instruction - break 0 - -result_ft_s: - move t0, t4 # result is FT - move t1, t5 - move t2, t6 -result_fs_s: # result is FS - jal set_fd_s # save result (in t0,t1,t2) - b done - -result_fs_w: - jal set_fd_word # save result (in t2) - b done - -result_ft_d: - move t0, t4 # result is FT - move t1, t5 - move t2, t6 - move t3, t7 -result_fs_d: # result is FS - jal set_fd_d # save result (in t0,t1,t2,t3) - -done: - lw ra, STAND_RA_OFFSET(sp) - addu sp, sp, STAND_FRAME_SIZE - j ra -END(MachEmulateFP) - -/*---------------------------------------------------------------------------- - * get_fs_int -- - * - * Read (integer) the FS register (bits 15-11). - * This is an internal routine used by MachEmulateFP only. - * - * Results: - * t0 contains the sign - * t2 contains the fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(get_fs_int) - srl a3, a0, 12 - 2 # get FS field (even regs only) - and a3, a3, 0xF << 2 # mask FS field - lw a3, get_fs_int_tbl(a3) # switch on register number - j a3 - - .rdata -get_fs_int_tbl: - .word get_fs_int_f0 - .word get_fs_int_f2 - .word get_fs_int_f4 - .word get_fs_int_f6 - .word get_fs_int_f8 - .word get_fs_int_f10 - .word get_fs_int_f12 - .word get_fs_int_f14 - .word get_fs_int_f16 - .word get_fs_int_f18 - .word get_fs_int_f20 - .word get_fs_int_f22 - .word get_fs_int_f24 - .word get_fs_int_f26 - .word get_fs_int_f28 - .word get_fs_int_f30 - .text - -get_fs_int_f0: - mfc1 t2, $f0 - b get_fs_int_done -get_fs_int_f2: - mfc1 t2, $f2 - b get_fs_int_done -get_fs_int_f4: - mfc1 t2, $f4 - b get_fs_int_done -get_fs_int_f6: - mfc1 t2, $f6 - b get_fs_int_done -get_fs_int_f8: - mfc1 t2, $f8 - b get_fs_int_done -get_fs_int_f10: - mfc1 t2, $f10 - b get_fs_int_done -get_fs_int_f12: - mfc1 t2, $f12 - b get_fs_int_done -get_fs_int_f14: - mfc1 t2, $f14 - b get_fs_int_done -get_fs_int_f16: - mfc1 t2, $f16 - b get_fs_int_done -get_fs_int_f18: - mfc1 t2, $f18 - b get_fs_int_done -get_fs_int_f20: - mfc1 t2, $f20 - b get_fs_int_done -get_fs_int_f22: - mfc1 t2, $f22 - b get_fs_int_done -get_fs_int_f24: - mfc1 t2, $f24 - b get_fs_int_done -get_fs_int_f26: - mfc1 t2, $f26 - b get_fs_int_done -get_fs_int_f28: - mfc1 t2, $f28 - b get_fs_int_done -get_fs_int_f30: - mfc1 t2, $f30 -get_fs_int_done: - srl t0, t2, 31 # init the sign bit - bge t2, zero, 1f - negu t2 -1: - j ra -END(get_fs_int) - -/*---------------------------------------------------------------------------- - * get_ft_fs_s -- - * - * Read (single precision) the FT register (bits 20-16) and - * the FS register (bits 15-11) and break up into fields. - * This is an internal routine used by MachEmulateFP only. - * - * Results: - * t0 contains the FS sign - * t1 contains the FS (biased) exponent - * t2 contains the FS fraction - * t4 contains the FT sign - * t5 contains the FT (biased) exponent - * t6 contains the FT fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(get_ft_fs_s) - srl a3, a0, 17 - 2 # get FT field (even regs only) - and a3, a3, 0xF << 2 # mask FT field - lw a3, get_ft_s_tbl(a3) # switch on register number - j a3 - - .rdata -get_ft_s_tbl: - .word get_ft_s_f0 - .word get_ft_s_f2 - .word get_ft_s_f4 - .word get_ft_s_f6 - .word get_ft_s_f8 - .word get_ft_s_f10 - .word get_ft_s_f12 - .word get_ft_s_f14 - .word get_ft_s_f16 - .word get_ft_s_f18 - .word get_ft_s_f20 - .word get_ft_s_f22 - .word get_ft_s_f24 - .word get_ft_s_f26 - .word get_ft_s_f28 - .word get_ft_s_f30 - .text - -get_ft_s_f0: - mfc1 t4, $f0 - b get_ft_s_done -get_ft_s_f2: - mfc1 t4, $f2 - b get_ft_s_done -get_ft_s_f4: - mfc1 t4, $f4 - b get_ft_s_done -get_ft_s_f6: - mfc1 t4, $f6 - b get_ft_s_done -get_ft_s_f8: - mfc1 t4, $f8 - b get_ft_s_done -get_ft_s_f10: - mfc1 t4, $f10 - b get_ft_s_done -get_ft_s_f12: - mfc1 t4, $f12 - b get_ft_s_done -get_ft_s_f14: - mfc1 t4, $f14 - b get_ft_s_done -get_ft_s_f16: - mfc1 t4, $f16 - b get_ft_s_done -get_ft_s_f18: - mfc1 t4, $f18 - b get_ft_s_done -get_ft_s_f20: - mfc1 t4, $f20 - b get_ft_s_done -get_ft_s_f22: - mfc1 t4, $f22 - b get_ft_s_done -get_ft_s_f24: - mfc1 t4, $f24 - b get_ft_s_done -get_ft_s_f26: - mfc1 t4, $f26 - b get_ft_s_done -get_ft_s_f28: - mfc1 t4, $f28 - b get_ft_s_done -get_ft_s_f30: - mfc1 t4, $f30 -get_ft_s_done: - srl t5, t4, 23 # get exponent - and t5, t5, 0xFF - and t6, t4, 0x7FFFFF # get fraction - srl t4, t4, 31 # get sign - bne t5, SEXP_INF, 1f # is it a signaling NAN? - and v0, t6, SSIGNAL_NAN - bne v0, zero, invalid_s -1: - /* fall through to get FS */ - -/*---------------------------------------------------------------------------- - * get_fs_s -- - * - * Read (single precision) the FS register (bits 15-11) and - * break up into fields. - * This is an internal routine used by MachEmulateFP only. - * - * Results: - * t0 contains the sign - * t1 contains the (biased) exponent - * t2 contains the fraction - * - *---------------------------------------------------------------------------- - */ -ALEAF(get_fs_s) - srl a3, a0, 12 - 2 # get FS field (even regs only) - and a3, a3, 0xF << 2 # mask FS field - lw a3, get_fs_s_tbl(a3) # switch on register number - j a3 - - .rdata -get_fs_s_tbl: - .word get_fs_s_f0 - .word get_fs_s_f2 - .word get_fs_s_f4 - .word get_fs_s_f6 - .word get_fs_s_f8 - .word get_fs_s_f10 - .word get_fs_s_f12 - .word get_fs_s_f14 - .word get_fs_s_f16 - .word get_fs_s_f18 - .word get_fs_s_f20 - .word get_fs_s_f22 - .word get_fs_s_f24 - .word get_fs_s_f26 - .word get_fs_s_f28 - .word get_fs_s_f30 - .text - -get_fs_s_f0: - mfc1 t0, $f0 - b get_fs_s_done -get_fs_s_f2: - mfc1 t0, $f2 - b get_fs_s_done -get_fs_s_f4: - mfc1 t0, $f4 - b get_fs_s_done -get_fs_s_f6: - mfc1 t0, $f6 - b get_fs_s_done -get_fs_s_f8: - mfc1 t0, $f8 - b get_fs_s_done -get_fs_s_f10: - mfc1 t0, $f10 - b get_fs_s_done -get_fs_s_f12: - mfc1 t0, $f12 - b get_fs_s_done -get_fs_s_f14: - mfc1 t0, $f14 - b get_fs_s_done -get_fs_s_f16: - mfc1 t0, $f16 - b get_fs_s_done -get_fs_s_f18: - mfc1 t0, $f18 - b get_fs_s_done -get_fs_s_f20: - mfc1 t0, $f20 - b get_fs_s_done -get_fs_s_f22: - mfc1 t0, $f22 - b get_fs_s_done -get_fs_s_f24: - mfc1 t0, $f24 - b get_fs_s_done -get_fs_s_f26: - mfc1 t0, $f26 - b get_fs_s_done -get_fs_s_f28: - mfc1 t0, $f28 - b get_fs_s_done -get_fs_s_f30: - mfc1 t0, $f30 -get_fs_s_done: - srl t1, t0, 23 # get exponent - and t1, t1, 0xFF - and t2, t0, 0x7FFFFF # get fraction - srl t0, t0, 31 # get sign - bne t1, SEXP_INF, 1f # is it a signaling NAN? - and v0, t2, SSIGNAL_NAN - bne v0, zero, invalid_s -1: - j ra -END(get_ft_fs_s) - -/*---------------------------------------------------------------------------- - * get_ft_fs_d -- - * - * Read (double precision) the FT register (bits 20-16) and - * the FS register (bits 15-11) and break up into fields. - * This is an internal routine used by MachEmulateFP only. - * - * Results: - * t0 contains the FS sign - * t1 contains the FS (biased) exponent - * t2 contains the FS fraction - * t3 contains the FS remaining fraction - * t4 contains the FT sign - * t5 contains the FT (biased) exponent - * t6 contains the FT fraction - * t7 contains the FT remaining fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(get_ft_fs_d) - srl a3, a0, 17 - 2 # get FT field (even regs only) - and a3, a3, 0xF << 2 # mask FT field - lw a3, get_ft_d_tbl(a3) # switch on register number - j a3 - - .rdata -get_ft_d_tbl: - .word get_ft_d_f0 - .word get_ft_d_f2 - .word get_ft_d_f4 - .word get_ft_d_f6 - .word get_ft_d_f8 - .word get_ft_d_f10 - .word get_ft_d_f12 - .word get_ft_d_f14 - .word get_ft_d_f16 - .word get_ft_d_f18 - .word get_ft_d_f20 - .word get_ft_d_f22 - .word get_ft_d_f24 - .word get_ft_d_f26 - .word get_ft_d_f28 - .word get_ft_d_f30 - .text - -get_ft_d_f0: - mfc1 t7, $f0 - mfc1 t4, $f1 - b get_ft_d_done -get_ft_d_f2: - mfc1 t7, $f2 - mfc1 t4, $f3 - b get_ft_d_done -get_ft_d_f4: - mfc1 t7, $f4 - mfc1 t4, $f5 - b get_ft_d_done -get_ft_d_f6: - mfc1 t7, $f6 - mfc1 t4, $f7 - b get_ft_d_done -get_ft_d_f8: - mfc1 t7, $f8 - mfc1 t4, $f9 - b get_ft_d_done -get_ft_d_f10: - mfc1 t7, $f10 - mfc1 t4, $f11 - b get_ft_d_done -get_ft_d_f12: - mfc1 t7, $f12 - mfc1 t4, $f13 - b get_ft_d_done -get_ft_d_f14: - mfc1 t7, $f14 - mfc1 t4, $f15 - b get_ft_d_done -get_ft_d_f16: - mfc1 t7, $f16 - mfc1 t4, $f17 - b get_ft_d_done -get_ft_d_f18: - mfc1 t7, $f18 - mfc1 t4, $f19 - b get_ft_d_done -get_ft_d_f20: - mfc1 t7, $f20 - mfc1 t4, $f21 - b get_ft_d_done -get_ft_d_f22: - mfc1 t7, $f22 - mfc1 t4, $f23 - b get_ft_d_done -get_ft_d_f24: - mfc1 t7, $f24 - mfc1 t4, $f25 - b get_ft_d_done -get_ft_d_f26: - mfc1 t7, $f26 - mfc1 t4, $f27 - b get_ft_d_done -get_ft_d_f28: - mfc1 t7, $f28 - mfc1 t4, $f29 - b get_ft_d_done -get_ft_d_f30: - mfc1 t7, $f30 - mfc1 t4, $f31 -get_ft_d_done: - srl t5, t4, 20 # get exponent - and t5, t5, 0x7FF - and t6, t4, 0xFFFFF # get fraction - srl t4, t4, 31 # get sign - bne t5, DEXP_INF, 1f # is it a signaling NAN? - and v0, t6, DSIGNAL_NAN - bne v0, zero, invalid_d -1: - /* fall through to get FS */ - -/*---------------------------------------------------------------------------- - * get_fs_d -- - * - * Read (double precision) the FS register (bits 15-11) and - * break up into fields. - * This is an internal routine used by MachEmulateFP only. - * - * Results: - * t0 contains the sign - * t1 contains the (biased) exponent - * t2 contains the fraction - * t3 contains the remaining fraction - * - *---------------------------------------------------------------------------- - */ -ALEAF(get_fs_d) - srl a3, a0, 12 - 2 # get FS field (even regs only) - and a3, a3, 0xF << 2 # mask FS field - lw a3, get_fs_d_tbl(a3) # switch on register number - j a3 - - .rdata -get_fs_d_tbl: - .word get_fs_d_f0 - .word get_fs_d_f2 - .word get_fs_d_f4 - .word get_fs_d_f6 - .word get_fs_d_f8 - .word get_fs_d_f10 - .word get_fs_d_f12 - .word get_fs_d_f14 - .word get_fs_d_f16 - .word get_fs_d_f18 - .word get_fs_d_f20 - .word get_fs_d_f22 - .word get_fs_d_f24 - .word get_fs_d_f26 - .word get_fs_d_f28 - .word get_fs_d_f30 - .text - -get_fs_d_f0: - mfc1 t3, $f0 - mfc1 t0, $f1 - b get_fs_d_done -get_fs_d_f2: - mfc1 t3, $f2 - mfc1 t0, $f3 - b get_fs_d_done -get_fs_d_f4: - mfc1 t3, $f4 - mfc1 t0, $f5 - b get_fs_d_done -get_fs_d_f6: - mfc1 t3, $f6 - mfc1 t0, $f7 - b get_fs_d_done -get_fs_d_f8: - mfc1 t3, $f8 - mfc1 t0, $f9 - b get_fs_d_done -get_fs_d_f10: - mfc1 t3, $f10 - mfc1 t0, $f11 - b get_fs_d_done -get_fs_d_f12: - mfc1 t3, $f12 - mfc1 t0, $f13 - b get_fs_d_done -get_fs_d_f14: - mfc1 t3, $f14 - mfc1 t0, $f15 - b get_fs_d_done -get_fs_d_f16: - mfc1 t3, $f16 - mfc1 t0, $f17 - b get_fs_d_done -get_fs_d_f18: - mfc1 t3, $f18 - mfc1 t0, $f19 - b get_fs_d_done -get_fs_d_f20: - mfc1 t3, $f20 - mfc1 t0, $f21 - b get_fs_d_done -get_fs_d_f22: - mfc1 t3, $f22 - mfc1 t0, $f23 - b get_fs_d_done -get_fs_d_f24: - mfc1 t3, $f24 - mfc1 t0, $f25 - b get_fs_d_done -get_fs_d_f26: - mfc1 t3, $f26 - mfc1 t0, $f27 - b get_fs_d_done -get_fs_d_f28: - mfc1 t3, $f28 - mfc1 t0, $f29 - b get_fs_d_done -get_fs_d_f30: - mfc1 t3, $f30 - mfc1 t0, $f31 -get_fs_d_done: - srl t1, t0, 20 # get exponent - and t1, t1, 0x7FF - and t2, t0, 0xFFFFF # get fraction - srl t0, t0, 31 # get sign - bne t1, DEXP_INF, 1f # is it a signaling NAN? - and v0, t2, DSIGNAL_NAN - bne v0, zero, invalid_d -1: - j ra -END(get_ft_fs_d) - -/*---------------------------------------------------------------------------- - * get_cmp_s -- - * - * Read (single precision) the FS register (bits 15-11) and - * the FT register (bits 20-16) and break up into fields. - * This is an internal routine used by MachEmulateFP only. - * - * Results: - * t0 contains the sign - * t1 contains the (biased) exponent - * t2 contains the fraction - * t4 contains the sign - * t5 contains the (biased) exponent - * t6 contains the fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(get_cmp_s) - srl a3, a0, 12 - 2 # get FS field (even regs only) - and a3, a3, 0xF << 2 # mask FS field - lw a3, cmp_fs_s_tbl(a3) # switch on register number - j a3 - - .rdata -cmp_fs_s_tbl: - .word cmp_fs_s_f0 - .word cmp_fs_s_f2 - .word cmp_fs_s_f4 - .word cmp_fs_s_f6 - .word cmp_fs_s_f8 - .word cmp_fs_s_f10 - .word cmp_fs_s_f12 - .word cmp_fs_s_f14 - .word cmp_fs_s_f16 - .word cmp_fs_s_f18 - .word cmp_fs_s_f20 - .word cmp_fs_s_f22 - .word cmp_fs_s_f24 - .word cmp_fs_s_f26 - .word cmp_fs_s_f28 - .word cmp_fs_s_f30 - .text - -cmp_fs_s_f0: - mfc1 t0, $f0 - b cmp_fs_s_done -cmp_fs_s_f2: - mfc1 t0, $f2 - b cmp_fs_s_done -cmp_fs_s_f4: - mfc1 t0, $f4 - b cmp_fs_s_done -cmp_fs_s_f6: - mfc1 t0, $f6 - b cmp_fs_s_done -cmp_fs_s_f8: - mfc1 t0, $f8 - b cmp_fs_s_done -cmp_fs_s_f10: - mfc1 t0, $f10 - b cmp_fs_s_done -cmp_fs_s_f12: - mfc1 t0, $f12 - b cmp_fs_s_done -cmp_fs_s_f14: - mfc1 t0, $f14 - b cmp_fs_s_done -cmp_fs_s_f16: - mfc1 t0, $f16 - b cmp_fs_s_done -cmp_fs_s_f18: - mfc1 t0, $f18 - b cmp_fs_s_done -cmp_fs_s_f20: - mfc1 t0, $f20 - b cmp_fs_s_done -cmp_fs_s_f22: - mfc1 t0, $f22 - b cmp_fs_s_done -cmp_fs_s_f24: - mfc1 t0, $f24 - b cmp_fs_s_done -cmp_fs_s_f26: - mfc1 t0, $f26 - b cmp_fs_s_done -cmp_fs_s_f28: - mfc1 t0, $f28 - b cmp_fs_s_done -cmp_fs_s_f30: - mfc1 t0, $f30 -cmp_fs_s_done: - srl t1, t0, 23 # get exponent - and t1, t1, 0xFF - and t2, t0, 0x7FFFFF # get fraction - srl t0, t0, 31 # get sign - - srl a3, a0, 17 - 2 # get FT field (even regs only) - and a3, a3, 0xF << 2 # mask FT field - lw a3, cmp_ft_s_tbl(a3) # switch on register number - j a3 - - .rdata -cmp_ft_s_tbl: - .word cmp_ft_s_f0 - .word cmp_ft_s_f2 - .word cmp_ft_s_f4 - .word cmp_ft_s_f6 - .word cmp_ft_s_f8 - .word cmp_ft_s_f10 - .word cmp_ft_s_f12 - .word cmp_ft_s_f14 - .word cmp_ft_s_f16 - .word cmp_ft_s_f18 - .word cmp_ft_s_f20 - .word cmp_ft_s_f22 - .word cmp_ft_s_f24 - .word cmp_ft_s_f26 - .word cmp_ft_s_f28 - .word cmp_ft_s_f30 - .text - -cmp_ft_s_f0: - mfc1 t4, $f0 - b cmp_ft_s_done -cmp_ft_s_f2: - mfc1 t4, $f2 - b cmp_ft_s_done -cmp_ft_s_f4: - mfc1 t4, $f4 - b cmp_ft_s_done -cmp_ft_s_f6: - mfc1 t4, $f6 - b cmp_ft_s_done -cmp_ft_s_f8: - mfc1 t4, $f8 - b cmp_ft_s_done -cmp_ft_s_f10: - mfc1 t4, $f10 - b cmp_ft_s_done -cmp_ft_s_f12: - mfc1 t4, $f12 - b cmp_ft_s_done -cmp_ft_s_f14: - mfc1 t4, $f14 - b cmp_ft_s_done -cmp_ft_s_f16: - mfc1 t4, $f16 - b cmp_ft_s_done -cmp_ft_s_f18: - mfc1 t4, $f18 - b cmp_ft_s_done -cmp_ft_s_f20: - mfc1 t4, $f20 - b cmp_ft_s_done -cmp_ft_s_f22: - mfc1 t4, $f22 - b cmp_ft_s_done -cmp_ft_s_f24: - mfc1 t4, $f24 - b cmp_ft_s_done -cmp_ft_s_f26: - mfc1 t4, $f26 - b cmp_ft_s_done -cmp_ft_s_f28: - mfc1 t4, $f28 - b cmp_ft_s_done -cmp_ft_s_f30: - mfc1 t4, $f30 -cmp_ft_s_done: - srl t5, t4, 23 # get exponent - and t5, t5, 0xFF - and t6, t4, 0x7FFFFF # get fraction - srl t4, t4, 31 # get sign - j ra -END(get_cmp_s) - -/*---------------------------------------------------------------------------- - * get_cmp_d -- - * - * Read (double precision) the FS register (bits 15-11) and - * the FT register (bits 20-16) and break up into fields. - * This is an internal routine used by MachEmulateFP only. - * - * Results: - * t0 contains the sign - * t1 contains the (biased) exponent - * t2 contains the fraction - * t3 contains the remaining fraction - * t4 contains the sign - * t5 contains the (biased) exponent - * t6 contains the fraction - * t7 contains the remaining fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(get_cmp_d) - srl a3, a0, 12 - 2 # get FS field (even regs only) - and a3, a3, 0xF << 2 # mask FS field - lw a3, cmp_fs_d_tbl(a3) # switch on register number - j a3 - - .rdata -cmp_fs_d_tbl: - .word cmp_fs_d_f0 - .word cmp_fs_d_f2 - .word cmp_fs_d_f4 - .word cmp_fs_d_f6 - .word cmp_fs_d_f8 - .word cmp_fs_d_f10 - .word cmp_fs_d_f12 - .word cmp_fs_d_f14 - .word cmp_fs_d_f16 - .word cmp_fs_d_f18 - .word cmp_fs_d_f20 - .word cmp_fs_d_f22 - .word cmp_fs_d_f24 - .word cmp_fs_d_f26 - .word cmp_fs_d_f28 - .word cmp_fs_d_f30 - .text - -cmp_fs_d_f0: - mfc1 t3, $f0 - mfc1 t0, $f1 - b cmp_fs_d_done -cmp_fs_d_f2: - mfc1 t3, $f2 - mfc1 t0, $f3 - b cmp_fs_d_done -cmp_fs_d_f4: - mfc1 t3, $f4 - mfc1 t0, $f5 - b cmp_fs_d_done -cmp_fs_d_f6: - mfc1 t3, $f6 - mfc1 t0, $f7 - b cmp_fs_d_done -cmp_fs_d_f8: - mfc1 t3, $f8 - mfc1 t0, $f9 - b cmp_fs_d_done -cmp_fs_d_f10: - mfc1 t3, $f10 - mfc1 t0, $f11 - b cmp_fs_d_done -cmp_fs_d_f12: - mfc1 t3, $f12 - mfc1 t0, $f13 - b cmp_fs_d_done -cmp_fs_d_f14: - mfc1 t3, $f14 - mfc1 t0, $f15 - b cmp_fs_d_done -cmp_fs_d_f16: - mfc1 t3, $f16 - mfc1 t0, $f17 - b cmp_fs_d_done -cmp_fs_d_f18: - mfc1 t3, $f18 - mfc1 t0, $f19 - b cmp_fs_d_done -cmp_fs_d_f20: - mfc1 t3, $f20 - mfc1 t0, $f21 - b cmp_fs_d_done -cmp_fs_d_f22: - mfc1 t3, $f22 - mfc1 t0, $f23 - b cmp_fs_d_done -cmp_fs_d_f24: - mfc1 t3, $f24 - mfc1 t0, $f25 - b cmp_fs_d_done -cmp_fs_d_f26: - mfc1 t3, $f26 - mfc1 t0, $f27 - b cmp_fs_d_done -cmp_fs_d_f28: - mfc1 t3, $f28 - mfc1 t0, $f29 - b cmp_fs_d_done -cmp_fs_d_f30: - mfc1 t3, $f30 - mfc1 t0, $f31 -cmp_fs_d_done: - srl t1, t0, 20 # get exponent - and t1, t1, 0x7FF - and t2, t0, 0xFFFFF # get fraction - srl t0, t0, 31 # get sign - - srl a3, a0, 17 - 2 # get FT field (even regs only) - and a3, a3, 0xF << 2 # mask FT field - lw a3, cmp_ft_d_tbl(a3) # switch on register number - j a3 - - .rdata -cmp_ft_d_tbl: - .word cmp_ft_d_f0 - .word cmp_ft_d_f2 - .word cmp_ft_d_f4 - .word cmp_ft_d_f6 - .word cmp_ft_d_f8 - .word cmp_ft_d_f10 - .word cmp_ft_d_f12 - .word cmp_ft_d_f14 - .word cmp_ft_d_f16 - .word cmp_ft_d_f18 - .word cmp_ft_d_f20 - .word cmp_ft_d_f22 - .word cmp_ft_d_f24 - .word cmp_ft_d_f26 - .word cmp_ft_d_f28 - .word cmp_ft_d_f30 - .text - -cmp_ft_d_f0: - mfc1 t7, $f0 - mfc1 t4, $f1 - b cmp_ft_d_done -cmp_ft_d_f2: - mfc1 t7, $f2 - mfc1 t4, $f3 - b cmp_ft_d_done -cmp_ft_d_f4: - mfc1 t7, $f4 - mfc1 t4, $f5 - b cmp_ft_d_done -cmp_ft_d_f6: - mfc1 t7, $f6 - mfc1 t4, $f7 - b cmp_ft_d_done -cmp_ft_d_f8: - mfc1 t7, $f8 - mfc1 t4, $f9 - b cmp_ft_d_done -cmp_ft_d_f10: - mfc1 t7, $f10 - mfc1 t4, $f11 - b cmp_ft_d_done -cmp_ft_d_f12: - mfc1 t7, $f12 - mfc1 t4, $f13 - b cmp_ft_d_done -cmp_ft_d_f14: - mfc1 t7, $f14 - mfc1 t4, $f15 - b cmp_ft_d_done -cmp_ft_d_f16: - mfc1 t7, $f16 - mfc1 t4, $f17 - b cmp_ft_d_done -cmp_ft_d_f18: - mfc1 t7, $f18 - mfc1 t4, $f19 - b cmp_ft_d_done -cmp_ft_d_f20: - mfc1 t7, $f20 - mfc1 t4, $f21 - b cmp_ft_d_done -cmp_ft_d_f22: - mfc1 t7, $f22 - mfc1 t4, $f23 - b cmp_ft_d_done -cmp_ft_d_f24: - mfc1 t7, $f24 - mfc1 t4, $f25 - b cmp_ft_d_done -cmp_ft_d_f26: - mfc1 t7, $f26 - mfc1 t4, $f27 - b cmp_ft_d_done -cmp_ft_d_f28: - mfc1 t7, $f28 - mfc1 t4, $f29 - b cmp_ft_d_done -cmp_ft_d_f30: - mfc1 t7, $f30 - mfc1 t4, $f31 -cmp_ft_d_done: - srl t5, t4, 20 # get exponent - and t5, t5, 0x7FF - and t6, t4, 0xFFFFF # get fraction - srl t4, t4, 31 # get sign - j ra -END(get_cmp_d) - -/*---------------------------------------------------------------------------- - * set_fd_s -- - * - * Write (single precision) the FD register (bits 10-6). - * This is an internal routine used by MachEmulateFP only. - * - * Arguments: - * a0 contains the FP instruction - * t0 contains the sign - * t1 contains the (biased) exponent - * t2 contains the fraction - * - * set_fd_word -- - * - * Write (integer) the FD register (bits 10-6). - * This is an internal routine used by MachEmulateFP only. - * - * Arguments: - * a0 contains the FP instruction - * t2 contains the integer - * - *---------------------------------------------------------------------------- - */ -LEAF(set_fd_s) - sll t0, t0, 31 # position sign - sll t1, t1, 23 # position exponent - or t2, t2, t0 - or t2, t2, t1 -ALEAF(set_fd_word) - srl a3, a0, 7 - 2 # get FD field (even regs only) - and a3, a3, 0xF << 2 # mask FT field - lw a3, set_fd_s_tbl(a3) # switch on register number - j a3 - - .rdata -set_fd_s_tbl: - .word set_fd_s_f0 - .word set_fd_s_f2 - .word set_fd_s_f4 - .word set_fd_s_f6 - .word set_fd_s_f8 - .word set_fd_s_f10 - .word set_fd_s_f12 - .word set_fd_s_f14 - .word set_fd_s_f16 - .word set_fd_s_f18 - .word set_fd_s_f20 - .word set_fd_s_f22 - .word set_fd_s_f24 - .word set_fd_s_f26 - .word set_fd_s_f28 - .word set_fd_s_f30 - .text - -set_fd_s_f0: - mtc1 t2, $f0 - j ra -set_fd_s_f2: - mtc1 t2, $f2 - j ra -set_fd_s_f4: - mtc1 t2, $f4 - j ra -set_fd_s_f6: - mtc1 t2, $f6 - j ra -set_fd_s_f8: - mtc1 t2, $f8 - j ra -set_fd_s_f10: - mtc1 t2, $f10 - j ra -set_fd_s_f12: - mtc1 t2, $f12 - j ra -set_fd_s_f14: - mtc1 t2, $f14 - j ra -set_fd_s_f16: - mtc1 t2, $f16 - j ra -set_fd_s_f18: - mtc1 t2, $f18 - j ra -set_fd_s_f20: - mtc1 t2, $f20 - j ra -set_fd_s_f22: - mtc1 t2, $f22 - j ra -set_fd_s_f24: - mtc1 t2, $f24 - j ra -set_fd_s_f26: - mtc1 t2, $f26 - j ra -set_fd_s_f28: - mtc1 t2, $f28 - j ra -set_fd_s_f30: - mtc1 t2, $f30 - j ra -END(set_fd_s) - -/*---------------------------------------------------------------------------- - * set_fd_d -- - * - * Write (double precision) the FT register (bits 10-6). - * This is an internal routine used by MachEmulateFP only. - * - * Arguments: - * a0 contains the FP instruction - * t0 contains the sign - * t1 contains the (biased) exponent - * t2 contains the fraction - * t3 contains the remaining fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(set_fd_d) - sll t0, t0, 31 # set sign - sll t1, t1, 20 # set exponent - or t0, t0, t1 - or t0, t0, t2 # set fraction - srl a3, a0, 7 - 2 # get FD field (even regs only) - and a3, a3, 0xF << 2 # mask FD field - lw a3, set_fd_d_tbl(a3) # switch on register number - j a3 - - .rdata -set_fd_d_tbl: - .word set_fd_d_f0 - .word set_fd_d_f2 - .word set_fd_d_f4 - .word set_fd_d_f6 - .word set_fd_d_f8 - .word set_fd_d_f10 - .word set_fd_d_f12 - .word set_fd_d_f14 - .word set_fd_d_f16 - .word set_fd_d_f18 - .word set_fd_d_f20 - .word set_fd_d_f22 - .word set_fd_d_f24 - .word set_fd_d_f26 - .word set_fd_d_f28 - .word set_fd_d_f30 - .text - -set_fd_d_f0: - mtc1 t3, $f0 - mtc1 t0, $f1 - j ra -set_fd_d_f2: - mtc1 t3, $f2 - mtc1 t0, $f3 - j ra -set_fd_d_f4: - mtc1 t3, $f4 - mtc1 t0, $f5 - j ra -set_fd_d_f6: - mtc1 t3, $f6 - mtc1 t0, $f7 - j ra -set_fd_d_f8: - mtc1 t3, $f8 - mtc1 t0, $f9 - j ra -set_fd_d_f10: - mtc1 t3, $f10 - mtc1 t0, $f11 - j ra -set_fd_d_f12: - mtc1 t3, $f12 - mtc1 t0, $f13 - j ra -set_fd_d_f14: - mtc1 t3, $f14 - mtc1 t0, $f15 - j ra -set_fd_d_f16: - mtc1 t3, $f16 - mtc1 t0, $f17 - j ra -set_fd_d_f18: - mtc1 t3, $f18 - mtc1 t0, $f19 - j ra -set_fd_d_f20: - mtc1 t3, $f20 - mtc1 t0, $f21 - j ra -set_fd_d_f22: - mtc1 t3, $f22 - mtc1 t0, $f23 - j ra -set_fd_d_f24: - mtc1 t3, $f24 - mtc1 t0, $f25 - j ra -set_fd_d_f26: - mtc1 t3, $f26 - mtc1 t0, $f27 - j ra -set_fd_d_f28: - mtc1 t3, $f28 - mtc1 t0, $f29 - j ra -set_fd_d_f30: - mtc1 t3, $f30 - mtc1 t0, $f31 - j ra -END(set_fd_d) - -/*---------------------------------------------------------------------------- - * renorm_fs_s -- - * - * Results: - * t1 unbiased exponent - * t2 normalized fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(renorm_fs_s) -/* - * Find out how many leading zero bits are in t2 and put in t9. - */ - move v0, t2 - move t9, zero - srl v1, v0, 16 - bne v1, zero, 1f - addu t9, 16 - sll v0, 16 -1: - srl v1, v0, 24 - bne v1, zero, 1f - addu t9, 8 - sll v0, 8 -1: - srl v1, v0, 28 - bne v1, zero, 1f - addu t9, 4 - sll v0, 4 -1: - srl v1, v0, 30 - bne v1, zero, 1f - addu t9, 2 - sll v0, 2 -1: - srl v1, v0, 31 - bne v1, zero, 1f - addu t9, 1 -/* - * Now shift t2 the correct number of bits. - */ -1: - subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros - li t1, SEXP_MIN - subu t1, t1, t9 # adjust exponent - sll t2, t2, t9 - j ra -END(renorm_fs_s) - -/*---------------------------------------------------------------------------- - * renorm_fs_d -- - * - * Results: - * t1 unbiased exponent - * t2,t3 normalized fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(renorm_fs_d) -/* - * Find out how many leading zero bits are in t2,t3 and put in t9. - */ - move v0, t2 - move t9, zero - bne t2, zero, 1f - move v0, t3 - addu t9, 32 -1: - srl v1, v0, 16 - bne v1, zero, 1f - addu t9, 16 - sll v0, 16 -1: - srl v1, v0, 24 - bne v1, zero, 1f - addu t9, 8 - sll v0, 8 -1: - srl v1, v0, 28 - bne v1, zero, 1f - addu t9, 4 - sll v0, 4 -1: - srl v1, v0, 30 - bne v1, zero, 1f - addu t9, 2 - sll v0, 2 -1: - srl v1, v0, 31 - bne v1, zero, 1f - addu t9, 1 -/* - * Now shift t2,t3 the correct number of bits. - */ -1: - subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros - li t1, DEXP_MIN - subu t1, t1, t9 # adjust exponent - li v0, 32 - blt t9, v0, 1f - subu t9, t9, v0 # shift fraction left >= 32 bits - sll t2, t3, t9 - move t3, zero - j ra -1: - subu v0, v0, t9 # shift fraction left < 32 bits - sll t2, t2, t9 - srl v1, t3, v0 - or t2, t2, v1 - sll t3, t3, t9 - j ra -END(renorm_fs_d) - -/*---------------------------------------------------------------------------- - * renorm_ft_s -- - * - * Results: - * t5 unbiased exponent - * t6 normalized fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(renorm_ft_s) -/* - * Find out how many leading zero bits are in t6 and put in t9. - */ - move v0, t6 - move t9, zero - srl v1, v0, 16 - bne v1, zero, 1f - addu t9, 16 - sll v0, 16 -1: - srl v1, v0, 24 - bne v1, zero, 1f - addu t9, 8 - sll v0, 8 -1: - srl v1, v0, 28 - bne v1, zero, 1f - addu t9, 4 - sll v0, 4 -1: - srl v1, v0, 30 - bne v1, zero, 1f - addu t9, 2 - sll v0, 2 -1: - srl v1, v0, 31 - bne v1, zero, 1f - addu t9, 1 -/* - * Now shift t6 the correct number of bits. - */ -1: - subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros - li t5, SEXP_MIN - subu t5, t5, t9 # adjust exponent - sll t6, t6, t9 - j ra -END(renorm_ft_s) - -/*---------------------------------------------------------------------------- - * renorm_ft_d -- - * - * Results: - * t5 unbiased exponent - * t6,t7 normalized fraction - * - *---------------------------------------------------------------------------- - */ -LEAF(renorm_ft_d) -/* - * Find out how many leading zero bits are in t6,t7 and put in t9. - */ - move v0, t6 - move t9, zero - bne t6, zero, 1f - move v0, t7 - addu t9, 32 -1: - srl v1, v0, 16 - bne v1, zero, 1f - addu t9, 16 - sll v0, 16 -1: - srl v1, v0, 24 - bne v1, zero, 1f - addu t9, 8 - sll v0, 8 -1: - srl v1, v0, 28 - bne v1, zero, 1f - addu t9, 4 - sll v0, 4 -1: - srl v1, v0, 30 - bne v1, zero, 1f - addu t9, 2 - sll v0, 2 -1: - srl v1, v0, 31 - bne v1, zero, 1f - addu t9, 1 -/* - * Now shift t6,t7 the correct number of bits. - */ -1: - subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros - li t5, DEXP_MIN - subu t5, t5, t9 # adjust exponent - li v0, 32 - blt t9, v0, 1f - subu t9, t9, v0 # shift fraction left >= 32 bits - sll t6, t7, t9 - move t7, zero - j ra -1: - subu v0, v0, t9 # shift fraction left < 32 bits - sll t6, t6, t9 - srl v1, t7, v0 - or t6, t6, v1 - sll t7, t7, t9 - j ra -END(renorm_ft_d) diff --git a/sys/arch/arc/arc/genassym.cf b/sys/arch/arc/arc/genassym.cf deleted file mode 100644 index 09c1dc463151..000000000000 --- a/sys/arch/arc/arc/genassym.cf +++ /dev/null @@ -1,57 +0,0 @@ -# $OpenBSD: genassym.cf,v 1.1 1997/04/19 17:19:42 pefo Exp $ */ -# -# Copyright (c) 1997 Per Fogelstrom / Opsycon AB -# -# 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 under OpenBSD by -# Per Fogelstrom. -# 4. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -# - - -include -include -include -include -include -include - -include - - -define P_FORW offsetof(struct proc, p_forw) -define P_BACK offsetof(struct proc, p_back) -define P_PRIORITY offsetof(struct proc, p_priority) -define P_ADDR offsetof(struct proc, p_addr) -define P_UPTE offsetof(struct proc, p_md.md_upte) -define U_PCB_REGS offsetof(struct user, u_pcb.pcb_regs[ZERO]) -define U_PCB_FPREGS offsetof(struct user, u_pcb.pcb_regs[F0]) -define U_PCB_CONTEXT offsetof(struct user, u_pcb.pcb_context) -define U_PCB_ONFAULT offsetof(struct user, u_pcb.pcb_onfault) -define U_PCB_SEGTAB offsetof(struct user, u_pcb.pcb_segtab) -define V_SWTCH offsetof(struct vmmeter, v_swtch) - -define VM_MIN_KERNEL_ADDRESS VM_MIN_KERNEL_ADDRESS -define SIGFPE SIGFPE diff --git a/sys/arch/arc/arc/locore.S b/sys/arch/arc/arc/locore.S deleted file mode 100644 index d3e3b04748bb..000000000000 --- a/sys/arch/arc/arc/locore.S +++ /dev/null @@ -1,4178 +0,0 @@ -/* $NetBSD: locore.S,v 1.9 2000/01/23 20:09:10 soda Exp $ */ - -/* - * 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 -#include - -#include -#include -#include -#include -#include - -#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 start - .globl _C_LABEL(kernel_text) -start: -_C_LABEL(kernel_text): - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mtc0 zero, MIPS_COP_0_CAUSE_REG # Clear soft interrupts - -/* - * Initialize stack and call machine startup. - */ - la sp, start - START_FRAME -#ifdef __GP_SUPPORT__ - la gp, _C_LABEL(_gp) -#endif - sw zero, START_FRAME - 4(sp) # Zero out old ra for debugger - jal mips_init # mips_init(argc, argv, envp) - sw zero, START_FRAME - 8(sp) # Zero out old fp for debugger - - li t0, MIPS_SR_COP_1_BIT # Disable interrupts and - mtc0 t0, MIPS_COP_0_STATUS_REG # enable the fp coprocessor - li sp, KERNELSTACK - START_FRAME # switch to standard stack - mfc0 t0, MIPS_COP_0_PRID # read processor ID register - - nop # XXX r4000 pipeline: - nop # wait for new status to - nop # to be effective - nop - cfc1 t1, MIPS_FPU_ID # read FPU ID register - sw t0, _C_LABEL(cpu_id) # save PRID register - sw t1, _C_LABEL(fpu_id) # save FPU ID register - jal _C_LABEL(main) # main(regs) - move a0, zero -/* - * proc[1] == /etc/init now running here. - * Restore user registers and return. - */ - .set noat - li v0, MIPS_SR_EXL - mtc0 v0, MIPS_COP_0_STATUS_REG # set exeption level bit. - 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 a0, UADDR+U_PCB_REGS+(PC * 4) - lw AT, UADDR+U_PCB_REGS+(AST * 4) - lw v0, UADDR+U_PCB_REGS+(V0 * 4) - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - li a0, PSL_USERSET - mtc0 a0, MIPS_COP_0_STATUS_REG # switch to user mode - 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) - eret - .set at - -/* - * GCC2 seems to want to call __main in main() for some reason. - */ -LEAF(__main) - j ra - nop -END(__main) - -/* - * 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 2 -_C_LABEL(onfault_table): - .word 0 # invalid index number -#define BADERR 1 - .word _C_LABEL(baderr) -#define COPYERR 2 - .word _C_LABEL(copyerr) -#define FSWBERR 3 - .word _C_LABEL(fswberr) -#define FSWINTRBERR 4 - .word _C_LABEL(fswintrberr) -#ifdef DEBUG -#define MDBERR 5 - .word _C_LABEL(mdberr) -#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 errors -baderr: - j ra - li v0, 1 # trap sends us here -END(badaddr) - -/* - * 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 sigcode -sigcode: - addu a0, sp, 16 # address of sigcontext - li v0, SYS_sigreturn # sigreturn(scp) - syscall - break 0 # just in case sigreturn fails - .globl esigcode -esigcode: - -/* - * netorder = htonl(hostorder) - * hostorder = ntohl(netorder) - */ -LEAF(htonl) # a0 = 0x11223344, return 0x44332211 -ALEAF(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, v1 -END(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, v1 -END(htons) - -/* - * bit = ffs(value) - */ -LEAF(ffs) - beq a0, zero, 2f - move v0, zero -1: - and v1, a0, 1 # bit set? - addu v0, v0, 1 - beq v1, zero, 1b # no, continue - srl a0, a0, 1 -2: - j ra - nop -END(ffs) - -/* - * strlen(str) - */ -LEAF(strlen) - addu v1, a0, 1 -1: - 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' char -END(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, 2 -NotEq: - j ra - subu v0, t0, t1 -LessOrEq: - j ra - subu v0, zero, t1 -END(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, a3 -1: - and v0, a1, 3 # compute number of words left - subu a3, a1, v0 - move a1, v0 - addu a3, a3, a0 # compute ending address -2: - 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 speed -smallclr: - ble a1, zero, 2f - addu a3, a1, a0 # compute ending address -1: - addu a0, a0, 1 # clear bytes - bne a0, a3, 1b - sb zero, -1(a0) -2: - j ra - nop -END(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, a3 -1: - 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 address -2: - 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 - nop -unalignedcmp: - beq a3, zero, 2f - subu a2, a2, a3 # subtract from remaining count - addu a3, a3, a0 # compute ending address -1: - 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 - nop -2: - 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 address -3: - 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 - nop -smallcmp: - ble a2, zero, match - addu a3, a2, a0 # compute ending address -1: - lbu v0, 0(a0) - lbu v1, 0(a1) - addu a0, a0, 1 - bne v0, v1, nomatch - addu a1, a1, 1 - bne a0, a3, 1b - nop -match: - j ra - move v0, zero -nomatch: - j ra - li v0, 1 -END(bcmp) - -/* - * memcpy(to, from, len) - * {ov}bcopy(from, to, len) - */ -LEAF(memcpy) - move v0, a0 # swap from and to - move a0, a1 - move a1, v0 -ALEAF(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 region -1: - 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 - nop -forward: - 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, a3 -1: - and v1, a2, 3 # compute number of words left - subu a3, a2, v1 - move a2, v1 - addu a3, a3, a0 # compute ending address -2: - lwr v1, 0(a0) # copy words a0 unaligned, a1 aligned - lwl v1, 3(a0) - addu a0, a0, 4 - sw v1, 0(a1) - addu a1, a1, 4 - bne a0, a3, 2b - nop # We have to do this mmu-bug. - b smallcpy - nop -aligned: - beq a3, zero, 1f - subu a2, a2, a3 # subtract from remaining count - lwr v1, 0(a0) # copy 1, 2, or 3 bytes to align - addu a0, a0, a3 - swr v1, 0(a1) - addu a1, a1, a3 -1: - and v1, a2, 3 # compute number of whole words left - subu a3, a2, v1 - move a2, v1 - addu a3, a3, a0 # compute ending address -2: - lw v1, 0(a0) # copy words - addu a0, a0, 4 - sw v1, 0(a1) - bne a0, a3, 2b - addu a1, a1, 4 -smallcpy: - ble a2, zero, 2f - addu a3, a2, a0 # compute ending address -1: - lbu v1, 0(a0) # copy bytes - addu a0, a0, 1 - sb v1, 0(a1) - addu a1, a1, 1 - bne a0, a3, 1b - nop # MMU BUG ? (cant do -1(a1) !! -2: - j ra - nop -END(memcpy) - -/* - * fillw(pat, addr, count) - */ -LEAF(fillw) -1: - addiu a2, a2, -1 - sh a0, 0(a1) - bne a2,zero, 1b - addiu a1, a1, 2 - - jr ra - nop -END(fillw) - - -/* - * Copy a null terminated string within the kernel address space. - * Maxlength may be null if count not wanted. - * copystr(fromaddr, toaddr, maxlength, &lencopied) - * caddr_t fromaddr; - * caddr_t toaddr; - * u_int maxlength; - * u_int lencopied; - */ -LEAF(copystr) - move t2, a2 # Save the number of bytes -1: - lbu t0, 0(a0) - subu a2, a2, 1 - beq t0, zero, 2f - sb t0, 0(a1) - addu a0, a0, 1 - bne a2, zero, 1b - addu a1, a1, 1 -2: - beq a3, zero, 3f - subu a2, t2, a2 # compute length copied - sw a2, 0(a3) -3: - j ra - move v0, zero -END(copystr) - -/* - * Copy a null terminated string from the user address space into - * the kernel address space. - * - * copyinstr(fromaddr, toaddr, maxlength, &lencopied) - * caddr_t fromaddr; - * caddr_t toaddr; - * u_int maxlength; - * u_int *lencopied; - */ -NON_LEAF(copyinstr, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - sw ra, STAND_RA_OFFSET(sp) - blt a0, zero, copyerr # make sure address is in user space - li v0, COPYERR - jal copystr - sw v0, UADDR+U_PCB_ONFAULT - lw ra, STAND_RA_OFFSET(sp) - sw zero, UADDR+U_PCB_ONFAULT - addu sp, sp, STAND_FRAME_SIZE - j ra - move v0, zero -END(copyinstr) - -/* - * Copy a null terminated string from the kernel address space into - * the user address space. - * - * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) - * caddr_t fromaddr; - * caddr_t toaddr; - * u_int maxlength; - * u_int *lencopied; - */ -NON_LEAF(copyoutstr, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - sw ra, STAND_RA_OFFSET(sp) - blt a1, zero, copyerr # make sure address is in user space - li v0, COPYERR - jal copystr - sw v0, UADDR+U_PCB_ONFAULT - lw ra, STAND_RA_OFFSET(sp) - sw zero, UADDR+U_PCB_ONFAULT - addu sp, sp, STAND_FRAME_SIZE - j ra - move v0, zero -END(copyoutstr) - -/* - * Copy specified amount of data from user space into the kernel - * copyin(from, to, len) - * caddr_t *from; (user source address) - * caddr_t *to; (kernel destination address) - * unsigned len; - */ -NON_LEAF(copyin, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - sw ra, STAND_RA_OFFSET(sp) - blt a0, zero, copyerr # make sure address is in user space - li v0, COPYERR - jal bcopy - sw v0, UADDR+U_PCB_ONFAULT - lw ra, STAND_RA_OFFSET(sp) - sw zero, UADDR+U_PCB_ONFAULT - addu sp, sp, STAND_FRAME_SIZE - j ra - move v0, zero -END(copyin) - -/* - * Copy specified amount of data from kernel to the user space - * copyout(from, to, len) - * caddr_t *from; (kernel source address) - * caddr_t *to; (user destination address) - * unsigned len; - */ -NON_LEAF(copyout, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - sw ra, STAND_RA_OFFSET(sp) - blt a1, zero, copyerr # make sure address is in user space - li v0, COPYERR - jal bcopy - sw v0, UADDR+U_PCB_ONFAULT - lw ra, STAND_RA_OFFSET(sp) - sw zero, UADDR+U_PCB_ONFAULT - addu sp, sp, STAND_FRAME_SIZE - j ra - move v0, zero -END(copyout) - -LEAF(copyerr) - lw ra, STAND_RA_OFFSET(sp) - sw zero, UADDR+U_PCB_ONFAULT - addu sp, sp, STAND_FRAME_SIZE - j ra - li v0, EFAULT # return error -END(copyerr) - -/* - * Copy the kernel stack to the new process and save the current context so - * the new process will return nonzero when it is resumed by cpu_switch(). - * - * copykstack(up) - * struct user *up; - */ -LEAF(copykstack) - subu v0, sp, UADDR # compute offset into stack - addu v0, v0, a0 # v0 = new stack address - move v1, sp # v1 = old stack address - li t1, KERNELSTACK -1: - lw t0, 0(v1) # copy stack data - addu v1, v1, 4 - sw t0, 0(v0) - bne v1, t1, 1b - addu v0, v0, 4 - /* FALLTHROUGH */ -/* - * Save registers and state so we can do a longjmp later. - * Note: this only works if p != curproc since - * cpu_switch() will copy over pcb_context. - * - * savectx(up) - * struct user *up; - */ -ALEAF(savectx) - sw s0, U_PCB_CONTEXT+0(a0) - sw s1, U_PCB_CONTEXT+4(a0) - sw s2, U_PCB_CONTEXT+8(a0) - sw s3, U_PCB_CONTEXT+12(a0) - mfc0 v0, MIPS_COP_0_STATUS_REG - sw s4, U_PCB_CONTEXT+16(a0) - sw s5, U_PCB_CONTEXT+20(a0) - sw s6, U_PCB_CONTEXT+24(a0) - sw s7, U_PCB_CONTEXT+28(a0) - sw sp, U_PCB_CONTEXT+32(a0) - sw s8, U_PCB_CONTEXT+36(a0) - sw ra, U_PCB_CONTEXT+40(a0) - sw v0, U_PCB_CONTEXT+44(a0) - j ra - move v0, zero -END(copykstack) - -/* - * The following primitives manipulate the run queues. _whichqs tells which - * of the 32 queues _qs have processes in them. Setrunqueue puts processes - * into queues, remrunqueue removes them from queues. The running process is - * on no queue, other processes are on a queue related to p->p_priority, - * divided by 4 actually to shrink the 0-127 range of priorities into the 32 - * available queues. - */ -/* - * setrunqueue(p) - * proc *p; - * - * Call should be made at splclock(), and p->p_stat should be SRUN. - */ -NON_LEAF(setrunqueue, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - lw t0, P_BACK(a0) ## firewall: p->p_back must be 0 - sw ra, STAND_RA_OFFSET(sp) ## - beq t0, zero, 1f ## - lbu t0, P_PRIORITY(a0) # put on p->p_priority / 4 queue - PANIC("setrunqueue") ## -1: - li t1, 1 # compute corresponding bit - srl t0, t0, 2 # compute index into 'whichqs' - sll t1, t1, t0 - lw t2, _C_LABEL(whichqs) # set corresponding bit - nop - or t2, t2, t1 - sw t2, _C_LABEL(whichqs) - sll t0, t0, 3 # compute index into 'qs' - la t1, _C_LABEL(qs) - addu t0, t0, t1 # t0 = qp = &qs[pri >> 2] - lw t1, P_BACK(t0) # t1 = qp->ph_rlink - sw t0, P_FORW(a0) # p->p_forw = qp - sw t1, P_BACK(a0) # p->p_back = qp->ph_rlink - sw a0, P_FORW(t1) # p->p_back->p_forw = p; - sw a0, P_BACK(t0) # qp->ph_rlink = p - j ra - addu sp, sp, STAND_FRAME_SIZE -END(setrunqueue) - -/* - * remrunqueue(p) - * - * Call should be made at splclock(). - */ -NON_LEAF(remrunqueue, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - lbu t0, P_PRIORITY(a0) # get from p->p_priority / 4 queue - li t1, 1 # compute corresponding bit - srl t0, t0, 2 # compute index into 'whichqs' - lw t2, _C_LABEL(whichqs) # check corresponding bit - sll t1, t1, t0 - and v0, t2, t1 - sw ra, STAND_RA_OFFSET(sp) ## - bne v0, zero, 1f ## - lw v0, P_BACK(a0) # v0 = p->p_back - PANIC("remrunqueue") ## it wasnt recorded to be on its q -1: - lw v1, P_FORW(a0) # v1 = p->p_forw - nop - sw v1, P_FORW(v0) # p->p_back->p_forw = p->p_forw; - sw v0, P_BACK(v1) # p->p_forw->p_back = p->r_rlink - sll t0, t0, 3 # compute index into 'qs' - la v0, _C_LABEL(qs) - addu t0, t0, v0 # t0 = qp = &qs[pri >> 2] - lw v0, P_FORW(t0) # check if queue empty - nop - bne v0, t0, 2f # No. qp->ph_link != qp - nop - xor t2, t2, t1 # clear corresponding bit in 'whichqs' - sw t2, _C_LABEL(whichqs) -2: - sw zero, P_BACK(a0) ## for firewall checking - j ra - addu sp, sp, STAND_FRAME_SIZE -END(remrunqueue) - -/* - * switch_exit() - * - * At exit of a process, do a cpu_switch for the last time. - * The mapping of the pcb at p->p_addr has already been deleted, - * and the memory for the pcb+stack has been freed. - * All interrupts should be blocked at this point. - */ -LEAF(switch_exit) - la v1, nullproc # save state into garbage proc - lw t0, P_UPTE+0(v1) # t0 = first u. pte - lw t1, P_UPTE+4(v1) # t1 = 2nd u. pte - li v0, UADDR # v0 = first HI entry - mtc0 zero, MIPS_COP_0_TLB_INDEX # set the index register - dmtc0 v0, MIPS_COP_0_TLB_HI # init high entry - dmtc0 t0, MIPS_COP_0_TLB_LO0 # init low entry0 - dmtc0 t1, MIPS_COP_0_TLB_LO1 # init low entry1 - nop - tlbwi # Write the TLB entry. - nop - nop - sw zero, curproc - b cpu_switch - li sp, KERNELSTACK - START_FRAME # switch to standard stack -END(switch_exit) - -/* - * When no processes are on the runq, cpu_switch branches to idle - * to wait for something to come ready. - * Note: this is really a part of cpu_switch() but defined here for kernel - * profiling. - */ -LEAF(idle) - li t0, (MIPS_INT_MASK | MIPS_SR_INT_IE) - mtc0 t0, MIPS_COP_0_STATUS_REG # enable all interrupts - sw zero, curproc # set curproc NULL for stats -1: - lw t0, _C_LABEL(whichqs) # look for non-empty queue - nop - beq t0, zero, 1b - nop - b sw1 - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable all interrupts -END(idle) - -/* - * cpu_switch() - * Find the highest priority process and resume it. - */ -NON_LEAF(cpu_switch, STAND_FRAME_SIZE, ra) - sw sp, UADDR+U_PCB_CONTEXT+32 # save old sp - subu sp, sp, STAND_FRAME_SIZE - sw ra, STAND_RA_OFFSET(sp) - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - lw t2, cnt+V_SWTCH # for statistics - lw t1, _C_LABEL(whichqs) # look for non-empty queue - sw s0, UADDR+U_PCB_CONTEXT+0 # do a 'savectx()' - sw s1, UADDR+U_PCB_CONTEXT+4 - sw s2, UADDR+U_PCB_CONTEXT+8 - sw s3, UADDR+U_PCB_CONTEXT+12 - mfc0 t0, MIPS_COP_0_STATUS_REG # t0 = saved status register - sw s4, UADDR+U_PCB_CONTEXT+16 - sw s5, UADDR+U_PCB_CONTEXT+20 - sw s6, UADDR+U_PCB_CONTEXT+24 - sw s7, UADDR+U_PCB_CONTEXT+28 - sw s8, UADDR+U_PCB_CONTEXT+36 - sw ra, UADDR+U_PCB_CONTEXT+40 # save return address - sw t0, UADDR+U_PCB_CONTEXT+44 # save status register - addu t2, t2, 1 - sw t2, cnt+V_SWTCH - beq t1, zero, idle # if none, idle - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable all interrupts -sw1: - nop # wait for intrs disabled - nop - nop - nop - lw t0, _C_LABEL(whichqs) # look for non-empty queue - li t2, -1 # t2 = lowest bit set - beq t0, zero, idle # if none, idle - move t3, t0 # t3 = saved whichqs -1: - addu t2, t2, 1 - and t1, t0, 1 # bit set? - beq t1, zero, 1b - srl t0, t0, 1 # try next bit -/* - * Remove process from queue. - */ - sll t0, t2, 3 - la t1, _C_LABEL(qs) - addu t0, t0, t1 # t0 = qp = &qs[highbit] - lw a0, P_FORW(t0) # a0 = p = highest pri process - nop - lw v0, P_FORW(a0) # v0 = p->p_forw - bne t0, a0, 2f # make sure something in queue - sw v0, P_FORW(t0) # qp->ph_link = p->p_forw; - PANIC("cpu_switch") # nothing in queue -2: - sw t0, P_BACK(v0) # p->p_forw->p_back = qp - bne v0, t0, 3f # queue still not empty - sw zero, P_BACK(a0) ## for firewall checking - li v1, 1 # compute bit in 'whichqs' - sll v1, v1, t2 - xor t3, t3, v1 # clear bit in 'whichqs' - sw t3, _C_LABEL(whichqs) -3: -/* - * Switch to new context. - */ - sw zero, want_resched - jal pmap_alloc_tlbpid # v0 = TLB PID - move s0, a0 # BDSLOT: save p - sw s0, curproc # set curproc - lw t0, P_UPTE+0(s0) # t0 = first u. pte - lw t1, P_UPTE+4(s0) # t1 = 2nd u. pte - or v0, v0, UADDR # v0 = first HI entry -/* - * Resume process indicated by the pte's for its u struct - * NOTE: This is hard coded to UPAGES == 2. - * Also, there should be no TLB faults at this point. - */ - mtc0 zero, MIPS_COP_0_TLB_INDEX # set the index register - dmtc0 v0, MIPS_COP_0_TLB_HI # init high entry - dmtc0 t0, MIPS_COP_0_TLB_LO0 # init low entry0 - dmtc0 t1, MIPS_COP_0_TLB_LO1 # init low entry1 - nop - tlbwi # Write the TLB entry. - nop # Delay for effect - nop # Delay for effect - nop - nop -/* - * Now running on new u struct. - * Restore registers and return. - */ - lw v0, UADDR+U_PCB_CONTEXT+44 # restore kernel context - lw ra, UADDR+U_PCB_CONTEXT+40 - lw s0, UADDR+U_PCB_CONTEXT+0 - lw s1, UADDR+U_PCB_CONTEXT+4 - lw s2, UADDR+U_PCB_CONTEXT+8 - lw s3, UADDR+U_PCB_CONTEXT+12 - lw s4, UADDR+U_PCB_CONTEXT+16 - lw s5, UADDR+U_PCB_CONTEXT+20 - lw s6, UADDR+U_PCB_CONTEXT+24 - lw s7, UADDR+U_PCB_CONTEXT+28 - lw sp, UADDR+U_PCB_CONTEXT+32 - lw s8, UADDR+U_PCB_CONTEXT+36 - mtc0 v0, MIPS_COP_0_STATUS_REG - j ra - li v0, 1 # possible return to 'savectx()' -END(cpu_switch) - -/* - * {fu,su},{ibyte,isword,iword}, fetch or store a byte, short or word to - * user text space. - * {fu,su},{byte,sword,word}, fetch or store a byte, short or word to - * user data space. - */ -LEAF(fuword) -ALEAF(fuiword) - blt a0, zero, _C_LABEL(fswberr) # make sure address is in user space - li v0, FSWBERR - sw v0, UADDR+U_PCB_ONFAULT - lw v0, 0(a0) # fetch word - j ra - sw zero, UADDR+U_PCB_ONFAULT -END(fuword) - -LEAF(fusword) -ALEAF(fuisword) - blt a0, zero, _C_LABEL(fswberr) # make sure address is in user space - li v0, FSWBERR - sw v0, UADDR+U_PCB_ONFAULT - lhu v0, 0(a0) # fetch short - j ra - sw zero, UADDR+U_PCB_ONFAULT -END(fusword) - -LEAF(fubyte) -ALEAF(fuibyte) - blt a0, zero, _C_LABEL(fswberr) # make sure address is in user space - li v0, FSWBERR - sw v0, UADDR+U_PCB_ONFAULT - lbu v0, 0(a0) # fetch byte - j ra - sw zero, UADDR+U_PCB_ONFAULT -END(fubyte) - -LEAF(suword) - blt a0, zero, _C_LABEL(fswberr) # make sure address is in user space - li v0, FSWBERR - sw v0, UADDR+U_PCB_ONFAULT - sw a1, 0(a0) # store word - sw zero, UADDR+U_PCB_ONFAULT - j ra - move v0, zero -END(suword) - -/* - * Have to flush instruction cache afterwards. - */ -LEAF(suiword) - blt a0, zero, _C_LABEL(fswberr) # make sure address is in user space - li v0, FSWBERR - sw v0, UADDR+U_PCB_ONFAULT - sw a1, 0(a0) # store word - sw zero, UADDR+U_PCB_ONFAULT - move v0, zero - b MachFlushICache # NOTE: this should not clobber v0! - li a1, 4 # size of word -END(suiword) - -/* - * Will have to flush the instruction cache if byte merging is done in hardware. - */ -LEAF(susword) -ALEAF(suisword) - blt a0, zero, _C_LABEL(fswberr) # make sure address is in user space - li v0, FSWBERR - sw v0, UADDR+U_PCB_ONFAULT - sh a1, 0(a0) # store short - sw zero, UADDR+U_PCB_ONFAULT - j ra - move v0, zero -END(susword) - -LEAF(subyte) -ALEAF(suibyte) - blt a0, zero, _C_LABEL(fswberr) # make sure address is in user space - li v0, FSWBERR - sw v0, UADDR+U_PCB_ONFAULT - sb a1, 0(a0) # store byte - sw zero, UADDR+U_PCB_ONFAULT - j ra - move v0, zero -END(subyte) - -LEAF(fswberr) - j ra - li v0, -1 -END(fswberr) - -/* - * fuswintr and suswintr are just like fusword and susword except that if - * the page is not in memory or would cause a trap, then we return an error. - * The important thing is to prevent sleep() and switch(). - */ -LEAF(fuswintr) - blt a0, zero, fswintrberr # make sure address is in user space - li v0, FSWINTRBERR - sw v0, UADDR+U_PCB_ONFAULT - lhu v0, 0(a0) # fetch short - j ra - sw zero, UADDR+U_PCB_ONFAULT -END(fuswintr) - -LEAF(suswintr) - blt a0, zero, fswintrberr # make sure address is in user space - li v0, FSWINTRBERR - sw v0, UADDR+U_PCB_ONFAULT - sh a1, 0(a0) # store short - sw zero, UADDR+U_PCB_ONFAULT - j ra - move v0, zero -END(suswintr) - -LEAF(fswintrberr) - j ra - li v0, -1 -END(fswintrberr) - -/* - * Insert 'p' after 'q'. - * _insque(p, q) - * caddr_t p, q; - */ -LEAF(_insque) - lw v0, 0(a1) # v0 = q->next - sw a1, 4(a0) # p->prev = q - sw v0, 0(a0) # p->next = q->next - sw a0, 4(v0) # q->next->prev = p - j ra - sw a0, 0(a1) # q->next = p -END(_insque) - -/* - * Remove item 'p' from queue. - * _remque(p) - * caddr_t p; - */ -LEAF(_remque) - lw v0, 0(a0) # v0 = p->next - lw v1, 4(a0) # v1 = p->prev - nop - sw v0, 0(v1) # p->prev->next = p->next - j ra - sw v1, 4(v0) # p->next->prev = p->prev -END(_remque) - -/* - *---------------------------------------------------------------------------- - * - * mips_r2000_UTLBmiss -- - * MachUTLBmiss -- - * - * Vector code for a MIPS-I user-space TLB miss from user-space. - * - * - * This code is copied to the UTLB exception vector address to - * handle user level TLB translation misses. - * NOTE: This code must be relocatable!!! - */ - .globl _C_LABEL(mips_R2000_UTLBMiss) -_C_LABEL(mips_R2000_UTLBMiss): - .globl _C_LABEL(MachUTLBMiss) -_C_LABEL(MachUTLBMiss): - .set noat - mfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address - lw k1, UADDR+U_PCB_SEGTAB # get the current segment table - bltz k0, 1f # R3000 chip bug - srl k0, k0, SEGSHIFT # compute segment table index - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address - lw k1, 0(k1) # get pointer to segment map - srl k0, k0, PGSHIFT - 2 # compute segment map index - andi k0, k0, (NPTEPG - 1) << 2 - beq k1, zero, 2f # invalid segment map - addu k1, k1, k0 # index into segment map - lw k0, 0(k1) # get page PTE - nop - beq k0, zero, 2f # dont load invalid entries - mtc0 k0, MIPS_COP_0_TLB_LOW - mfc0 k1, MIPS_COP_0_EXC_PC # get return address - tlbwr # update TLB - j k1 - rfe -1: - mfc0 k1, MIPS_COP_0_EXC_PC # get return address - nop - j k1 - rfe -2: - j SlowFault # handle the rest - nop - .set at - .globl _C_LABEL(MachUTLBMissEnd) -_C_LABEL(MachUTLBMissEnd): - - .globl _C_LABEL(mips_R2000_UTLBMissEnd) -_C_LABEL(mips_R2000_UTLBMissEnd): - - -/* - *---------------------------------------------------------------------------- - * - * mips_R2000_execption -- - * - * Vector code for the general exception vector 0x80000080 - * on an r2000 or r3000. - * - * This code is copied to the general exception vector address to - * handle all execptions except RESET and UTLBMiss. - * NOTE: This code must be relocatable!!! - * - *---------------------------------------------------------------------------- - */ - .globl _C_LABEL(mips_R2000_exception) -_C_LABEL(mips_R2000_exception): -/* - * Find out what mode we came from and jump to the proper handler. - */ - .set noat - mfc0 k0, MIPS_COP_0_STATUS_REG # Get the status register - mfc0 k1, MIPS_COP_0_CAUSE_REG # Get the cause register value. - and k0, k0, MIPS_3K_SR_KU_PREV # test for user mode - sll k0, k0, 4 # shift user bit for cause index - and k1, k1, MIPS_3K_CR_EXC_CODE # Mask out the cause bits. - or k1, k1, k0 # change index to user table -1: - la k0, _C_LABEL(machExceptionTable) # get base of the jump table - addu k0, k0, k1 # Get the address of the - # function entry. Note that - # the cause is already - # shifted left by 2 bits so - # we dont have to shift. - lw k0, 0(k0) # Get the function address - nop - j k0 # Jump to the function. - nop - .set at - .globl _C_LABEL(mips_R2000_exceptionEnd) -_C_LABEL(mips_R2000_exceptionEnd): - - - -/* - *---------------------------------------------------------------------------- - * - * mips_R4000_TLBMiss -- - * MachTLBMiss -- - * - * Vector code for the TLB-miss exception vector 0x80000180 - * on an r4000. - * - * This code is copied to the TLB exception vector address to - * handle TLB translation misses. - * NOTE: This code must be relocatable and max 32 instructions!!! - * Don't check for invalid pte's here. We load them as well and - * let the processor trap to load the correct value after service. - * - *---------------------------------------------------------------------------- - */ - .globl _C_LABEL(mips_R4000_TLBMiss) -_C_LABEL(mips_R4000_TLBMiss): - .globl _C_LABEL(MachTLBMiss) -_C_LABEL(MachTLBMiss): - .set noat - dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address - lw k1, UADDR+U_PCB_SEGTAB # get the current segment table - bltz k0, 1f # kernel address space -> - srl k0, k0, SEGSHIFT - 2 # compute segment table index - andi k0, k0, 0x7fc # PMAP_SEGTABSIZ-1 - addu k1, k1, k0 - dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address - lw k1, 0(k1) # get pointer to segment map - srl k0, k0, PGSHIFT - 2 # compute segment map index - andi k0, k0, ((NPTEPG/2) - 1) << 3 - beq k1, zero, 2f # invalid segment map - addu k1, k1, k0 # index into segment map - lw k0, 0(k1) # get page PTE - lw k1, 4(k1) - dsll k0, k0, 34 - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO0 - dsll k1, k1, 34 - dsrl k1, k1, 34 - dmtc0 k1, MIPS_COP_0_TLB_LO1 - nop - tlbwr # update TLB - nop - nop - nop - nop - nop - eret -1: - j MachTLBMissException - nop -2: - j SlowFault - nop - - .globl _C_LABEL(MachTLBMissEnd) -C_LABEL(MachTLBMissEnd): - .globl _C_LABEL(mips_R4000_TLBMissEnd) -_C_LABEL(mips_R4000_TLBMissEnd): - .set at - - -/* - *---------------------------------------------------------------------------- - * - * Mips_R4000_execption -- - * - * Vector code for the general exception vector 0x80000080 - * on an r4000 or r4400. - * - * This code is copied to the general exception vector address to - * handle all execptions except RESET and TLBMiss. - * NOTE: This code must be relocatable!!! - *---------------------------------------------------------------------------- - */ - .globl mips_r4000_exception -_C_LABEL(mips_R4000_exception): -/* - * Find out what mode we came from and jump to the proper handler. - */ - .set noat - mfc0 k0, MIPS_COP_0_STATUS_REG # Get the status register - mfc0 k1, MIPS_COP_0_CAUSE_REG # Get the cause register value. - and k0, k0, MIPS_4K_SR_KSU_USER # test for user mode - # sneaky but the bits are - # with us........ - sll k0, k0, 3 # shift user bit for cause index - and k1, k1, MIPS_4K_CR_EXC_CODE # Mask out the cause bits. - or k1, k1, k0 # change index to user table -1: - la k0, machExceptionTable # get base of the jump table - addu k0, k0, k1 # Get the address of the - # function entry. Note that - # the cause is already - # shifted left by 2 bits so - # we dont have to shift. - lw k0, 0(k0) # Get the function address - nop - j k0 # Jump to the function. - nop - .set at - .globl mips_R4000_exceptionEnd -_C_LABEL(mips_R4000_exceptionEnd): - - -/* - * We couldn't find a TLB entry. - * Find out what mode we came from and call the appropriate handler. - */ -SlowFault: - .set noat - mfc0 k0, MIPS_COP_0_STATUS_REG - nop - and k0, k0, MIPS_SR_KSU_USER - bne k0, zero, MachUserGenException - nop - .set at -/* - * Fall though ... - */ - -/*---------------------------------------------------------------------------- - * - * MachKernGenException -- - * - * Handle an exception from kernel mode. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -/* - * The kernel exception stack contains 18 saved general registers, - * the status register and the multiply lo and high registers. - * In addition, we set this up for linkage conventions. - */ -#define KERN_REG_SIZE (18 * 4) -#define KERN_REG_OFFSET (STAND_FRAME_SIZE) -#define KERN_SR_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE) -#define KERN_MULT_LO_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 4) -#define KERN_MULT_HI_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 8) -#define KERN_EXC_FRAME_SIZE (STAND_FRAME_SIZE + KERN_REG_SIZE + 12) - -NNON_LEAF(MachKernGenException, KERN_EXC_FRAME_SIZE, ra) - .set noat -#ifdef DEBUG - la k0, mdbpcb # save registers for mdb - sw s0, (S0 * 4)(k0) - sw s1, (S1 * 4)(k0) - sw s2, (S2 * 4)(k0) - sw s3, (S3 * 4)(k0) - sw s4, (S4 * 4)(k0) - sw s5, (S5 * 4)(k0) - sw s6, (S6 * 4)(k0) - sw s7, (S7 * 4)(k0) - sw s8, (S8 * 4)(k0) - sw gp, (GP * 4)(k0) - sw sp, (SP * 4)(k0) -#endif - subu sp, sp, KERN_EXC_FRAME_SIZE - .mask 0x80000000, (STAND_RA_OFFSET - KERN_EXC_FRAME_SIZE) -/* - * Save the relevant kernel registers onto the stack. - * We don't need to save s0 - s8, sp and gp because - * the compiler does it for us. - */ - sw AT, KERN_REG_OFFSET + 0(sp) - sw v0, KERN_REG_OFFSET + 4(sp) - sw v1, KERN_REG_OFFSET + 8(sp) - sw a0, KERN_REG_OFFSET + 12(sp) - mflo v0 - mfhi v1 - sw a1, KERN_REG_OFFSET + 16(sp) - sw a2, KERN_REG_OFFSET + 20(sp) - sw a3, KERN_REG_OFFSET + 24(sp) - sw t0, KERN_REG_OFFSET + 28(sp) - mfc0 a0, MIPS_COP_0_STATUS_REG # First arg is the status reg. - sw t1, KERN_REG_OFFSET + 32(sp) - sw t2, KERN_REG_OFFSET + 36(sp) - sw t3, KERN_REG_OFFSET + 40(sp) - sw t4, KERN_REG_OFFSET + 44(sp) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw t5, KERN_REG_OFFSET + 48(sp) - sw t6, KERN_REG_OFFSET + 52(sp) - sw t7, KERN_REG_OFFSET + 56(sp) - sw t8, KERN_REG_OFFSET + 60(sp) - mfc0 a2, MIPS_COP_0_BAD_VADDR # Third arg is the fault addr. - sw t9, KERN_REG_OFFSET + 64(sp) - sw ra, KERN_REG_OFFSET + 68(sp) - sw v0, KERN_MULT_LO_OFFSET(sp) - sw v1, KERN_MULT_HI_OFFSET(sp) - mfc0 a3, MIPS_COP_0_EXC_PC # Fourth arg is the pc. - sw a0, KERN_SR_OFFSET(sp) - - mtc0 zero,MIPS_COP_0_STATUS_REG # Set kernel no error level -/* - * Call the exception handler. - */ - jal trap - sw a3, STAND_RA_OFFSET(sp) # for debugging -/* - * Restore registers and return from the exception. - * v0 contains the return address. - */ - mtc0 zero,MIPS_COP_0_STATUS_REG # Make shure int disabled - lw a0, KERN_SR_OFFSET(sp) - lw t0, KERN_MULT_LO_OFFSET(sp) - lw t1, KERN_MULT_HI_OFFSET(sp) - mtc0 a0, MIPS_COP_0_STATUS_REG # Restore the SR, disable intrs - mtlo t0 - mthi t1 - dmtc0 v0, MIPS_COP_0_EXC_PC # set return address - lw AT, KERN_REG_OFFSET + 0(sp) - lw v0, KERN_REG_OFFSET + 4(sp) - lw v1, KERN_REG_OFFSET + 8(sp) - lw a0, KERN_REG_OFFSET + 12(sp) - lw a1, KERN_REG_OFFSET + 16(sp) - lw a2, KERN_REG_OFFSET + 20(sp) - lw a3, KERN_REG_OFFSET + 24(sp) - lw t0, KERN_REG_OFFSET + 28(sp) - lw t1, KERN_REG_OFFSET + 32(sp) - lw t2, KERN_REG_OFFSET + 36(sp) - lw t3, KERN_REG_OFFSET + 40(sp) - lw t4, KERN_REG_OFFSET + 44(sp) - lw t5, KERN_REG_OFFSET + 48(sp) - lw t6, KERN_REG_OFFSET + 52(sp) - lw t7, KERN_REG_OFFSET + 56(sp) - lw t8, KERN_REG_OFFSET + 60(sp) - lw t9, KERN_REG_OFFSET + 64(sp) - lw ra, KERN_REG_OFFSET + 68(sp) - addu sp, sp, KERN_EXC_FRAME_SIZE - eret # exception. - .set at -END(MachKernGenException) - -/*---------------------------------------------------------------------------- - * - * MachUserGenException -- - * - * Handle an exception from user mode. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(MachUserGenException, STAND_FRAME_SIZE, ra) - .set noat - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) -/* - * Save all of the registers except for the kernel temporaries in u.u_pcb. - */ - sw AT, UADDR+U_PCB_REGS+(AST * 4) - sw v0, UADDR+U_PCB_REGS+(V0 * 4) - sw v1, UADDR+U_PCB_REGS+(V1 * 4) - sw a0, UADDR+U_PCB_REGS+(A0 * 4) - mflo v0 - sw a1, UADDR+U_PCB_REGS+(A1 * 4) - sw a2, UADDR+U_PCB_REGS+(A2 * 4) - sw a3, UADDR+U_PCB_REGS+(A3 * 4) - sw t0, UADDR+U_PCB_REGS+(T0 * 4) - mfhi v1 - sw t1, UADDR+U_PCB_REGS+(T1 * 4) - sw t2, UADDR+U_PCB_REGS+(T2 * 4) - sw t3, UADDR+U_PCB_REGS+(T3 * 4) - sw t4, UADDR+U_PCB_REGS+(T4 * 4) - mfc0 a0, MIPS_COP_0_STATUS_REG # First arg is the status reg. - sw t5, UADDR+U_PCB_REGS+(T5 * 4) - sw t6, UADDR+U_PCB_REGS+(T6 * 4) - sw t7, UADDR+U_PCB_REGS+(T7 * 4) - sw s0, UADDR+U_PCB_REGS+(S0 * 4) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw s1, UADDR+U_PCB_REGS+(S1 * 4) - sw s2, UADDR+U_PCB_REGS+(S2 * 4) - sw s3, UADDR+U_PCB_REGS+(S3 * 4) - sw s4, UADDR+U_PCB_REGS+(S4 * 4) - mfc0 a2, MIPS_COP_0_BAD_VADDR # Third arg is the fault addr - sw s5, UADDR+U_PCB_REGS+(S5 * 4) - sw s6, UADDR+U_PCB_REGS+(S6 * 4) - sw s7, UADDR+U_PCB_REGS+(S7 * 4) - sw t8, UADDR+U_PCB_REGS+(T8 * 4) - mfc0 a3, MIPS_COP_0_EXC_PC # Fourth arg is the pc. - sw t9, UADDR+U_PCB_REGS+(T9 * 4) - sw gp, UADDR+U_PCB_REGS+(GP * 4) - sw sp, UADDR+U_PCB_REGS+(SP * 4) - sw s8, UADDR+U_PCB_REGS+(S8 * 4) - li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP - sw ra, UADDR+U_PCB_REGS+(RA * 4) - sw v0, UADDR+U_PCB_REGS+(MULLO * 4) - sw v1, UADDR+U_PCB_REGS+(MULHI * 4) - sw a0, UADDR+U_PCB_REGS+(SR * 4) - la gp, _gp # switch to kernel GP - sw a3, UADDR+U_PCB_REGS+(PC * 4) - sw a3, STAND_RA_OFFSET(sp) # for debugging - .set at -# Turn off fpu and enter kernel mode - and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK | MIPS_SR_INT_IE) - .set noat -/* - * Call the exception handler. - */ - jal trap - mtc0 t0, MIPS_COP_0_STATUS_REG -/* - * Restore user registers and return. - * First disable interrupts and set exeption level. - */ - mtc0 zero, MIPS_COP_0_STATUS_REG # disable int - nop - nop - nop - li v0, MIPS_SR_EXL - mtc0 v0, MIPS_COP_0_STATUS_REG # set exeption level - - lw a0, UADDR+U_PCB_REGS+(SR * 4) - lw t0, UADDR+U_PCB_REGS+(MULLO * 4) - lw t1, UADDR+U_PCB_REGS+(MULHI * 4) - mtc0 a0, MIPS_COP_0_STATUS_REG # still exeption level - mtlo t0 - mthi t1 - lw a0, UADDR+U_PCB_REGS+(PC * 4) - lw AT, UADDR+U_PCB_REGS+(AST * 4) - lw v0, UADDR+U_PCB_REGS+(V0 * 4) - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - 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) - eret - .set at -END(MachUserGenException) - -/*---------------------------------------------------------------------------- - * - * MachKernIntr -- - * - * Handle an interrupt from kernel mode. - * Interrupts use the standard kernel stack. - * switch_exit sets up a kernel stack after exit so interrupts won't fail. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -#define KINTR_REG_OFFSET (STAND_FRAME_SIZE) -#define KINTR_SR_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE) -#define KINTR_MULT_LO_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 4) -#define KINTR_MULT_HI_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 8) -#define KINTR_MULT_GP_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 12) -#define KINTR_FRAME_SIZE (STAND_FRAME_SIZE + KERN_REG_SIZE + 16) - -NNON_LEAF(MachKernIntr, KINTR_FRAME_SIZE, ra) - .set noat - subu sp, sp, KINTR_FRAME_SIZE # allocate stack frame - .mask 0x80000000, (STAND_RA_OFFSET - KINTR_FRAME_SIZE) -/* - * Save the relevant kernel registers onto the stack. - * We don't need to save s0 - s8, sp and gp because - * the compiler does it for us. - */ - sw AT, KINTR_REG_OFFSET + 0(sp) - sw v0, KINTR_REG_OFFSET + 4(sp) - sw v1, KINTR_REG_OFFSET + 8(sp) - sw a0, KINTR_REG_OFFSET + 12(sp) - mflo v0 - mfhi v1 - sw a1, KINTR_REG_OFFSET + 16(sp) - sw a2, KINTR_REG_OFFSET + 20(sp) - sw a3, KINTR_REG_OFFSET + 24(sp) - sw t0, KINTR_REG_OFFSET + 28(sp) - mfc0 a0, MIPS_COP_0_STATUS_REG # First arg is the status reg. - sw t1, KINTR_REG_OFFSET + 32(sp) - sw t2, KINTR_REG_OFFSET + 36(sp) - sw t3, KINTR_REG_OFFSET + 40(sp) - sw t4, KINTR_REG_OFFSET + 44(sp) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw t5, KINTR_REG_OFFSET + 48(sp) - sw t6, KINTR_REG_OFFSET + 52(sp) - sw t7, KINTR_REG_OFFSET + 56(sp) - sw t8, KINTR_REG_OFFSET + 60(sp) - mfc0 a2, MIPS_COP_0_EXC_PC # Third arg is the pc. - sw t9, KINTR_REG_OFFSET + 64(sp) - sw ra, KINTR_REG_OFFSET + 68(sp) - sw v0, KINTR_MULT_LO_OFFSET(sp) - sw v1, KINTR_MULT_HI_OFFSET(sp) - sw a0, KINTR_SR_OFFSET(sp) - - mtc0 zero, MIPS_COP_0_STATUS_REG # Reset exl, trap possible. -/* - * Call the interrupt handler. - */ - jal interrupt - sw a2, STAND_RA_OFFSET(sp) # for debugging -/* - * Restore registers and return from the interrupt. - */ - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupt - lw a0, KINTR_SR_OFFSET(sp) - lw t0, KINTR_MULT_LO_OFFSET(sp) - lw t1, KINTR_MULT_HI_OFFSET(sp) - mtc0 a0, MIPS_COP_0_STATUS_REG # Restore the SR, disable intrs - mtlo t0 - mthi t1 - lw a0, STAND_RA_OFFSET(sp) - lw AT, KINTR_REG_OFFSET + 0(sp) - lw v0, KINTR_REG_OFFSET + 4(sp) - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - lw v1, KINTR_REG_OFFSET + 8(sp) - lw a0, KINTR_REG_OFFSET + 12(sp) - lw a1, KINTR_REG_OFFSET + 16(sp) - lw a2, KINTR_REG_OFFSET + 20(sp) - lw a3, KINTR_REG_OFFSET + 24(sp) - lw t0, KINTR_REG_OFFSET + 28(sp) - lw t1, KINTR_REG_OFFSET + 32(sp) - lw t2, KINTR_REG_OFFSET + 36(sp) - lw t3, KINTR_REG_OFFSET + 40(sp) - lw t4, KINTR_REG_OFFSET + 44(sp) - lw t5, KINTR_REG_OFFSET + 48(sp) - lw t6, KINTR_REG_OFFSET + 52(sp) - lw t7, KINTR_REG_OFFSET + 56(sp) - lw t8, KINTR_REG_OFFSET + 60(sp) - lw t9, KINTR_REG_OFFSET + 64(sp) - lw ra, KINTR_REG_OFFSET + 68(sp) - addu sp, sp, KINTR_FRAME_SIZE - eret # interrupt. - .set at -END(MachKernIntr) - -/*---------------------------------------------------------------------------- - * - * MachUserIntr -- - * - * Handle an interrupt from user mode. - * Note: we save minimal state in the u.u_pcb struct and use the standard - * kernel stack since there has to be a u page if we came from user mode. - * If there is a pending software interrupt, then save the remaining state - * and call softintr(). This is all because if we call switch() inside - * interrupt(), not all the user registers have been saved in u.u_pcb. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(MachUserIntr, STAND_FRAME_SIZE, ra) - .set noat - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) -/* - * Save the relevant user registers into the u.u_pcb struct. - * We don't need to save s0 - s8 because - * the compiler does it for us. - */ - sw AT, UADDR+U_PCB_REGS+(AST * 4) - sw v0, UADDR+U_PCB_REGS+(V0 * 4) - sw v1, UADDR+U_PCB_REGS+(V1 * 4) - sw a0, UADDR+U_PCB_REGS+(A0 * 4) - mflo v0 - mfhi v1 - sw a1, UADDR+U_PCB_REGS+(A1 * 4) - sw a2, UADDR+U_PCB_REGS+(A2 * 4) - sw a3, UADDR+U_PCB_REGS+(A3 * 4) - sw t0, UADDR+U_PCB_REGS+(T0 * 4) - mfc0 a0, MIPS_COP_0_STATUS_REG # First arg is the status reg. - sw t1, UADDR+U_PCB_REGS+(T1 * 4) - sw t2, UADDR+U_PCB_REGS+(T2 * 4) - sw t3, UADDR+U_PCB_REGS+(T3 * 4) - sw t4, UADDR+U_PCB_REGS+(T4 * 4) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw t5, UADDR+U_PCB_REGS+(T5 * 4) - sw t6, UADDR+U_PCB_REGS+(T6 * 4) - sw t7, UADDR+U_PCB_REGS+(T7 * 4) - sw t8, UADDR+U_PCB_REGS+(T8 * 4) - mfc0 a2, MIPS_COP_0_EXC_PC # Third arg is the pc. - sw t9, UADDR+U_PCB_REGS+(T9 * 4) - sw gp, UADDR+U_PCB_REGS+(GP * 4) - sw sp, UADDR+U_PCB_REGS+(SP * 4) - sw ra, UADDR+U_PCB_REGS+(RA * 4) - li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP - sw v0, UADDR+U_PCB_REGS+(MULLO * 4) - sw v1, UADDR+U_PCB_REGS+(MULHI * 4) - sw a0, UADDR+U_PCB_REGS+(SR * 4) - sw a2, UADDR+U_PCB_REGS+(PC * 4) - la gp, _gp # switch to kernel GP -# Turn off fpu and enter kernel mode - .set at - and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_INT_IE | MIPS_SR_KSU_MASK) - .set noat - mtc0 t0, MIPS_COP_0_STATUS_REG -/* - * Call the interrupt handler. - */ - jal interrupt - sw a2, STAND_RA_OFFSET(sp) # for debugging -/* - * Restore registers and return from the interrupt. - */ - mtc0 zero, MIPS_COP_0_STATUS_REG - nop - nop - nop - li v0, MIPS_SR_EXL - mtc0 v0, MIPS_COP_0_STATUS_REG # set exeption level bit. - - lw a0, UADDR+U_PCB_REGS+(SR * 4) - lw v0, astpending # any pending interrupts? - mtc0 a0, MIPS_COP_0_STATUS_REG # Restore the SR, disable intrs - bne v0, zero, 1f # dont restore, call softintr - lw t0, UADDR+U_PCB_REGS+(MULLO * 4) - lw t1, UADDR+U_PCB_REGS+(MULHI * 4) - lw a0, UADDR+U_PCB_REGS+(PC * 4) - lw AT, UADDR+U_PCB_REGS+(AST * 4) - lw v0, UADDR+U_PCB_REGS+(V0 * 4) - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - 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) - mtlo t0 - mthi t1 - 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 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 ra, UADDR+U_PCB_REGS+(RA * 4) - eret # interrupt. - -1: -/* - * We have pending software interrupts; save remaining user state in u.u_pcb. - */ - sw s0, UADDR+U_PCB_REGS+(S0 * 4) - sw s1, UADDR+U_PCB_REGS+(S1 * 4) - sw s2, UADDR+U_PCB_REGS+(S2 * 4) - sw s3, UADDR+U_PCB_REGS+(S3 * 4) - sw s4, UADDR+U_PCB_REGS+(S4 * 4) - sw s5, UADDR+U_PCB_REGS+(S5 * 4) - sw s6, UADDR+U_PCB_REGS+(S6 * 4) - sw s7, UADDR+U_PCB_REGS+(S7 * 4) - sw s8, UADDR+U_PCB_REGS+(S8 * 4) - li t0, MIPS_HARD_INT_MASK | MIPS_SR_INT_IE -/* - * Call the software interrupt handler. - */ - jal softintr - mtc0 t0, MIPS_COP_0_STATUS_REG # enable interrupts (spl0) -/* - * Restore user registers and return. NOTE: interrupts are enabled. - */ - mtc0 zero, MIPS_COP_0_STATUS_REG - nop - nop - nop - li v0, MIPS_SR_EXL - mtc0 v0, MIPS_COP_0_STATUS_REG # set exeption level bit. - - lw a0, UADDR+U_PCB_REGS+(SR * 4) - lw t0, UADDR+U_PCB_REGS+(MULLO * 4) - lw t1, UADDR+U_PCB_REGS+(MULHI * 4) - mtc0 a0, MIPS_COP_0_STATUS_REG # this should disable interrupts - mtlo t0 - mthi t1 - lw a0, UADDR+U_PCB_REGS+(PC * 4) - lw AT, UADDR+U_PCB_REGS+(AST * 4) - lw v0, UADDR+U_PCB_REGS+(V0 * 4) - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - 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) - eret - .set at -END(MachUserIntr) - - -/* - * Set/clear software interrupt routines. - */ - -LEAF(setsoftclock) - mfc0 v0, MIPS_COP_0_CAUSE_REG # read cause register - nop - or v0, v0, MIPS_SOFT_INT_MASK_0 # set soft clock interrupt - mtc0 v0, MIPS_COP_0_CAUSE_REG # save it - j ra - nop -END(setsoftclock) - -LEAF(clearsoftclock) - mfc0 v0, MIPS_COP_0_CAUSE_REG # read cause register - nop - and v0, v0, ~MIPS_SOFT_INT_MASK_0 # clear soft clock interrupt - mtc0 v0, MIPS_COP_0_CAUSE_REG # save it - j ra - nop -END(clearsoftclock) - -LEAF(setsoftnet) - mfc0 v0, MIPS_COP_0_CAUSE_REG # read cause register - nop - or v0, v0, MIPS_SOFT_INT_MASK_1 # set soft net interrupt - mtc0 v0, MIPS_COP_0_CAUSE_REG # save it - j ra - nop -END(setsoftnet) - -LEAF(clearsoftnet) - mfc0 v0, MIPS_COP_0_CAUSE_REG # read cause register - nop - and v0, v0, ~MIPS_SOFT_INT_MASK_1 # clear soft net interrupt - mtc0 v0, MIPS_COP_0_CAUSE_REG # save it - j ra - nop -END(clearsoftnet) - -/* - * Set/change interrupt priority routines. - */ - -LEAF(MachEnableIntr) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - nop - or v0, v0, MIPS_SR_INT_IE - mtc0 v0, MIPS_COP_0_STATUS_REG # enable all interrupts - j ra - nop -END(MachEnableIntr) - -LEAF(spl0) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - nop - or t0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) - mtc0 t0, MIPS_COP_0_STATUS_REG # enable all interrupts - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(spl0) - -LEAF(splsoftclock) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~MIPS_SOFT_INT_MASK_0 # disable soft clock - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - nop # 3 ins to disable - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(splsoftclock) - -LEAF(splsoftnet) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~(MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0) - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(splsoftnet) - -LEAF(Mach_spl0) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~(MIPS_INT_MASK_0|MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0) - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - nop # 3 ins to disable - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(Mach_spl0) - -LEAF(Mach_spl1) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~(MIPS_INT_MASK_1|MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0) - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - nop # 3 ins to disable - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(Mach_spl1) - -LEAF(Mach_spl2) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~(MIPS_INT_MASK_2|MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0) - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - nop # 3 ins to disable - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(Mach_spl2) - -LEAF(Mach_spl3) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~(MIPS_INT_MASK_3|MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0) - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - nop # 3 ins to disable - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(Mach_spl3) - -LEAF(Mach_spl4) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~(MIPS_INT_MASK_4|MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0) - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - nop # 3 ins to disable - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(Mach_spl4) - -LEAF(Mach_spl5) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~(MIPS_INT_MASK_5|MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0) - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - nop # 3 ins to disable - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(Mach_spl5) - - -/* - * We define an alternate entry point after mcount is called so it - * can be used in mcount without causeing a recursive loop. - */ -LEAF(splhigh) -ALEAF(_splhigh) - mfc0 v0, MIPS_COP_0_STATUS_REG # read status register - li t0, ~MIPS_SR_INT_IE # disable all interrupts - and t0, t0, v0 - mtc0 t0, MIPS_COP_0_STATUS_REG # save it - nop # 3 ins to disable - j ra - and v0, v0, (MIPS_INT_MASK | MIPS_SR_INT_IE) -END(splhigh) - -/* - * Restore saved interrupt mask. - */ -LEAF(splx) -ALEAF(_splx) - mfc0 v0, MIPS_COP_0_STATUS_REG - li t0, ~(MIPS_INT_MASK | MIPS_SR_INT_IE) - and t0, t0, v0 - or t0, t0, a0 - mtc0 t0, MIPS_COP_0_STATUS_REG - nop # 3 ins to disable - j ra - nop -END(splx) - -/*---------------------------------------------------------------------------- - * - * wbflush -- - * - * Return when the write buffer is empty. - * - * wbflush() - * MachEmptyWriteBuffer() [[backwards compatibility]] - * - * Results: - * None. - * - * Side effects: - * None. - * - * XXX really r4000-specific, but the pmax wbflush() should be - * more tailored, too. - * - *---------------------------------------------------------------------------- - */ -LEAF(wbflush) -ALEAF(MachEmptyWriteBuffer) - nop - sync - j ra - nop -END(MachEmptyWriteBuffer) - -#ifdef notyet /* XXX XXX -- r3000 support, not yet */ - -/*---------------------------------------------------------------------------- - * - * XXX START of r3000-specific code XXX - * - *---------------------------------------------------------------------------- - */ - - - -#if 0 -/*---------------------------------------------------------------------------- - * - * MachTLBModException -- - * - * Handle a TLB modified exception. - * The BaddVAddr, Context, and EntryHi registers contain the failed - * virtual address. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NLEAF(MachTLBModException) - .set noat - tlbp # find the TLB entry - mfc0 k0, MIPS_COP_0_TLB_LOW # get the physical address - mfc0 k1, MIPS_COP_0_TLB_INDEX # check to be sure its valid - or k0, k0, VMMACH_TLB_MOD_BIT # update TLB - blt k1, zero, 4f # not found!!! - mtc0 k0, MIPS_COP_0_TLB_LOW - li k1, MACH_CACHED_MEMORY_ADDR - subu k0, k0, k1 - srl k0, k0, VMMACH_TLB_PHYS_PAGE_SHIFT - la k1, pmap_attributes - addu k0, k0, k1 - lbu k1, 0(k0) # fetch old value - nop - or k1, k1, 1 # set modified bit - sb k1, 0(k0) # save new value - mfc0 k0, MIPS_COP_0_EXC_PC # get return address - nop - j k0 - rfe -4: - break 0 # panic - .set at -END(MachTLBModException) -#endif - -/*---------------------------------------------------------------------------- - * - * MachTLBMissException -- - * - * Handle a TLB miss exception from kernel mode. - * The BaddVAddr, Context, and EntryHi registers contain the failed - * virtual address. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NLEAF(MachTLBMissException) - .set noat - mfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address - li k1, VM_MIN_KERNEL_ADDRESS # compute index - subu k0, k0, k1 - lw k1, _C_LABEL(Sysmapsize) # index within range? - srl k0, k0, PGSHIFT - sltu k1, k0, k1 - beq k1, zero, 1f # No. check for valid stack - nop - lw k1, _C_LABEL(Sysmap) - sll k0, k0, 2 # compute offset from index - addu k1, k1, k0 - lw k0, 0(k1) # get PTE entry - mfc0 k1, MIPS_COP_0_EXC_PC # get return address - mtc0 k0, MIPS_COP_0_TLB_LOW # save PTE entry - and k0, k0, PG_V # check for valid entry - beq k0, zero, _C_LABEL(MachKernGenException) # PTE invalid - nop - tlbwr # update TLB - j k1 - rfe - -1: - subu k0, sp, UADDR + 0x200 # check to see if we have a - sltiu k0, UPAGES*NBPG - 0x200 # valid kernel stack - bne k0, zero, _C_LABEL(MachKernGenException) # Go panic - nop - - la a0, start - START_FRAME - 8 # set sp to a valid place - sw sp, 24(a0) - move sp, a0 - la a0, 1f - mfc0 a2, MIPS_COP_0_STATUS_REG - mfc0 a3, MIPS_COP_0_CAUSE_REG - mfc0 a1, MIPS_COP_0_EXC_PC - sw a2, 16(sp) - sw a3, 20(sp) - sw sp, 24(sp) - move a2, ra - jal _C_LABEL(printf) - mfc0 a3, MIPS_COP_0_BAD_VADDR - .data -1: - .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n" - .text - - la sp, start - START_FRAME # set sp to a valid place - PANIC("kernel stack overflow") - .set at -END(MachTLBMissException) - - -/*-------------------------------------------------------------------------- - * - * MachTLBWriteIndexed -- - * - * Write the given entry into the TLB at the given index. - * - * MachTLBWriteIndexed(index, highEntry, lowEntry) - * int index; - * int highEntry; - * int lowEntry; - * - * Results: - * None. - * - * Side effects: - * TLB entry set. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBWriteIndexed) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Save the current PID. - - sll a0, a0, VMMACH_TLB_INDEX_SHIFT - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index. - mtc0 a1, MIPS_COP_0_TLB_HI # Set up entry high. - mtc0 a2, MIPS_COP_0_TLB_LOW # Set up entry low. - nop - tlbwi # Write the TLB - - mtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID. - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBWriteIndexed) - -#if 0 -/*-------------------------------------------------------------------------- - * - * MachTLBWriteRandom -- - * - * Write the given entry into the TLB at a random location. - * - * MachTLBWriteRandom(highEntry, lowEntry) - * unsigned highEntry; - * unsigned lowEntry; - * - * Results: - * None. - * - * Side effects: - * TLB entry set. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBWriteRandom) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 v0, MIPS_COP_0_TLB_HI # Save the current PID. - nop - - mtc0 a0, MIPS_COP_0_TLB_HI # Set up entry high. - mtc0 a1, MIPS_COP_0_TLB_LOW # Set up entry low. - nop - tlbwr # Write the TLB - - mtc0 v0, MIPS_COP_0_TLB_HI # Restore the PID. - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBWriteRandom) -#endif - -/*-------------------------------------------------------------------------- - * - * MachSetPID -- - * - * Write the given pid into the TLB pid reg. - * - * MachSetPID(pid) - * int pid; - * - * Results: - * None. - * - * Side effects: - * PID set in the entry hi register. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachSetPID) - sll a0, a0, VMMACH_TLB_PID_SHIFT # put PID in right spot - mtc0 a0, MIPS_COP_0_TLB_HI # Write the hi reg value - j ra - nop -END(MachSetPID) - -/*-------------------------------------------------------------------------- - * - * MachTLBFlush -- - * - * Flush the "random" entries from the TLB. - * - * MachTLBFlush() - * - * Results: - * None. - * - * Side effects: - * The TLB is flushed. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBFlush) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Save the PID - li t1, MACH_CACHED_MEMORY_ADDR # invalid address - mtc0 t1, MIPS_COP_0_TLB_HI # Mark entry high as invalid - mtc0 zero, MIPS_COP_0_TLB_LOW # Zero out low entry. -/* - * Align the starting value (t1) and the upper bound (t2). - */ - li t1, VMMACH_FIRST_RAND_ENTRY << VMMACH_TLB_INDEX_SHIFT - li t2, VMMACH_NUM_TLB_ENTRIES << VMMACH_TLB_INDEX_SHIFT -1: - mtc0 t1, MIPS_COP_0_TLB_INDEX # Set the index register. - addu t1, t1, 1 << VMMACH_TLB_INDEX_SHIFT # Increment index. - bne t1, t2, 1b - tlbwi # Write the TLB entry. - - mtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBFlush) - -#if 0 -/*-------------------------------------------------------------------------- - * - * MachTLBFlushPID -- - * - * Flush all entries with the given PID from the TLB. - * - * MachTLBFlushPID(pid) - * int pid; - * - * Results: - * None. - * - * Side effects: - * All entries corresponding to this PID are flushed. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBFlushPID) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Save the current PID - sll a0, a0, VMMACH_TLB_PID_SHIFT # Align the pid to flush. -/* - * Align the starting value (t1) and the upper bound (t2). - */ - li t1, VMMACH_FIRST_RAND_ENTRY << VMMACH_TLB_INDEX_SHIFT - li t2, VMMACH_NUM_TLB_ENTRIES << VMMACH_TLB_INDEX_SHIFT - mtc0 t1, MIPS_COP_0_TLB_INDEX # Set the index register -1: - addu t1, t1, 1 << VMMACH_TLB_INDEX_SHIFT # Increment index. - tlbr # Read from the TLB - mfc0 t4, MIPS_COP_0_TLB_HI # Fetch the hi register. - nop - and t4, t4, VMMACH_TLB_PID # compare PIDs - bne t4, a0, 2f - li v0, MACH_CACHED_MEMORY_ADDR # invalid address - mtc0 v0, MIPS_COP_0_TLB_HI # Mark entry high as invalid - mtc0 zero, MIPS_COP_0_TLB_LOW # Zero out low entry. - nop - tlbwi # Write the entry. -2: - bne t1, t2, 1b - mtc0 t1, MIPS_COP_0_TLB_INDEX # Set the index register - - mtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBFlushPID) -#endif - -/*-------------------------------------------------------------------------- - * - * MachTLBFlushAddr -- - * - * Flush any TLB entries for the given address and TLB PID. - * - * MachTLBFlushAddr(highreg) - * unsigned highreg; - * - * Results: - * None. - * - * Side effects: - * The process's page is flushed from the TLB. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBFlushAddr) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - nop - - mtc0 a0, MIPS_COP_0_TLB_HI # look for addr & PID - nop - tlbp # Probe for the entry. - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got - li t1, MACH_CACHED_MEMORY_ADDR # Load invalid entry. - bltz v0, 1f # index < 0 => !found - mtc0 t1, MIPS_COP_0_TLB_HI # Mark entry high as invalid - mtc0 zero, MIPS_COP_0_TLB_LOW # Zero out low entry. - nop - tlbwi -1: - mtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBFlushAddr) - -/*-------------------------------------------------------------------------- - * - * MachTLBUpdate -- - * - * Update the TLB if highreg is found; otherwise, enter the data. - * - * MachTLBUpdate(highreg, lowreg) - * unsigned highreg, lowreg; - * - * Results: - * None. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBUpdate) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Save current PID - nop # 2 cycles before intr disabled - mtc0 a0, MIPS_COP_0_TLB_HI # init high reg. - nop - tlbp # Probe for the entry. - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got - mtc0 a1, MIPS_COP_0_TLB_LOW # init low reg. - bltz v0, 1f # index < 0 => !found - sra v0, v0, VMMACH_TLB_INDEX_SHIFT # convert index to regular num - b 2f - tlbwi # update slot found -1: - mtc0 a0, MIPS_COP_0_TLB_HI # init high reg. - nop - tlbwr # enter into a random slot -2: - mtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBUpdate) - -/*-------------------------------------------------------------------------- - * - * MachTLBFind -- - * - * Search the TLB for the given entry. - * - * MachTLBFind(hi) - * unsigned hi; - * - * Results: - * Returns a value >= 0 if the entry was found (the index). - * Returns a value < 0 if the entry was not found. - * - * Side effects: - * tlbhi and tlblo will contain the TLB entry found. - * - *-------------------------------------------------------------------------- - */ - .comm tlbhi, 4 - .comm tlblo, 4 -LEAF(MachTLBFind) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - nop - mtc0 a0, MIPS_COP_0_TLB_HI # Set up entry high. - nop - tlbp # Probe for the entry. - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got - nop - bltz v0, 1f # not found - nop - tlbr # read TLB - mfc0 t1, MIPS_COP_0_TLB_HI # See what we got - mfc0 t2, MIPS_COP_0_TLB_LOW # See what we got - sw t1, tlbhi - sw t2, tlblo - srl v0, v0, VMMACH_TLB_INDEX_SHIFT # convert index to regular num -1: - mtc0 t0, MIPS_COP_0_TLB_HI # Restore current PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBFind) - -/*-------------------------------------------------------------------------- - * - * MachTLBRead -- - * - * Read the TLB entry. - * - * MachTLBRead(entry) - * unsigned entry; - * - * Results: - * None. - * - * Side effects: - * tlbhi and tlblo will contain the TLB entry found. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBRead) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - - sll a0, a0, VMMACH_TLB_INDEX_SHIFT - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register - nop - tlbr # Read from the TLB - mfc0 t3, MIPS_COP_0_TLB_HI # fetch the hi entry - mfc0 t4, MIPS_COP_0_TLB_LOW # fetch the low entry - sw t3, tlbhi - sw t4, tlblo - - mtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBRead) - -/*-------------------------------------------------------------------------- - * - * MachTLBGetPID -- - * - * MachTLBGetPID() - * - * Results: - * Returns the current TLB pid reg. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBGetPID) - mfc0 v0, MIPS_COP_0_TLB_HI # get PID - nop - and v0, v0, VMMACH_TLB_PID # mask off PID - j ra - srl v0, v0, VMMACH_TLB_PID_SHIFT # put PID in right spot -END(MachTLBGetPID) - - -/*---------------------------------------------------------------------------- - * - * R3000 cache sizing and flushing code. - * - *---------------------------------------------------------------------------- - */ - - -/*---------------------------------------------------------------------------- - * - * MachConfigCache -- - * - * Size the caches. - * NOTE: should only be called from mach_init(). - * - * Results: - * None. - * - * Side effects: - * The size of the data cache is stored into machDataCacheSize and the - * size of instruction cache is stored into machInstCacheSize. - * - *---------------------------------------------------------------------------- - */ -NON_LEAF(MachConfigCache, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - sw ra, STAND_RA_OFFSET(sp) # Save return address. - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts. - la v0, 1f - or v0, MACH_UNCACHED_MEMORY_ADDR # Run uncached. - j v0 - nop -1: -/* - * This works because jal doesn't change pc[31..28] and the - * linker still thinks SizeCache is in the cached region so it computes - * the correct address without complaining. - */ - jal _C_LABEL(SizeCache) # Get the size of the d-cache. - nop - sw v0, _C_LABEL(machDataCacheSize) - nop # Make sure sw out of pipe - nop - nop - nop - li v0, MIPS_SR_SWAP_CACHES # Swap caches - mtc0 v0, MIPS_COP_0_STATUS_REG - nop # Insure caches stable - nop - nop - nop - jal _C_LABEL(SizeCache) # Get the size of the i-cache. - nop - mtc0 zero, MIPS_COP_0_STATUS_REG # Swap back caches and enable. - nop - nop - nop - nop - sw v0, _C_LABEL(machInstCacheSize) - la t0, 1f - j t0 # Back to cached mode - nop -1: - lw ra, STAND_RA_OFFSET(sp) # Restore return addr - addu sp, sp, STAND_FRAME_SIZE # Restore sp. - j ra - nop -END(MachConfigCache) - -/*---------------------------------------------------------------------------- - * - * SizeCache -- - * - * Get the size of the cache. - * - * Results: - * The size of the cache. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -LEAF(SizeCache) - mfc0 t0, MIPS_COP_0_STATUS_REG # Save the current status reg. - nop - or v0, t0, MIPS_SR_ISOL_CACHES # Isolate the caches. - nop # Make sure no stores in pipe - mtc0 v0, MIPS_COP_0_STATUS_REG - nop # Make sure isolated - nop - nop -/* - * Clear cache size boundaries. - */ - li v0, MIPS_MIN_CACHE_SIZE - li v1, MACH_CACHED_MEMORY_ADDR - li t2, MIPS_MAX_CACHE_SIZE -1: - addu t1, v0, v1 # Compute address to clear - sw zero, 0(t1) # Clear cache memory - bne v0, t2, 1b - sll v0, v0, 1 - - li v0, -1 - sw v0, 0(v1) # Store marker in cache - li v0, MIPS_MIN_CACHE_SIZE -2: - addu t1, v0, v1 # Compute address - lw t3, 0(t1) # Look for marker - nop - bne t3, zero, 3f # Found marker. - nop - bne v0, t2, 2b # keep looking - sll v0, v0, 1 # cache size * 2 - - move v0, zero # must be no cache -3: - mtc0 t0, MIPS_COP_0_STATUS_REG - nop # Make sure unisolated - nop - nop - nop - j ra - nop -END(SizeCache) - -/*---------------------------------------------------------------------------- - * - * MachFlushCache -- - * - * Flush the caches. - * - * Results: - * None. - * - * Side effects: - * The contents of the caches is flushed. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachFlushCache) - lw t1, _C_LABEL(machInstCacheSize) # Must load before isolating - lw t2, _C_LABEL(machDataCacheSize) # Must load before isolating - mfc0 t3, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts. - la v0, 1f - or v0, MACH_UNCACHED_MEMORY_ADDR # Run uncached. - j v0 - nop -/* - * Flush the instruction cache. - */ -1: - li v0, MIPS_SR_ISOL_CACHES | MIPS_SR_SWAP_CACHES - mtc0 v0, MIPS_COP_0_STATUS_REG # Isolate and swap caches. - li t0, MACH_UNCACHED_MEMORY_ADDR - subu t0, t0, t1 - li t1, MACH_UNCACHED_MEMORY_ADDR - la v0, 1f # Run cached - j v0 - nop -1: - addu t0, t0, 4 - bne t0, t1, 1b - sb zero, -4(t0) - - la v0, 1f - or v0, MACH_UNCACHED_MEMORY_ADDR - j v0 # Run uncached - nop -/* - * Flush the data cache. - */ -1: - li v0, MIPS_SR_ISOL_CACHES - mtc0 v0, MIPS_COP_0_STATUS_REG # Isolate and swap back caches - li t0, MACH_UNCACHED_MEMORY_ADDR - subu t0, t0, t2 - la v0, 1f - j v0 # Back to cached mode - nop -1: - addu t0, t0, 4 - bne t0, t1, 1b - sb zero, -4(t0) - - nop # Insure isolated stores - nop # out of pipe. - nop - nop - mtc0 t3, MIPS_COP_0_STATUS_REG # Restore status reg. - nop # Insure cache unisolated. - nop - nop - nop - j ra - nop -END(MachFlushCache) - -/*---------------------------------------------------------------------------- - * - * MachFlushICache -- - * - * void MachFlushICache(addr, len) - * vm_offset_t addr, len; - * - * Flush instruction cache for range of addr to addr + len - 1. - * The address can be any valid address so long as no TLB misses occur. - * - * Results: - * None. - * - * Side effects: - * The contents of the cache is flushed. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachFlushICache) - mfc0 t0, MIPS_COP_0_STATUS_REG # Save SR - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts. - - la v1, 1f - or v1, MACH_UNCACHED_MEMORY_ADDR # Run uncached. - j v1 - nop -1: - bc0f 1b # make sure stores are complete - li v1, MIPS_SR_ISOL_CACHES | MIPS_SR_SWAP_CACHES - mtc0 v1, MIPS_COP_0_STATUS_REG - nop - addu a1, a1, a0 # compute ending address -1: - addu a0, a0, 4 - bne a0, a1, 1b - sb zero, -4(a0) - - mtc0 t0, MIPS_COP_0_STATUS_REG # enable interrupts - j ra # return and run cached - nop -END(MachFlushICache) - -/*---------------------------------------------------------------------------- - * - * MachFlushDCache -- - * - * void MachFlushDCache(addr, len) - * vm_offset_t addr, len; - * - * Flush data cache for range of addr to addr + len - 1. - * The address can be any valid address so long as no TLB misses occur. - * (Be sure to use cached K0SEG kernel addresses) - * Results: - * None. - * - * Side effects: - * The contents of the cache is flushed. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachFlushDCache) - mfc0 t0, MIPS_COP_0_STATUS_REG # Save SR - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts. - nop -1: - bc0f 1b # make sure stores are complete -# BUG: should drain write buffer. -# The insn above does not work on some all DEC machines, or all variants -# of the mips architecture. - li v1, MIPS_SR_ISOL_CACHES - mtc0 v1, MIPS_COP_0_STATUS_REG - nop - addu t1, a1, a0 # compute ending address -1: - sb zero, 0(a0) - sb zero, 4(a0) - sb zero, 8(a0) - sb zero, 12(a0) - sb zero, 16(a0) - sb zero, 20(a0) - sb zero, 24(a0) - addu a0, 32 - bltu a0, t1, 1b - sb zero, -4(a0) - - nop # drain pipeline - nop - mtc0 t0, MIPS_COP_0_STATUS_REG # enable interrupts - nop - j ra # return and run cached - nop -END(MachFlushDCache) - -/*---------------------------------------------------------------------------- - * - * XXX END of r3000-specific code XXX - * - *---------------------------------------------------------------------------- - */ -#endif /* XXX XXX -- r3000 support, not yet */ - - - -#if 1 /* R4000 support */ - -/*---------------------------------------------------------------------------- - * - * XXX START of r4000-specific code XXX - * - *---------------------------------------------------------------------------- - */ - - -/*---------------------------------------------------------------------------- - * - * R4000 TLB exception handlers - * - *---------------------------------------------------------------------------- -*/ - - -/*---------------------------------------------------------------------------- - * - * MachTLBMInvalidException -- - * - * Handle a TLB invalid exception from kernel mode in kernel space. - * The BaddVAddr, Context, and EntryHi registers contain the failed - * virtual address. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NLEAF(MachTLBInvalidException) - .set noat - dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address - li k1, VM_MIN_KERNEL_ADDRESS # compute index - subu k0, k0, k1 - lw k1, Sysmapsize # index within range? - srl k0, k0, PGSHIFT - sltu k1, k0, k1 - beq k1, zero, sys_stk_chk # No. check for valid stack - lw k1, Sysmap - - sll k0, k0, 2 # compute offset from index - tlbp # Probe the invalid entry - addu k1, k1, k0 - and k0, k0, 4 # check even/odd page - bne k0, zero, KernTLBIOdd - nop - - mfc0 k0, MIPS_COP_0_TLB_INDEX - nop - bltz k0, sys_stk_chk - sltiu k0, k0, 8 - - bne k0, zero, sys_stk_chk - lw k0, 0(k1) # get PTE entry - - dsll k0, k0, 34 # get rid of "wired" bit - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO0 # load PTE entry - and k0, k0, PG_V # check for valid entry - beq k0, zero, MachKernGenException # PTE invalid - lw k0, 4(k1) # get odd PTE entry - dsll k0, k0, 34 - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO1 # load PTE entry - nop - tlbwi # write TLB - nop - nop - nop - nop - nop - eret - -KernTLBIOdd: - mfc0 k0, MIPS_COP_0_TLB_INDEX - nop - bltz k0, sys_stk_chk - sltiu k0, k0, 8 - - bne k0, zero, sys_stk_chk - lw k0, 0(k1) # get PTE entry - - dsll k0, k0, 34 # get rid of wired bit - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO1 # save PTE entry - and k0, k0, PG_V # check for valid entry - beq k0, zero, MachKernGenException # PTE invalid - lw k0, -4(k1) # get even PTE entry - dsll k0, k0, 34 - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO0 # save PTE entry - nop - tlbwi # update TLB - nop - nop - nop - nop - nop - eret -END(MachTLBInvalidException) - -/*---------------------------------------------------------------------------- - * - * MachTLBMissException -- - * - * Handle a TLB miss exception from kernel mode in kernel space. - * The BaddVAddr, Context, and EntryHi registers contain the failed - * virtual address. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NLEAF(MachTLBMissException) - .set noat - dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address - li k1, VM_MIN_KERNEL_ADDRESS # compute index - subu k0, k0, k1 - lw k1, Sysmapsize # index within range? - srl k0, k0, PGSHIFT - sltu k1, k0, k1 - beq k1, zero, sys_stk_chk # No. check for valid stack - lw k1, Sysmap - srl k0, k0, 1 - sll k0, k0, 3 # compute offset from index - addu k1, k1, k0 - lw k0, 0(k1) # get PTE entry - lw k1, 4(k1) # get odd PTE entry - dsll k0, k0, 34 # get rid of "wired" bit - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO0 # load PTE entry - dsll k1, k1, 34 - dsrl k1, k1, 34 - dmtc0 k1, MIPS_COP_0_TLB_LO1 # load PTE entry - nop - tlbwr # write TLB - nop - nop - nop - nop - nop - eret - -sys_stk_chk: - subu k0, sp, UADDR + 0x200 # check to see if we have a - sltiu k0, UPAGES*NBPG - 0x200 # valid kernel stack - bne k0, zero, MachKernGenException # Go panic - nop - - la a0, start - START_FRAME - 8 # set sp to a valid place - sw sp, 24(a0) - move sp, a0 - la a0, 1f - mfc0 a2, MIPS_COP_0_STATUS_REG - mfc0 a3, MIPS_COP_0_CAUSE_REG - dmfc0 a1, MIPS_COP_0_EXC_PC - sw a2, 16(sp) - sw a3, 20(sp) - move a2, ra - jal printf - dmfc0 a3, MIPS_COP_0_BAD_VADDR - .data -1: - .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n" - .text - - la sp, start - START_FRAME # set sp to a valid place - PANIC("kernel stack overflow") - .set at -END(MachTLBMissException) - - -/*-------------------------------------------------------------------------- - * - * MachTLBWriteIndexed -- - * - * Write the given entry into the TLB at the given index. - * - * MachTLBWriteIndexed(index, tlb) - * unsigned index; - * tlb *tlb; - * - * Results: - * None. - * - * Side effects: - * TLB entry set. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBWriteIndexed) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - nop - lw a2, 8(a1) - lw a3, 12(a1) - dmfc0 t0, MIPS_COP_0_TLB_HI # Save the current PID. - - dmtc0 a2, MIPS_COP_0_TLB_LO0 # Set up entry low0. - dmtc0 a3, MIPS_COP_0_TLB_LO1 # Set up entry low1. - lw a2, 0(a1) - lw a3, 4(a1) - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index. - dmtc0 a2, MIPS_COP_0_TLB_PG_MASK # Set up entry mask. - dmtc0 a3, MIPS_COP_0_TLB_HI # Set up entry high. - nop - tlbwi # Write the TLB - nop - nop - nop # Delay for effect - nop - - dmtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID. - nop - dmtc0 zero, MIPS_COP_0_TLB_PG_MASK # Default mask value. - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBWriteIndexed) - -/*-------------------------------------------------------------------------- - * - * MachSetPID -- - * - * Write the given pid into the TLB pid reg. - * - * MachSetPID(pid) - * int pid; - * - * Results: - * None. - * - * Side effects: - * PID set in the entry hi register. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachSetPID) - dmtc0 a0, MIPS_COP_0_TLB_HI # Write the hi reg value - j ra - nop -END(MachSetPID) - -/*-------------------------------------------------------------------------- - * - * MachSetWIRED -- - * - * Write the given value into the TLB wired reg. - * - * MachSetPID(wired) - * int wired; - * - * Results: - * None. - * - * Side effects: - * WIRED set in the wired register. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachSetWIRED) - mtc0 a0, MIPS_COP_0_TLB_WIRED - j ra - nop -END(MachSetWIRED) - -/*-------------------------------------------------------------------------- - * - * MachGetWIRED -- - * - * Get the value from the TLB wired reg. - * - * MachGetWIRED(void) - * - * Results: - * Value of wired reg. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachGetWIRED) - mfc0 v0, MIPS_COP_0_TLB_WIRED - j ra - nop -END(MachGetWIRED) - -/*-------------------------------------------------------------------------- - * - * MachTLBFlush -- - * - * Flush the "random" entries from the TLB. - * Uses "wired" register to determine what register to start with. - * - * MachTLBFlush() - * - * Results: - * None. - * - * Side effects: - * The TLB is flushed. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBFlush) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t1, MIPS_COP_0_TLB_WIRED - li t2, VMMACH_NUM_TLB_ENTRIES - li v0, MACH_CACHED_MEMORY_ADDR # invalid address - dmfc0 t0, MIPS_COP_0_TLB_HI # Save the PID - - dmtc0 v0, MIPS_COP_0_TLB_HI # Mark entry high as invalid - dmtc0 zero, MIPS_COP_0_TLB_LO0 # Zero out low entry0. - dmtc0 zero, MIPS_COP_0_TLB_LO1 # Zero out low entry1. - mtc0 zero, MIPS_COP_0_TLB_PG_MASK # Zero out mask entry. -/* - * Align the starting value (t1) and the upper bound (t2). - */ -1: - mtc0 t1, MIPS_COP_0_TLB_INDEX # Set the index register. - addu t1, t1, 1 # Increment index. - tlbwi # Write the TLB entry. - nop - nop - bne t1, t2, 1b - nop - - dmtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBFlush) - - -/*-------------------------------------------------------------------------- - * - * MachTLBFlushAddr -- - * - * Flush any TLB entries for the given address and TLB PID. - * - * MachTLBFlushAddr(TLBhi) - * unsigned TLBhi; - * - * Results: - * None. - * - * Side effects: - * The process's page is flushed from the TLB. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBFlushAddr) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - nop - li v0, (PG_HVPN | PG_ASID) - and a0, a0, v0 # Make shure valid hi value. - dmfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - dmtc0 a0, MIPS_COP_0_TLB_HI # look for addr & PID - nop - nop - nop - tlbp # Probe for the entry. - nop - nop # Delay for effect - nop - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got - li t1, MACH_CACHED_MEMORY_ADDR # Load invalid entry. - bltz v0, 1f # index < 0 => !found - nop - dmtc0 t1, MIPS_COP_0_TLB_HI # Mark entry high as invalid - - dmtc0 zero, MIPS_COP_0_TLB_LO0 # Zero out low entry. - dmtc0 zero, MIPS_COP_0_TLB_LO1 # Zero out low entry. - nop - tlbwi - nop - nop - nop - nop -1: - dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBFlushAddr) - -/*-------------------------------------------------------------------------- - * - * MachTLBUpdate -- - * - * Update the TLB if highreg is found; otherwise, enter the data. - * - * MachTLBUpdate(virpageadr, lowregx) - * unsigned virpageadr, lowregx; - * - * Results: - * < 0 if loaded >= 0 if updated. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBUpdate) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - and t1, a0, 0x1000 # t1 = Even/Odd flag - li v0, (PG_HVPN | PG_ASID) - and a0, a0, v0 - dmfc0 t0, MIPS_COP_0_TLB_HI # Save current PID - dmtc0 a0, MIPS_COP_0_TLB_HI # Init high reg - and a2, a1, PG_G # Copy global bit - nop - nop - tlbp # Probe for the entry. - dsll a1, a1, 34 - dsrl a1, a1, 34 - bne t1, zero, 2f # Decide even odd - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got -# EVEN - nop - bltz v0, 1f # index < 0 => !found - nop - - tlbr # update, read entry first - nop - nop - nop - dmtc0 a1, MIPS_COP_0_TLB_LO0 # init low reg0. - nop - tlbwi # update slot found - b 4f - nop -1: - mtc0 zero, MIPS_COP_0_TLB_PG_MASK # init mask. - dmtc0 a0, MIPS_COP_0_TLB_HI # init high reg. - dmtc0 a1, MIPS_COP_0_TLB_LO0 # init low reg0. - dmtc0 a2, MIPS_COP_0_TLB_LO1 # init low reg1. - nop - tlbwr # enter into a random slot - b 4f - nop -# ODD -2: - nop - bltz v0, 3f # index < 0 => !found - nop - - tlbr # read the entry first - nop - nop - nop - dmtc0 a1, MIPS_COP_0_TLB_LO1 # init low reg1. - nop - tlbwi # update slot found - b 4f - nop -3: - mtc0 zero, MIPS_COP_0_TLB_PG_MASK # init mask. - dmtc0 a0, MIPS_COP_0_TLB_HI # init high reg. - dmtc0 a2, MIPS_COP_0_TLB_LO0 # init low reg0. - dmtc0 a1, MIPS_COP_0_TLB_LO1 # init low reg1. - nop - tlbwr # enter into a random slot - -4: # Make shure pipeline - nop # advances before we - nop # uses the tlb. - nop - nop - dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(MachTLBUpdate) - -/*-------------------------------------------------------------------------- - * - * MachTLBRead -- - * - * Read the TLB entry. - * - * MachTLBRead(entry, tlb) - * unsigned entry; - * struct tlb *tlb; - * - * Results: - * None. - * - * Side effects: - * tlb will contain the TLB entry found. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBRead) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - nop - nop - nop - dmfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register - nop - tlbr # Read from the TLB - nop - nop - nop - mfc0 t2, MIPS_COP_0_TLB_PG_MASK # fetch the hi entry - dmfc0 t3, MIPS_COP_0_TLB_HI # fetch the hi entry - dmfc0 t4, MIPS_COP_0_TLB_LO0 # See what we got - dmfc0 t5, MIPS_COP_0_TLB_LO1 # See what we got - dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID - nop - nop - nop # wait for PID active - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register - sw t2, 0(a1) - sw t3, 4(a1) - sw t4, 8(a1) - j ra - sw t5, 12(a1) -END(MachTLBRead) - -/*-------------------------------------------------------------------------- - * - * MachTLBGetPID -- - * - * MachTLBGetPID() - * - * Results: - * Returns the current TLB pid reg. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(MachTLBGetPID) - dmfc0 v0, MIPS_COP_0_TLB_HI # get PID - j ra - and v0, v0, VMMACH_TLB_PID # mask off PID -END(MachTLBGetPID) - - - -/*---------------------------------------------------------------------------- - * - * R4000 cache sizing and flushing code. - * - *---------------------------------------------------------------------------- - */ - - -/*---------------------------------------------------------------------------- - * - * MachConfigCache -- - * - * Size the caches. - * NOTE: should only be called from mach_init(). - * - * Results: - * None. - * - * Side effects: - * The size of the data cache is stored into machPrimaryDataCacheSize. - * The size of instruction cache is stored into machPrimaryInstCacheSize. - * Alignment mask for cache aliasing test is stored in machCacheAliasMask. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachConfigCache) - mfc0 v0, MIPS_COP_0_CONFIG # Get configuration register - nop - srl t1, v0, 9 # Get I cache size. - and t1, 3 - li t2, 4096 - sllv t2, t2, t1 - sw t2, machPrimaryDataCacheSize - addiu t2, -1 - and t2, ~(NBPG - 1) - sw t2, machCacheAliasMask - - and t2, v0, 0x20 - srl t2, t2, 1 - addu t2, t2, 16 - sw t2, machPrimaryDataCacheLSize - - srl t1, v0, 6 # Get I cache size. - and t1, 3 - li t2, 4096 - sllv t2, t2, t1 - sw t2, machPrimaryInstCacheSize - - and t2, v0, 0x10 - addu t2, t2, 16 - sw t2, machPrimaryInstCacheLSize - j ra - nop -END(MachConfigCache) - -/*---------------------------------------------------------------------------- - * - * MachFlushCache -- - * - * Flush the caches. Assumes a line size of 16 bytes for speed. - * - * Results: - * None. - * - * Side effects: - * The contents of the caches is flushed. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachFlushCache) - lw t1, machPrimaryInstCacheSize - lw t2, machPrimaryDataCacheSize - # lw t3, machPrimaryInstCacheLSize - # lw t4, machPrimaryDataCacheLSize -/* - * Flush the instruction cache. - */ - li t0, MACH_CACHED_MEMORY_ADDR - addu t1, t0, t1 # End address - subu t1, t1, 128 -1: - cache 0, 0(t0) - cache 0, 16(t0) - cache 0, 32(t0) - cache 0, 48(t0) - cache 0, 64(t0) - cache 0, 80(t0) - cache 0, 96(t0) - cache 0, 112(t0) - bne t0, t1, 1b - addu t0, t0, 128 - -/* - * Flush the data cache. - */ - li t0, MACH_CACHED_MEMORY_ADDR - addu t1, t0, t2 # End address - subu t1, t1, 128 -1: - cache 1, 0(t0) - cache 1, 16(t0) - cache 1, 32(t0) - cache 1, 48(t0) - cache 1, 64(t0) - cache 1, 80(t0) - cache 1, 96(t0) - cache 1, 112(t0) - bne t0, t1, 1b - addu t0, t0, 128 - - j ra - nop -END(MachFlushCache) - -/*---------------------------------------------------------------------------- - * - * MachFlushICache -- - * - * void MachFlushICache(addr, len) - * vm_offset_t addr, len; - * - * Flush instruction cache for range of addr to addr + len - 1. - * The address can be any valid address so long as no TLB misses occur. - * Assumes a cache line size of 16 bytes for speed. - * - * Results: - * None. - * - * Side effects: - * The contents of the cache is flushed. - * Must not touch v0. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachFlushICache) - addu a1, 127 # Align - srl a1, a1, 7 # Number of unrolled loops -1: - cache 0, 0(a0) - cache 0, 16(a0) - cache 0, 32(a0) - cache 0, 48(a0) - cache 0, 64(a0) - cache 0, 80(a0) - cache 0, 96(a0) - cache 0, 112(a0) - addu a1, -1 - bne a1, zero, 1b - addu a0, 128 - - j ra - nop -END(MachFlushICache) - -/*---------------------------------------------------------------------------- - * - * MachFlushDCache -- - * - * void MachFlushDCache(addr, len) - * vm_offset_t addr, len; - * - * Flush data cache for index range of addr to addr + len - 1. - * The address is reduced to a kseg0 index. - * - * Results: - * None. - * - * Side effects: - * The contents of the cache is written back to primary memory. - * The cache line is invalidated. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachFlushDCache) - lw a2, machPrimaryDataCacheSize - addiu a2, -1 - and a0, a0, a2 - addu a1, 127 # Align - li a2, 0x80000000 - addu a0, a0, a2 - addu a1, a1, a0 - and a0, a0, -128 - subu a1, a1, a0 - srl a1, a1, 7 # Compute number of cache lines -1: - cache 1, 0(a0) - cache 1, 16(a0) - cache 1, 32(a0) - cache 1, 48(a0) - cache 1, 64(a0) - cache 1, 80(a0) - cache 1, 96(a0) - cache 1, 112(a0) - addu a1, -1 - bne a1, zero, 1b - addu a0, 128 - - j ra - nop -END(MachFlushDCache) - -/*---------------------------------------------------------------------------- - * - * MachHitFlushDCache -- - * - * void MachHitFlushDCache(addr, len) - * vm_offset_t addr, len; - * - * Flush data cache for range of addr to addr + len - 1. - * The address can be any valid viritual address as long - * as no TLB invalid traps occur. Only lines with matching - * addr is flushed. - * - * Results: - * None. - * - * Side effects: - * The contents of the cache is written back to primary memory. - * The cache line is invalidated. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachHitFlushDCache) - beq a1, zero, 2f - addu a1, 127 # Align - addu a1, a1, a0 - and a0, a0, -128 - subu a1, a1, a0 - srl a1, a1, 7 # Compute number of cache lines -1: - cache 0x15, 0(a0) - cache 0x15, 16(a0) - cache 0x15, 32(a0) - cache 0x15, 48(a0) - cache 0x15, 64(a0) - cache 0x15, 80(a0) - cache 0x15, 96(a0) - cache 0x15, 112(a0) - addu a1, -1 - bne a1, zero, 1b - addu a0, 128 - -2: - j ra - nop -END(MachHitFlushDCache) -/*---------------------------------------------------------------------------- - * - * MachInvalidateDCache -- - * - * void MachFlushDCache(addr, len) - * vm_offset_t addr, len; - * - * Flush data cache for range of addr to addr + len - 1. - * The address can be any valid address as long as no TLB misses occur. - * (Be sure to use cached K0SEG kernel addresses or mapped addresses) - * Results: - * None. - * - * Side effects: - * The cache line is invalidated. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachInvalidateDCache) - addu a1, a1, a0 # compute ending address -1: - addu a0, a0, 4 - bne a0, a1, 1b - cache 0x11,-4(a0) - - j ra - nop -END(MachInvalidateDCache) - -/*---------------------------------------------------------------------------- - * - * XXX END of r4000-specific code XXX - * - *---------------------------------------------------------------------------- - */ - -/*#endif*/ /* r4000 support */ - - - -/*---------------------------------------------------------------------------- - * - * MachSwitchFPState -- - * - * Return the current value of the cause register. - * - * MachGetCauseReg(void) - * - * Results: - * current value of Cause register.None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachGetCauseReg) - mfc0 v0, MIPS_COP_0_CAUSE_REG - j ra - nop -END(MachGetCauseReg) - - -/*---------------------------------------------------------------------------- - * - * MachSwitchFPState -- - * - * Save the current state into 'from' and restore it from 'to'. - * - * MachSwitchFPState(from, to) - * struct proc *from; - * struct user *to; - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachSwitchFPState) - mfc0 t1, MIPS_COP_0_STATUS_REG # Save old SR - li t0, MIPS_SR_COP_1_BIT # enable the coprocessor - mtc0 t0, MIPS_COP_0_STATUS_REG - - beq a0, zero, 1f # skip save if NULL pointer - nop -/* - * First read out the status register to make sure that all FP operations - * have completed. - */ - lw a0, P_ADDR(a0) # get pointer to pcb for proc - cfc1 t0, MIPS_FPU_CSR # stall til FP done - cfc1 t0, MIPS_FPU_CSR # now get status - li t3, ~MIPS_SR_COP_1_BIT - lw t2, U_PCB_REGS+(PS * 4)(a0) # get CPU status register - sw t0, U_PCB_FPREGS+(32 * 4)(a0) # save FP status - and t2, t2, t3 # clear COP_1 enable bit - sw t2, U_PCB_REGS+(PS * 4)(a0) # save new status register -/* - * Save the floating point registers. - */ - swc1 $f0, U_PCB_FPREGS+(0 * 4)(a0) - swc1 $f1, U_PCB_FPREGS+(1 * 4)(a0) - swc1 $f2, U_PCB_FPREGS+(2 * 4)(a0) - swc1 $f3, U_PCB_FPREGS+(3 * 4)(a0) - swc1 $f4, U_PCB_FPREGS+(4 * 4)(a0) - swc1 $f5, U_PCB_FPREGS+(5 * 4)(a0) - swc1 $f6, U_PCB_FPREGS+(6 * 4)(a0) - swc1 $f7, U_PCB_FPREGS+(7 * 4)(a0) - swc1 $f8, U_PCB_FPREGS+(8 * 4)(a0) - swc1 $f9, U_PCB_FPREGS+(9 * 4)(a0) - swc1 $f10, U_PCB_FPREGS+(10 * 4)(a0) - swc1 $f11, U_PCB_FPREGS+(11 * 4)(a0) - swc1 $f12, U_PCB_FPREGS+(12 * 4)(a0) - swc1 $f13, U_PCB_FPREGS+(13 * 4)(a0) - swc1 $f14, U_PCB_FPREGS+(14 * 4)(a0) - swc1 $f15, U_PCB_FPREGS+(15 * 4)(a0) - swc1 $f16, U_PCB_FPREGS+(16 * 4)(a0) - swc1 $f17, U_PCB_FPREGS+(17 * 4)(a0) - swc1 $f18, U_PCB_FPREGS+(18 * 4)(a0) - swc1 $f19, U_PCB_FPREGS+(19 * 4)(a0) - swc1 $f20, U_PCB_FPREGS+(20 * 4)(a0) - swc1 $f21, U_PCB_FPREGS+(21 * 4)(a0) - swc1 $f22, U_PCB_FPREGS+(22 * 4)(a0) - swc1 $f23, U_PCB_FPREGS+(23 * 4)(a0) - swc1 $f24, U_PCB_FPREGS+(24 * 4)(a0) - swc1 $f25, U_PCB_FPREGS+(25 * 4)(a0) - swc1 $f26, U_PCB_FPREGS+(26 * 4)(a0) - swc1 $f27, U_PCB_FPREGS+(27 * 4)(a0) - swc1 $f28, U_PCB_FPREGS+(28 * 4)(a0) - swc1 $f29, U_PCB_FPREGS+(29 * 4)(a0) - swc1 $f30, U_PCB_FPREGS+(30 * 4)(a0) - swc1 $f31, U_PCB_FPREGS+(31 * 4)(a0) - -1: -/* - * Restore the floating point registers. - */ - lw t0, U_PCB_FPREGS+(32 * 4)(a1) # get status register - lwc1 $f0, U_PCB_FPREGS+(0 * 4)(a1) - lwc1 $f1, U_PCB_FPREGS+(1 * 4)(a1) - lwc1 $f2, U_PCB_FPREGS+(2 * 4)(a1) - lwc1 $f3, U_PCB_FPREGS+(3 * 4)(a1) - lwc1 $f4, U_PCB_FPREGS+(4 * 4)(a1) - lwc1 $f5, U_PCB_FPREGS+(5 * 4)(a1) - lwc1 $f6, U_PCB_FPREGS+(6 * 4)(a1) - lwc1 $f7, U_PCB_FPREGS+(7 * 4)(a1) - lwc1 $f8, U_PCB_FPREGS+(8 * 4)(a1) - lwc1 $f9, U_PCB_FPREGS+(9 * 4)(a1) - lwc1 $f10, U_PCB_FPREGS+(10 * 4)(a1) - lwc1 $f11, U_PCB_FPREGS+(11 * 4)(a1) - lwc1 $f12, U_PCB_FPREGS+(12 * 4)(a1) - lwc1 $f13, U_PCB_FPREGS+(13 * 4)(a1) - lwc1 $f14, U_PCB_FPREGS+(14 * 4)(a1) - lwc1 $f15, U_PCB_FPREGS+(15 * 4)(a1) - lwc1 $f16, U_PCB_FPREGS+(16 * 4)(a1) - lwc1 $f17, U_PCB_FPREGS+(17 * 4)(a1) - lwc1 $f18, U_PCB_FPREGS+(18 * 4)(a1) - lwc1 $f19, U_PCB_FPREGS+(19 * 4)(a1) - lwc1 $f20, U_PCB_FPREGS+(20 * 4)(a1) - lwc1 $f21, U_PCB_FPREGS+(21 * 4)(a1) - lwc1 $f22, U_PCB_FPREGS+(22 * 4)(a1) - lwc1 $f23, U_PCB_FPREGS+(23 * 4)(a1) - lwc1 $f24, U_PCB_FPREGS+(24 * 4)(a1) - lwc1 $f25, U_PCB_FPREGS+(25 * 4)(a1) - lwc1 $f26, U_PCB_FPREGS+(26 * 4)(a1) - lwc1 $f27, U_PCB_FPREGS+(27 * 4)(a1) - lwc1 $f28, U_PCB_FPREGS+(28 * 4)(a1) - lwc1 $f29, U_PCB_FPREGS+(29 * 4)(a1) - lwc1 $f30, U_PCB_FPREGS+(30 * 4)(a1) - lwc1 $f31, U_PCB_FPREGS+(31 * 4)(a1) - - and t0, t0, ~MIPS_FPU_EXCEPTION_BITS - ctc1 t0, MIPS_FPU_CSR - nop - - mtc0 t1, MIPS_COP_0_STATUS_REG # Restore the status register. - j ra - nop -END(MachSwitchFPState) - -/*---------------------------------------------------------------------------- - * - * MachSaveCurFPState -- - * - * Save the current floating point coprocessor state. - * - * MachSaveCurFPState(p) - * struct proc *p; - * - * Results: - * None. - * - * Side effects: - * machFPCurProcPtr is cleared. - * - *---------------------------------------------------------------------------- - */ -LEAF(MachSaveCurFPState) - lw a0, P_ADDR(a0) # get pointer to pcb for proc - mfc0 t1, MIPS_COP_0_STATUS_REG # Disable interrupts and - li t0, MIPS_SR_COP_1_BIT # enable the coprocessor - mtc0 t0, MIPS_COP_0_STATUS_REG - sw zero, _C_LABEL(machFPCurProcPtr) # indicate state has been saved -/* - * First read out the status register to make sure that all FP operations - * have completed. - */ - lw t2, U_PCB_REGS+(PS * 4)(a0) # get CPU status register - li t3, ~MIPS_SR_COP_1_BIT - and t2, t2, t3 # clear COP_1 enable bit - cfc1 t0, MIPS_FPU_CSR # stall til FP done - cfc1 t0, MIPS_FPU_CSR # now get status - sw t2, U_PCB_REGS+(PS * 4)(a0) # save new status register - sw t0, U_PCB_FPREGS+(32 * 4)(a0) # save FP status -/* - * Save the floating point registers. - */ - swc1 $f0, U_PCB_FPREGS+(0 * 4)(a0) - swc1 $f1, U_PCB_FPREGS+(1 * 4)(a0) - swc1 $f2, U_PCB_FPREGS+(2 * 4)(a0) - swc1 $f3, U_PCB_FPREGS+(3 * 4)(a0) - swc1 $f4, U_PCB_FPREGS+(4 * 4)(a0) - swc1 $f5, U_PCB_FPREGS+(5 * 4)(a0) - swc1 $f6, U_PCB_FPREGS+(6 * 4)(a0) - swc1 $f7, U_PCB_FPREGS+(7 * 4)(a0) - swc1 $f8, U_PCB_FPREGS+(8 * 4)(a0) - swc1 $f9, U_PCB_FPREGS+(9 * 4)(a0) - swc1 $f10, U_PCB_FPREGS+(10 * 4)(a0) - swc1 $f11, U_PCB_FPREGS+(11 * 4)(a0) - swc1 $f12, U_PCB_FPREGS+(12 * 4)(a0) - swc1 $f13, U_PCB_FPREGS+(13 * 4)(a0) - swc1 $f14, U_PCB_FPREGS+(14 * 4)(a0) - swc1 $f15, U_PCB_FPREGS+(15 * 4)(a0) - swc1 $f16, U_PCB_FPREGS+(16 * 4)(a0) - swc1 $f17, U_PCB_FPREGS+(17 * 4)(a0) - swc1 $f18, U_PCB_FPREGS+(18 * 4)(a0) - swc1 $f19, U_PCB_FPREGS+(19 * 4)(a0) - swc1 $f20, U_PCB_FPREGS+(20 * 4)(a0) - swc1 $f21, U_PCB_FPREGS+(21 * 4)(a0) - swc1 $f22, U_PCB_FPREGS+(22 * 4)(a0) - swc1 $f23, U_PCB_FPREGS+(23 * 4)(a0) - swc1 $f24, U_PCB_FPREGS+(24 * 4)(a0) - swc1 $f25, U_PCB_FPREGS+(25 * 4)(a0) - swc1 $f26, U_PCB_FPREGS+(26 * 4)(a0) - swc1 $f27, U_PCB_FPREGS+(27 * 4)(a0) - swc1 $f28, U_PCB_FPREGS+(28 * 4)(a0) - swc1 $f29, U_PCB_FPREGS+(29 * 4)(a0) - swc1 $f30, U_PCB_FPREGS+(30 * 4)(a0) - swc1 $f31, U_PCB_FPREGS+(31 * 4)(a0) - - mtc0 t1, MIPS_COP_0_STATUS_REG # Restore the status register. - j ra - nop -END(MachSaveCurFPState) - -/*---------------------------------------------------------------------------- - * - * MachFPInterrupt -- - * MachFPTrap -- - * - * Handle a floating point interrupt (r3k) or trap (r4k). - * the handlers are indentical, only the reporting mechanisms differ. - * - * MachFPInterrupt(statusReg, causeReg, pc) - * unsigned statusReg; - * unsigned causeReg; - * unsigned pc; - * - * MachFPTrap(statusReg, causeReg, pc) - * unsigned statusReg; - * unsigned causeReg; - * unsigned pc; - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NON_LEAF(MachFPTrap, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - mfc0 t0, MIPS_COP_0_STATUS_REG - sw ra, STAND_RA_OFFSET(sp) - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - - or t1, t0, MIPS_SR_COP_1_BIT - mtc0 t1, MIPS_COP_0_STATUS_REG - nop - nop - nop - nop - cfc1 t1, MIPS_FPU_CSR # stall til FP done - cfc1 t1, MIPS_FPU_CSR # now get status - nop - sll t2, t1, (31 - 17) # unimplemented operation? - bgez t2, 3f # no, normal trap - nop -/* - * We got an unimplemented operation trap so - * fetch the instruction, compute the next PC and emulate the instruction. - */ - bgez a1, 1f # Check the branch delay bit. - nop -/* - * The instruction is in the branch delay slot so the branch will have to - * be emulated to get the resulting PC. - */ - sw a2, STAND_FRAME_SIZE + 8(sp) - li a0, UADDR+U_PCB_REGS # first arg is ptr to CPU registers - move a1, a2 # second arg is instruction PC - move a2, t1 # third arg is floating point CSR - jal _C_LABEL(MachEmulateBranch) # compute PC after branch - move a3, zero # fourth arg is FALSE -/* - * Now load the floating-point instruction in the branch delay slot - * to be emulated. - */ - lw a2, STAND_FRAME_SIZE + 8(sp) # restore EXC pc - b 2f - lw a0, 4(a2) # a0 = coproc instruction -/* - * This is not in the branch delay slot so calculate the resulting - * PC (epc + 4) into v0 and continue to MachEmulateFP(). - */ -1: - lw a0, 0(a2) # a0 = coproc instruction - addu v0, a2, 4 # v0 = next pc -2: - sw v0, UADDR+U_PCB_REGS+(PC * 4) # save new pc -/* - * Check to see if the instruction to be emulated is a floating-point - * instruction. - */ - srl a3, a0, MIPS_OPCODE_SHIFT - beq a3, MIPS_OPCODE_C1, 4f # this should never fail - nop -/* - * Send a floating point exception signal to the current process. - */ -3: - lw a0, _C_LABEL(curproc) # get current process - cfc1 a2, MIPS_FPU_CSR # code = FP execptions - ctc1 zero, MIPS_FPU_CSR # Clear exceptions - jal _C_LABEL(trapsignal) - li a1, SIGFPE - b FPReturn - nop - -/* - * Finally, we can call MachEmulateFP() where a0 is the instruction to emulate. - */ -4: - jal _C_LABEL(MachEmulateFP) - nop - -/* - * Turn off the floating point coprocessor and return. - */ -FPReturn: - mfc0 t0, MIPS_COP_0_STATUS_REG - lw ra, STAND_RA_OFFSET(sp) - and t0, t0, ~MIPS_SR_COP_1_BIT - mtc0 t0, MIPS_COP_0_STATUS_REG - j ra - addu sp, sp, STAND_FRAME_SIZE -END(MachFPTrap) - -#ifdef DEBUG -/* - * Read a long and return it. - * Note: addresses can be unaligned! - * - * long -L* mdbpeek(addr) -L* caddt_t addr; -L* { -L* return (*(long *)addr); -L* } - */ -LEAF(mdbpeek) - li v0, MDBERR - sw v0, UADDR+U_PCB_ONFAULT - and v0, a0, 3 # unaligned address? - bne v0, zero, 1f - nop - b 2f - lw v0, (a0) # aligned access -1: - lwr v0, 0(a0) # get next 4 bytes (unaligned) - lwl v0, 3(a0) -2: - j ra # made it w/o errors - sw zero, UADDR+U_PCB_ONFAULT -mdberr: - li v0, 1 # trap sends us here - sw v0, mdbmkfault - j ra - nop -END(mdbpeek) - -/* - * Write a long to 'addr'. - * Note: addresses can be unaligned! - * -L* void -L* mdbpoke(addr, value) -L* caddt_t addr; -L* long value; -L* { -L* *(long *)addr = value; -L* } - */ -LEAF(mdbpoke) - li v0, MDBERR - sw v0, UADDR+U_PCB_ONFAULT - and v0, a0, 3 # unaligned address? - bne v0, zero, 1f - nop - b 2f - sw a1, (a0) # aligned access -1: - swr a1, 0(a0) # store next 4 bytes (unaligned) - swl a1, 3(a0) - and a0, a0, ~3 # align address for cache flush -2: - sw zero, UADDR+U_PCB_ONFAULT - b MachFlushICache # flush instruction cache - li a1, 8 -END(mdbpoke) - -/* - * Save registers and state so we can do a 'mdbreset' (like longjmp) later. - * Always returns zero. - * -L* int mdb_savearea[11]; -L* -L* int -L* mdbsetexit() -L* { -L* mdb_savearea[0] = 0; -L* return (0); -L* } - */ - .comm mdb_savearea, (11 * 4) - -LEAF(mdbsetexit) - la a0, mdb_savearea - sw s0, 0(a0) - sw s1, 4(a0) - sw s2, 8(a0) - sw s3, 12(a0) - sw s4, 16(a0) - sw s5, 20(a0) - sw s6, 24(a0) - sw s7, 28(a0) - sw sp, 32(a0) - sw s8, 36(a0) - sw ra, 40(a0) - j ra - move v0, zero -END(mdbsetexit) - -/* - * Restore registers and state (like longjmp) and return x. - * -L* int -L* mdbreset(x) -L* { -L* return (x); -L* } - */ -LEAF(mdbreset) - la v0, mdb_savearea - lw ra, 40(v0) - lw s0, 0(v0) - lw s1, 4(v0) - lw s2, 8(v0) - lw s3, 12(v0) - lw s4, 16(v0) - lw s5, 20(v0) - lw s6, 24(v0) - lw s7, 28(v0) - lw sp, 32(v0) - lw s8, 36(v0) - j ra - move v0, a0 -END(mdbreset) - -/* - * Trap into the debugger. - * -L* void -L* mdbpanic() -L* { -L* } - */ -LEAF(mdbpanic) - break MIPS_BREAK_SOVER_VAL - j ra - nop -END(mdbpanic) -#endif /* DEBUG */ - -#ifdef DEBUG -LEAF(cpu_getregs) - sw sp, 0(a0) - sw ra, 4(a0) - j ra - sw s8, 8(a0) -END(cpu_getregs) -#endif /* DEBUG */ - -/* - * Interrupt counters for vmstat. - * XXX These aren't used yet. - */ - .data - .globl intrcnt - .globl eintrcnt - .globl intrnames - .globl eintrnames -intrnames: - .asciiz "spur" - .asciiz "hil" - .asciiz "lev2" - .asciiz "lev3" - .asciiz "lev4" - .asciiz "lev5" - .asciiz "dma" - .asciiz "clock" - .asciiz "statclock" - .asciiz "nmi" -eintrnames: - .align 2 -intrcnt: - .word 0,0,0,0,0,0,0,0,0,0 -eintrcnt: diff --git a/sys/arch/arc/arc/mem.c b/sys/arch/arc/arc/mem.c deleted file mode 100644 index c6020f0b6ef6..000000000000 --- a/sys/arch/arc/arc/mem.c +++ /dev/null @@ -1,182 +0,0 @@ -/* $OpenBSD: mem.c,v 1.3 1997/04/19 17:19:45 pefo Exp $ */ -/* $NetBSD: mem.c,v 1.1.1.1 2000/01/23 20:24:25 soda Exp $ */ - -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1982, 1986, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department 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. - * - * @(#)mem.c 8.3 (Berkeley) 1/12/94 - */ - -/* - * Memory special file - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -extern vm_offset_t avail_end; -caddr_t zeropage; - -int mmopen __P((dev_t, int, int)); -int mmclose __P((dev_t, int, int)); -int mmrw __P((dev_t, struct uio *uio, int)); -int mmmmap __P((dev_t, int, int)); - -/*ARGSUSED*/ -int -mmopen(dev, flag, mode) - dev_t dev; - int flag, mode; -{ - - return (0); -} - -/*ARGSUSED*/ -int -mmclose(dev, flag, mode) - dev_t dev; - int flag, mode; -{ - - return (0); -} - -/*ARGSUSED*/ -int -mmrw(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; -{ - register vm_offset_t v; - register int c; - register struct iovec *iov; - int error = 0; - - while (uio->uio_resid > 0 && error == 0) { - iov = uio->uio_iov; - if (iov->iov_len == 0) { - uio->uio_iov++; - uio->uio_iovcnt--; - if (uio->uio_iovcnt < 0) - panic("mmrw"); - continue; - } - switch (minor(dev)) { - -/* minor device 0 is physical memory */ - case 0: - v = uio->uio_offset; - c = iov->iov_len; - if (v + c > ctob(physmem)) - return (EFAULT); - v += CACHED_MEMORY_ADDR; - error = uiomove((caddr_t)v, c, uio); - continue; - -/* minor device 1 is kernel memory */ - case 1: - v = uio->uio_offset; - c = min(iov->iov_len, MAXPHYS); - if (v < CACHED_MEMORY_ADDR) - return (EFAULT); - if (v + c > PHYS_TO_CACHED(avail_end + - sizeof (struct msgbuf)) && - (v < KSEG2_ADDR || - !kernacc((caddr_t)v, c, - uio->uio_rw == UIO_READ ? B_READ : B_WRITE))) - return (EFAULT); - - error = uiomove((caddr_t)v, c, uio); - continue; - -/* minor device 2 is EOF/RATHOLE */ - case 2: - if (uio->uio_rw == UIO_WRITE) - uio->uio_resid = 0; - return (0); - -/* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ - case 12: - if (uio->uio_rw == UIO_WRITE) { - c = iov->iov_len; - break; - } - if (zeropage == NULL) { - zeropage = (caddr_t) - malloc(CLBYTES, M_TEMP, M_WAITOK); - bzero(zeropage, CLBYTES); - } - c = min(iov->iov_len, CLBYTES); - error = uiomove(zeropage, c, uio); - continue; - - default: - return (ENXIO); - } - if (error) - break; - iov->iov_base += c; - iov->iov_len -= c; - uio->uio_offset += c; - uio->uio_resid -= c; - } - return (error); -} - -/*ARGSUSED*/ -int -mmmmap(dev, off, prot) - dev_t dev; - int off, prot; -{ - - return (EOPNOTSUPP); -} diff --git a/sys/arch/arc/arc/pmap.c b/sys/arch/arc/arc/pmap.c deleted file mode 100644 index 5842852e4cc3..000000000000 --- a/sys/arch/arc/arc/pmap.c +++ /dev/null @@ -1,1615 +0,0 @@ -/* $NetBSD: pmap.c,v 1.11 2000/01/23 20:09:17 soda Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department 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. - * - * from: @(#)pmap.c 8.4 (Berkeley) 1/26/94 - */ - -/* - * Manages physical address maps. - * - * In addition to hardware address maps, this - * module is called upon to provide software-use-only - * maps which may or may not be stored in the same - * form as hardware maps. These pseudo-maps are - * used to store intermediate results from copy - * operations to and from address spaces. - * - * Since the information managed by this module is - * also stored by the logical address mapping module, - * this module may throw away valid virtual-to-physical - * mappings at almost any time. However, invalidations - * of virtual-to-physical mappings must be done as - * requested. - * - * In order to cope with hardware architectures which - * make virtual-to-physical map invalidates expensive, - * this module may delay invalidate or reduced protection - * operations until such time as they are actually - * necessary. This module is given full information as - * to which processors are currently using which maps, - * and to when physical maps must be made correct. - */ - -#include "opt_sysv.h" - -#include -#include -#include -#include -#include -#include -#ifdef SYSVSHM -#include -#endif - -#include -#include -#include - -#include -#include -#include -#include - -extern vm_page_t vm_page_alloc1 __P((void)); -extern void vm_page_free1 __P((vm_page_t)); - -/* - * For each vm_page_t, there is a list of all currently valid virtual - * mappings of that page. An entry is a pv_entry_t, the list is pv_table. - * XXX really should do this as a part of the higher level code. - */ -typedef struct pv_entry { - struct pv_entry *pv_next; /* next pv_entry */ - struct pmap *pv_pmap; /* pmap where mapping lies */ - vm_offset_t pv_va; /* virtual address for mapping */ - int pv_flags; /* Some flags for the mapping */ -} *pv_entry_t; -#define PV_UNCACHED 0x0001 /* Page is mapped unchached */ - -/* - * Local pte bits used only here - */ -#define PG_RO 0x40000000 -#define PG_WIRED 0x80000000 - -pv_entry_t pv_table; /* array of entries, one per page */ -int pmap_remove_pv(); - -#define pa_index(pa) atop((pa) - first_phys_addr) -#define pa_to_pvh(pa) (&pv_table[pa_index(pa)]) - -#ifdef DEBUG -struct { - int kernel; /* entering kernel mapping */ - int user; /* entering user mapping */ - int ptpneeded; /* needed to allocate a PT page */ - int pwchange; /* no mapping change, just wiring or protection */ - int wchange; /* no mapping change, just wiring */ - int mchange; /* was mapped but mapping to different page */ - int managed; /* a managed page */ - int firstpv; /* first mapping for this PA */ - int secondpv; /* second mapping for this PA */ - int ci; /* cache inhibited */ - int unmanaged; /* not a managed page */ - int flushes; /* cache flushes */ - int cachehit; /* new entry forced valid entry out */ -} enter_stats; -struct { - int calls; - int removes; - int flushes; - int pidflushes; /* HW pid stolen */ - int pvfirst; - int pvsearch; -} remove_stats; - -int pmapdebug = 0; -#define PDB_FOLLOW 0x0001 -#define PDB_INIT 0x0002 -#define PDB_ENTER 0x0004 -#define PDB_REMOVE 0x0008 -#define PDB_CREATE 0x0010 -#define PDB_PTPAGE 0x0020 -#define PDB_PVENTRY 0x0040 -#define PDB_BITS 0x0080 -#define PDB_COLLECT 0x0100 -#define PDB_PROTECT 0x0200 -#define PDB_TLBPID 0x0400 -#define PDB_PARANOIA 0x2000 -#define PDB_WIRING 0x4000 -#define PDB_PVDUMP 0x8000 - -#endif /* DEBUG */ - -struct pmap kernel_pmap_store; - -vm_offset_t avail_start; /* PA of first available physical page */ -vm_offset_t avail_end; /* PA of last available physical page */ -vm_size_t mem_size; /* memory size in bytes */ -vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/ -vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ -int picapagesperpage; /* PAGE_SIZE / NBPG */ -#ifdef ATTR -char *pmap_attributes; /* reference and modify bits */ -#endif -struct segtab *free_segtab; /* free list kept locally */ -u_int tlbpid_gen = 1; /* TLB PID generation count */ -int tlbpid_cnt = 2; /* next available TLB PID */ -pt_entry_t *Sysmap; /* kernel pte table */ -u_int Sysmapsize; /* number of pte's in Sysmap */ - -void pmap_pinit __P((pmap_t)); -void pmap_release __P((pmap_t)); - -/* - * Bootstrap the system enough to run with virtual memory. - * firstaddr is the first unused kseg0 address (not page aligned). - */ -void -pmap_bootstrap(firstaddr) - vm_offset_t firstaddr; -{ - register int i; - register pt_entry_t *spte; - vm_offset_t start = firstaddr; - extern int maxmem, physmem; - -#define valloc(name, type, num) \ - (name) = (type *)firstaddr; firstaddr = (vm_offset_t)((name)+(num)) - /* - * Allocate a PTE table for the kernel. - * The '1024' comes from PAGER_MAP_SIZE in vm_pager_init(). - * This should be kept in sync. - * We also reserve space for kmem_alloc_pageable() for vm_fork(). - */ - Sysmapsize = (VM_KMEM_SIZE + VM_MBUF_SIZE + VM_PHYS_SIZE + - nbuf * MAXBSIZE + 16 * NCARGS) / NBPG + 1024 + 256; -#ifdef SYSVSHM - Sysmapsize += shminfo.shmall; -#endif - valloc(Sysmap, pt_entry_t, Sysmapsize); -#ifdef ATTR - valloc(pmap_attributes, char, physmem); -#endif - /* - * Allocate memory for pv_table. - * This will allocate more entries than we really need. - * We could do this in pmap_init when we know the actual - * phys_start and phys_end but its better to use kseg0 addresses - * rather than kernel virtual addresses mapped through the TLB. - */ - i = maxmem - pica_btop(MACH_CACHED_TO_PHYS(firstaddr)); - valloc(pv_table, struct pv_entry, i); - - /* - * Clear allocated memory. - */ - firstaddr = mips_round_page(firstaddr); - bzero((caddr_t)start, firstaddr - start); - - avail_start = MACH_CACHED_TO_PHYS(firstaddr); - avail_end = pica_ptob(maxmem); - mem_size = avail_end - avail_start; - - virtual_avail = VM_MIN_KERNEL_ADDRESS; - virtual_end = VM_MIN_KERNEL_ADDRESS + Sysmapsize * NBPG; - /* XXX need to decide how to set cnt.v_page_size */ - picapagesperpage = 1; - - simple_lock_init(&pmap_kernel()->pm_lock); - pmap_kernel()->pm_count = 1; - - /* - * The R4?00 stores only one copy of the Global bit in the - * translation lookaside buffer for each 2 page entry. - * Thus invalid entrys must have the Global bit set so - * when Entry LO and Entry HI G bits are anded together - * they will produce a global bit to store in the tlb. - */ - for(i = 0, spte = Sysmap; i < Sysmapsize; i++, spte++) - spte->pt_entry = PG_G; -} - -/* - * Bootstrap memory allocator. This function allows for early dynamic - * memory allocation until the virtual memory system has been bootstrapped. - * After that point, either kmem_alloc or malloc should be used. This - * function works by stealing pages from the (to be) managed page pool, - * stealing virtual address space, then mapping the pages and zeroing them. - * - * It should be used from pmap_bootstrap till vm_page_startup, afterwards - * it cannot be used, and will generate a panic if tried. Note that this - * memory will never be freed, and in essence it is wired down. - */ -void * -pmap_bootstrap_alloc(size) - int size; -{ - vm_offset_t val; - extern boolean_t vm_page_startup_initialized; - - if (vm_page_startup_initialized) - panic("pmap_bootstrap_alloc: called after startup initialized"); - - val = MACH_PHYS_TO_CACHED(avail_start); - size = round_page(size); - avail_start += size; - - blkclr((caddr_t)val, size); - return ((void *)val); -} - -/* - * Initialize the pmap module. - * Called by vm_init, to initialize any structures that the pmap - * system needs to map virtual memory. - */ -void -pmap_init(phys_start, phys_end) - vm_offset_t phys_start, phys_end; -{ - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_INIT)) - printf("pmap_init(%x, %x)\n", phys_start, phys_end); -#endif -} - -/* - * Create and return a physical map. - * - * If the size specified for the map - * is zero, the map is an actual physical - * map, and may be referenced by the - * hardware. - * - * If the size specified is non-zero, - * the map will be used in software only, and - * is bounded by that size. - */ -pmap_t -pmap_create(size) - vm_size_t size; -{ - register pmap_t pmap; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) - printf("pmap_create(%x)\n", size); -#endif - /* - * Software use map does not need a pmap - */ - if (size) - return (NULL); - - /* XXX: is it ok to wait here? */ - pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK); -#ifdef notifwewait - if (pmap == NULL) - panic("pmap_create: cannot allocate a pmap"); -#endif - bzero(pmap, sizeof(*pmap)); - pmap_pinit(pmap); - return (pmap); -} - -/* - * Initialize a preallocated and zeroed pmap structure, - * such as one in a vmspace structure. - */ -void -pmap_pinit(pmap) - register struct pmap *pmap; -{ - register int i; - int s; - extern struct vmspace vmspace0; - extern struct user *proc0paddr; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) - printf("pmap_pinit(%x)\n", pmap); -#endif - simple_lock_init(&pmap->pm_lock); - pmap->pm_count = 1; - if (free_segtab) { - s = splimp(); - pmap->pm_segtab = free_segtab; - free_segtab = *(struct segtab **)free_segtab; - pmap->pm_segtab->seg_tab[0] = NULL; - splx(s); - } else { - register struct segtab *stp; - vm_page_t mem; - void pmap_zero_page(); - - mem = vm_page_alloc1(); - pmap_zero_page(VM_PAGE_TO_PHYS(mem)); - pmap->pm_segtab = stp = (struct segtab *) - MACH_PHYS_TO_CACHED(VM_PAGE_TO_PHYS(mem)); - i = picapagesperpage * (NBPG / sizeof(struct segtab)); - s = splimp(); - while (--i != 0) { - stp++; - *(struct segtab **)stp = free_segtab; - free_segtab = stp; - } - splx(s); - } -#ifdef DIAGNOSTIC - for (i = 0; i < PMAP_SEGTABSIZE; i++) - if (pmap->pm_segtab->seg_tab[i] != 0) - panic("pmap_pinit: pm_segtab != 0"); -#endif - if (pmap == &vmspace0.vm_pmap) { - /* - * The initial process has already been allocated a TLBPID - * in mach_init(). - */ - pmap->pm_tlbpid = 1; - pmap->pm_tlbgen = tlbpid_gen; - proc0paddr->u_pcb.pcb_segtab = (void *)pmap->pm_segtab; - } else { - pmap->pm_tlbpid = 0; - pmap->pm_tlbgen = 0; - } -} - -/* - * Retire the given physical map from service. - * Should only be called if the map contains - * no valid mappings. - */ -void -pmap_destroy(pmap) - register pmap_t pmap; -{ - int count; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) - printf("pmap_destroy(%x)\n", pmap); -#endif - if (pmap == NULL) - return; - - simple_lock(&pmap->pm_lock); - count = --pmap->pm_count; - simple_unlock(&pmap->pm_lock); - if (count == 0) { - pmap_release(pmap); - free((caddr_t)pmap, M_VMPMAP); - } -} - -/* - * Release any resources held by the given physical map. - * Called when a pmap initialized by pmap_pinit is being released. - * Should only be called if the map contains no valid mappings. - */ -void -pmap_release(pmap) - register pmap_t pmap; -{ - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) - printf("pmap_release(%x)\n", pmap); -#endif - - if (pmap->pm_segtab) { - register pt_entry_t *pte; - register int i; - int s; -#ifdef DIAGNOSTIC - register int j; -#endif - - for (i = 0; i < PMAP_SEGTABSIZE; i++) { - /* get pointer to segment map */ - pte = pmap->pm_segtab->seg_tab[i]; - if (!pte) - continue; -#ifdef DIAGNOSTIC - for (j = 0; j < NPTEPG; j++) { - if ((pte+j)->pt_entry) - panic("pmap_release: segmap not empty"); - } -#endif - MachHitFlushDCache(pte, PAGE_SIZE); - vm_page_free1( - PHYS_TO_VM_PAGE(MACH_CACHED_TO_PHYS(pte))); - pmap->pm_segtab->seg_tab[i] = NULL; - } - s = splimp(); - *(struct segtab **)pmap->pm_segtab = free_segtab; - free_segtab = pmap->pm_segtab; - splx(s); - pmap->pm_segtab = NULL; - } -} - -/* - * Add a reference to the specified pmap. - */ -void -pmap_reference(pmap) - pmap_t pmap; -{ - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_reference(%x)\n", pmap); -#endif - if (pmap != NULL) { - simple_lock(&pmap->pm_lock); - pmap->pm_count++; - simple_unlock(&pmap->pm_lock); - } -} - -/* - * Remove the given range of addresses from the specified map. - * - * It is assumed that the start and end are properly - * rounded to the page size. - */ -void -pmap_remove(pmap, sva, eva) - register pmap_t pmap; - vm_offset_t sva, eva; -{ - register vm_offset_t nssva; - register pt_entry_t *pte; - unsigned entry; - int flush; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) - printf("pmap_remove(%x, %x, %x)\n", pmap, sva, eva); - remove_stats.calls++; -#endif - if (pmap == NULL) - return; - - if (!pmap->pm_segtab) { - register pt_entry_t *pte; - - /* remove entries from kernel pmap */ -#ifdef DIAGNOSTIC - if (sva < VM_MIN_KERNEL_ADDRESS || eva > virtual_end) - panic("pmap_remove: kva not in range"); -#endif - pte = kvtopte(sva); - for (; sva < eva; sva += NBPG, pte++) { - entry = pte->pt_entry; - if (!(entry & PG_V)) - continue; - if (entry & PG_WIRED) - pmap->pm_stats.wired_count--; - pmap->pm_stats.resident_count--; - if(pmap_remove_pv(pmap, sva, pfn_to_vad(entry))) { - MachFlushDCache(sva, PAGE_SIZE); - } -#ifdef ATTR - pmap_attributes[atop(pfn_to_vad(entry))] = 0; -#endif - /* - * Flush the TLB for the given address. - */ - pte->pt_entry = PG_NV | PG_G; /* See above about G bit */ - MachTLBFlushAddr(sva); -#ifdef DEBUG - remove_stats.flushes++; - -#endif - } - return; - } - -#ifdef DIAGNOSTIC - if (eva > VM_MAXUSER_ADDRESS) - panic("pmap_remove: uva not in range"); -#endif - while (sva < eva) { - nssva = mips_trunc_seg(sva) + NBSEG; - if (nssva == 0 || nssva > eva) - nssva = eva; - /* - * If VA belongs to an unallocated segment, - * skip to the next segment boundary. - */ - if (!(pte = pmap_segmap(pmap, sva))) { - sva = nssva; - continue; - } - /* - * Invalidate every valid mapping within this segment. - */ - pte += uvtopte(sva); - for (; sva < nssva; sva += NBPG, pte++) { - entry = pte->pt_entry; - if (!(entry & PG_V)) - continue; - if (entry & PG_WIRED) - pmap->pm_stats.wired_count--; - pmap->pm_stats.resident_count--; - if(pmap_remove_pv(pmap, sva, pfn_to_vad(entry))) { - MachFlushDCache(sva, PAGE_SIZE); - } -#ifdef ATTR - pmap_attributes[atop(pfn_to_vad(entry))] = 0; -#endif - pte->pt_entry = PG_NV; - /* - * Flush the TLB for the given address. - */ - if (pmap->pm_tlbgen == tlbpid_gen) { - MachTLBFlushAddr(sva | (pmap->pm_tlbpid << - VMMACH_TLB_PID_SHIFT)); -#ifdef DEBUG - remove_stats.flushes++; -#endif - } - } - } -} - -/* - * pmap_page_protect: - * - * Lower the permission for all mappings to a given page. - */ -void -pmap_page_protect(pa, prot) - vm_offset_t pa; - vm_prot_t prot; -{ - register pv_entry_t pv; - register vm_offset_t va; - int s; - -#ifdef DEBUG - if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) || - prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE)) - printf("pmap_page_protect(%x, %x)\n", pa, prot); -#endif - if (!IS_VM_PHYSADDR(pa)) - return; - - switch (prot) { - case VM_PROT_READ|VM_PROT_WRITE: - case VM_PROT_ALL: - break; - - /* copy_on_write */ - case VM_PROT_READ: - case VM_PROT_READ|VM_PROT_EXECUTE: - pv = pa_to_pvh(pa); - s = splimp(); - /* - * Loop over all current mappings setting/clearing as appropos. - */ - if (pv->pv_pmap != NULL) { - for (; pv; pv = pv->pv_next) { - extern vm_offset_t pager_sva, pager_eva; - - va = pv->pv_va; - - /* - * XXX don't write protect pager mappings - */ - if (va >= pager_sva && va < pager_eva) - continue; - pmap_protect(pv->pv_pmap, va, va + PAGE_SIZE, - prot); - } - } - splx(s); - break; - - /* remove_all */ - default: - pv = pa_to_pvh(pa); - s = splimp(); - while (pv->pv_pmap != NULL) { - pmap_remove(pv->pv_pmap, pv->pv_va, - pv->pv_va + PAGE_SIZE); - } - splx(s); - } -} - -/* - * Set the physical protection on the - * specified range of this map as requested. - */ -void -pmap_protect(pmap, sva, eva, prot) - register pmap_t pmap; - vm_offset_t sva, eva; - vm_prot_t prot; -{ - register vm_offset_t nssva; - register pt_entry_t *pte; - register unsigned entry; - u_int p; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) - printf("pmap_protect(%x, %x, %x, %x)\n", pmap, sva, eva, prot); -#endif - if (pmap == NULL) - return; - - if ((prot & VM_PROT_READ) == VM_PROT_NONE) { - pmap_remove(pmap, sva, eva); - return; - } - - p = (prot & VM_PROT_WRITE) ? PG_M : PG_RO; - - if (!pmap->pm_segtab) { - /* - * Change entries in kernel pmap. - * This will trap if the page is writeable (in order to set - * the dirty bit) even if the dirty bit is already set. The - * optimization isn't worth the effort since this code isn't - * executed much. The common case is to make a user page - * read-only. - */ -#ifdef DIAGNOSTIC - if (sva < VM_MIN_KERNEL_ADDRESS || eva > virtual_end) - panic("pmap_protect: kva not in range"); -#endif - pte = kvtopte(sva); - for (; sva < eva; sva += NBPG, pte++) { - entry = pte->pt_entry; - if (!(entry & PG_V)) - continue; - entry = (entry & ~(PG_M | PG_RO)) | p; - pte->pt_entry = entry; - /* - * Update the TLB if the given address is in the cache. - */ - MachTLBUpdate(sva, entry); - } - return; - } - -#ifdef DIAGNOSTIC - if (eva > VM_MAXUSER_ADDRESS) - panic("pmap_protect: uva not in range"); -#endif - while (sva < eva) { - nssva = mips_trunc_seg(sva) + NBSEG; - if (nssva == 0 || nssva > eva) - nssva = eva; - /* - * If VA belongs to an unallocated segment, - * skip to the next segment boundary. - */ - if (!(pte = pmap_segmap(pmap, sva))) { - sva = nssva; - continue; - } - /* - * Change protection on every valid mapping within this segment. - */ - pte += (sva >> PGSHIFT) & (NPTEPG - 1); - for (; sva < nssva; sva += NBPG, pte++) { - entry = pte->pt_entry; - if (!(entry & PG_V)) - continue; - entry = (entry & ~(PG_M | PG_RO)) | p; - pte->pt_entry = entry; - /* - * Update the TLB if the given address is in the cache. - */ - if (pmap->pm_tlbgen == tlbpid_gen) - MachTLBUpdate(sva | (pmap->pm_tlbpid << - VMMACH_TLB_PID_SHIFT), entry); - } - } -} - -/* - * Return RO protection of page. - */ -int -pmap_is_page_ro(pmap, va, entry) - pmap_t pmap; - vm_offset_t va; - int entry; -{ - return(entry & PG_RO); -} - -/* - * pmap_page_cache: - * - * Change all mappings of a page to cached/uncached. - */ -void -pmap_page_cache(pa,mode) - vm_offset_t pa; -{ - register pv_entry_t pv; - register pt_entry_t *pte; - register vm_offset_t va; - register unsigned entry; - register unsigned newmode; - int s; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_ENTER)) - printf("pmap_page_uncache(%x)\n", pa); -#endif - if (!IS_VM_PHYSADDR(pa)) - return; - - newmode = mode & PV_UNCACHED ? PG_UNCACHED : PG_CACHED; - pv = pa_to_pvh(pa); - s = splimp(); - while (pv) { - pv->pv_flags = (pv->pv_flags & ~PV_UNCACHED) | mode; - if (!pv->pv_pmap->pm_segtab) { - /* - * Change entries in kernel pmap. - */ - pte = kvtopte(pv->pv_va); - entry = pte->pt_entry; - if (entry & PG_V) { - entry = (entry & ~PG_CACHEMODE) | newmode; - pte->pt_entry = entry; - MachTLBUpdate(pv->pv_va, entry); - } - } - else { - if (pte = pmap_segmap(pv->pv_pmap, pv->pv_va)) { - pte += (pv->pv_va >> PGSHIFT) & (NPTEPG - 1); - entry = pte->pt_entry; - if (entry & PG_V) { - entry = (entry & ~PG_CACHEMODE) | newmode; - pte->pt_entry = entry; - if (pv->pv_pmap->pm_tlbgen == tlbpid_gen) - MachTLBUpdate(pv->pv_va | (pv->pv_pmap->pm_tlbpid << - VMMACH_TLB_PID_SHIFT), entry); - } - } - } - pv = pv->pv_next; - } - - splx(s); -} - -/* - * Insert the given physical page (p) at - * the specified virtual address (v) in the - * target physical map with the protection requested. - * - * If specified, the page will be wired down, meaning - * that the related pte can not be reclaimed. - * - * NB: This is the only routine which MAY NOT lazy-evaluate - * or lose information. That is, this routine must actually - * insert this page into the given map NOW. - */ -void -pmap_enter(pmap, va, pa, prot, wired, access_type) - register pmap_t pmap; - vm_offset_t va; - register vm_offset_t pa; - vm_prot_t prot; - boolean_t wired; - vm_prot_t access_type; -{ - register pt_entry_t *pte; - register u_int npte; - register int i; - vm_page_t mem; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_ENTER)) - printf("pmap_enter(%x, %x, %x, %x, %x)\n", - pmap, va, pa, prot, wired); -#endif -#ifdef DIAGNOSTIC - if (!pmap) - panic("pmap_enter: pmap"); - if (!pmap->pm_segtab) { - enter_stats.kernel++; - if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end) - panic("pmap_enter: kva"); - } else { - enter_stats.user++; - if (va >= VM_MAXUSER_ADDRESS) - panic("pmap_enter: uva"); - } - if (pa & 0x80000000) - panic("pmap_enter: pa"); - if (!(prot & VM_PROT_READ)) - panic("pmap_enter: prot"); -#endif - - if (IS_VM_PHYSADDR(pa)) { - register pv_entry_t pv, npv; - int s; - - if (!(prot & VM_PROT_WRITE)) - npte = PG_ROPAGE; - else { - register vm_page_t mem; - - mem = PHYS_TO_VM_PAGE(pa); - if ((int)va < 0) { - /* - * Don't bother to trap on kernel writes, - * just record page as dirty. - */ - npte = PG_RWPAGE; - mem->flags &= ~PG_CLEAN; - } else -#ifdef ATTR - if ((pmap_attributes[atop(pa)] & - PMAP_ATTR_MOD) || !(mem->flags & PG_CLEAN)) -#else - if (!(mem->flags & PG_CLEAN)) -#endif - npte = PG_RWPAGE; - else - npte = PG_CWPAGE; - } - -#ifdef DEBUG - enter_stats.managed++; -#endif - /* - * Enter the pmap and virtual address into the - * physical to virtual map table. - */ - pv = pa_to_pvh(pa); - s = splimp(); -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("pmap_enter: pv %x: was %x/%x/%x\n", - pv, pv->pv_va, pv->pv_pmap, pv->pv_next); -#endif - if (pv->pv_pmap == NULL) { - /* - * No entries yet, use header as the first entry - */ -#ifdef DEBUG - if (pmapdebug & PDB_PVENTRY) - printf("pmap_enter: first pv: pmap %x va %x\n", - pmap, va); - enter_stats.firstpv++; -#endif - pv->pv_va = va; - pv->pv_flags = 0; - pv->pv_pmap = pmap; - pv->pv_next = NULL; - } else { - if (!(pv->pv_flags & PV_UNCACHED)) { - /* - * There is at least one other VA mapping this page. - * Check if they are cache index compatible. If not - * remove all mappings, flush the cache and set page - * to be mapped uncached. Caching will be restored - * when pages are mapped compatible again. - */ - for (npv = pv; npv; npv = npv->pv_next) { - /* - * Check cache aliasing incompatibility - */ - if((npv->pv_va & machCacheAliasMask) != (va & machCacheAliasMask)) { - pmap_page_cache(pa,PV_UNCACHED); - MachFlushDCache(pv->pv_va, PAGE_SIZE); - npte = (npte & ~PG_CACHEMODE) | PG_UNCACHED; - break; - } - } - } - else { - npte = (npte & ~PG_CACHEMODE) | PG_UNCACHED; - } - /* - * There is at least one other VA mapping this page. - * Place this entry after the header. - * - * Note: the entry may already be in the table if - * we are only changing the protection bits. - */ - for (npv = pv; npv; npv = npv->pv_next) { - if (pmap == npv->pv_pmap && va == npv->pv_va) { -#ifdef DIAGNOSTIC - unsigned entry; - - if (!pmap->pm_segtab) - entry = kvtopte(va)->pt_entry; - else { - pte = pmap_segmap(pmap, va); - if (pte) { - pte += (va >> PGSHIFT) & - (NPTEPG - 1); - entry = pte->pt_entry; - } else - entry = 0; - } - if (!(entry & PG_V) || - pfn_to_vad(entry) != pa) - printf( - "pmap_enter: found va %x pa %x in pv_table but != %x\n", - va, pa, entry); -#endif - goto fnd; - } - } -#ifdef DEBUG - if (pmapdebug & PDB_PVENTRY) - printf("pmap_enter: new pv: pmap %x va %x\n", - pmap, va); -#endif - /* can this cause us to recurse forever? */ - npv = (pv_entry_t) - malloc(sizeof *npv, M_VMPVENT, M_NOWAIT); - npv->pv_va = va; - npv->pv_pmap = pmap; - npv->pv_next = pv->pv_next; - npv->pv_flags = pv->pv_flags; - pv->pv_next = npv; -#ifdef DEBUG - if (!npv->pv_next) - enter_stats.secondpv++; -#endif - fnd: - ; - } - splx(s); - } else { - /* - * Assumption: if it is not part of our managed memory - * then it must be device memory which may be volitile. - */ -#ifdef DEBUG - enter_stats.unmanaged++; -#endif - npte = (prot & VM_PROT_WRITE) ? (PG_IOPAGE & ~PG_G) : (PG_IOPAGE& ~(PG_G | PG_M)); - } - - /* - * The only time we need to flush the cache is if we - * execute from a physical address and then change the data. - * This is the best place to do this. - * pmap_protect() and pmap_remove() are mostly used to switch - * between R/W and R/O pages. - * NOTE: we only support cache flush for read only text. - */ - if (prot == (VM_PROT_READ | VM_PROT_EXECUTE)) - MachFlushICache(MACH_PHYS_TO_CACHED(pa), PAGE_SIZE); - - if (!pmap->pm_segtab) { - /* enter entries into kernel pmap */ - pte = kvtopte(va); - npte |= vad_to_pfn(pa) | PG_ROPAGE | PG_G; - if (wired) { - pmap->pm_stats.wired_count += picapagesperpage; - npte |= PG_WIRED; - } - i = picapagesperpage; - do { - if (!(pte->pt_entry & PG_V)) { - pmap->pm_stats.resident_count++; - } else { -#ifdef DIAGNOSTIC - if (pte->pt_entry & PG_WIRED) - panic("pmap_enter: kernel wired"); -#endif - } - /* - * Update the same virtual address entry. - */ - MachTLBUpdate(va, npte); - pte->pt_entry = npte; - va += NBPG; - npte += vad_to_pfn(NBPG); - pte++; - } while (--i != 0); - return; - } - - if (!(pte = pmap_segmap(pmap, va))) { - mem = vm_page_alloc1(); - pmap_zero_page(VM_PAGE_TO_PHYS(mem)); - pmap_segmap(pmap, va) = pte = (pt_entry_t *) - MACH_PHYS_TO_CACHED(VM_PAGE_TO_PHYS(mem)); -#ifdef DIAGNOSTIC - for (i = 0; i < NPTEPG; i++) { - if ((pte+i)->pt_entry) - panic("pmap_enter: new segmap not empty"); - } -#endif - } - pte += (va >> PGSHIFT) & (NPTEPG - 1); - - /* - * Now validate mapping with desired protection/wiring. - * Assume uniform modified and referenced status for all - * MIPS pages in a MACH page. - */ - npte |= vad_to_pfn(pa); - if (wired) { - pmap->pm_stats.wired_count += picapagesperpage; - npte |= PG_WIRED; - } -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) { - printf("pmap_enter: new pte %x", npte); - if (pmap->pm_tlbgen == tlbpid_gen) - printf(" tlbpid %d", pmap->pm_tlbpid); - printf("\n"); - } -#endif - i = picapagesperpage; - do { - pte->pt_entry = npte; - if (pmap->pm_tlbgen == tlbpid_gen) - MachTLBUpdate(va | (pmap->pm_tlbpid << - VMMACH_TLB_PID_SHIFT), npte); - va += NBPG; - npte += vad_to_pfn(NBPG); - pte++; - } while (--i != 0); -} - -/* - * Routine: pmap_unwire - * Function: Clear the wired attribute for a map/virtual-address - * pair. - * In/out conditions: - * The mapping must already exist in the pmap. - */ -void -pmap_unwire(pmap, va) - register pmap_t pmap; - vm_offset_t va; -{ - register pt_entry_t *pte; - register int i; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_WIRING)) - printf("pmap_unwire(%x, %x)\n", pmap, va); -#endif - if (pmap == NULL) - return; - - /* - * Don't need to flush the TLB since PG_WIRED is only in software. - */ - if (!pmap->pm_segtab) { - /* change entries in kernel pmap */ -#ifdef DIAGNOSTIC - if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end) - panic("pmap_unwire"); -#endif - pte = kvtopte(va); - } else { - pte = pmap_segmap(pmap, va); -#ifdef DIAGNOSTIC - if (pte == NULL) - panic("pmap_unwire: pmap %p va 0x%lx invalid STE", - pmap, va); -#endif - pte += (va >> PGSHIFT) & (NPTEPG - 1); - } - -#ifdef DIAGNOSTIC - if ((pte->pt_entry & PG_V) == 0) - panic("pmap_unwire: pmap %p va 0x%lx invalid PTE", - pmap, va); -#endif - - i = picapagesperpage; - if (pte->pt_entry & PG_WIRED) { - pmap->pm_stats.wired_count -= i; - do { - pte->pt_entry &= ~PG_WIRED; - } while (--i != 0); - } -#ifdef DIAGNOSTIC - else { - printf("pmap_unwire: wiring for pmap %p va 0x%lx " - "didn't change!\n", pmap, va); - } -#endif -} - -/* - * Routine: pmap_extract - * Function: - * Extract the physical page address associated - * with the given map/virtual_address pair. - */ -vm_offset_t -pmap_extract(pmap, va) - register pmap_t pmap; - vm_offset_t va; -{ - register vm_offset_t pa; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_extract(%x, %x) -> ", pmap, va); -#endif - - if (!pmap->pm_segtab) { -#ifdef DIAGNOSTIC - if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end) - panic("pmap_extract"); -#endif - pa = pfn_to_vad(kvtopte(va)->pt_entry); - } else { - register pt_entry_t *pte; - - if (!(pte = pmap_segmap(pmap, va))) - pa = 0; - else { - pte += (va >> PGSHIFT) & (NPTEPG - 1); - pa = pfn_to_vad(pte->pt_entry); - } - } - if (pa) - pa |= va & PGOFSET; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_extract: pa %x\n", pa); -#endif - return (pa); -} - -/* - * Copy the range specified by src_addr/len - * from the source map to the range dst_addr/len - * in the destination map. - * - * This routine is only advisory and need not do anything. - */ -void -pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) - pmap_t dst_pmap; - pmap_t src_pmap; - vm_offset_t dst_addr; - vm_size_t len; - vm_offset_t src_addr; -{ - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_copy(%x, %x, %x, %x, %x)\n", - dst_pmap, src_pmap, dst_addr, len, src_addr); -#endif -} - -/* - * Require that all active physical maps contain no - * incorrect entries NOW. [This update includes - * forcing updates of any address map caching.] - * - * Generally used to insure that a thread about - * to run will see a semantically correct world. - */ -void -pmap_update() -{ - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_update()\n"); -#endif -} - -/* - * Routine: pmap_collect - * Function: - * Garbage collects the physical map system for - * pages which are no longer used. - * Success need not be guaranteed -- that is, there - * may well be pages which are not referenced, but - * others may be collected. - * Usage: - * Called by the pageout daemon when pages are scarce. - */ -void -pmap_collect(pmap) - pmap_t pmap; -{ - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_collect(%x)\n", pmap); -#endif -} - -/* - * pmap_zero_page zeros the specified (machine independent) - * page. - */ -void -pmap_zero_page(phys) - vm_offset_t phys; -{ - register int *p, *end; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_zero_page(%x)\n", phys); -#endif -/*XXX FIXME Not very sophisticated */ - MachFlushCache(); - p = (int *)MACH_PHYS_TO_CACHED(phys); - end = p + PAGE_SIZE / sizeof(int); - do { - p[0] = 0; - p[1] = 0; - p[2] = 0; - p[3] = 0; - p += 4; - } while (p != end); -/*XXX FIXME Not very sophisticated */ - MachFlushCache(); -} - -/* - * pmap_copy_page copies the specified (machine independent) - * page. - */ -void -pmap_copy_page(src, dst) - vm_offset_t src, dst; -{ - register int *s, *d, *end; - register int tmp0, tmp1, tmp2, tmp3; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_copy_page(%x, %x)\n", src, dst); -#endif -/*XXX FIXME Not very sophisticated */ - MachFlushCache(); - s = (int *)MACH_PHYS_TO_CACHED(src); - d = (int *)MACH_PHYS_TO_CACHED(dst); - end = s + PAGE_SIZE / sizeof(int); - do { - tmp0 = s[0]; - tmp1 = s[1]; - tmp2 = s[2]; - tmp3 = s[3]; - d[0] = tmp0; - d[1] = tmp1; - d[2] = tmp2; - d[3] = tmp3; - s += 4; - d += 4; - } while (s != end); -/*XXX FIXME Not very sophisticated */ - MachFlushCache(); -} - -/* - * Clear the modify bits on the specified physical page. - */ -void -pmap_clear_modify(pa) - vm_offset_t pa; -{ - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_clear_modify(%x)\n", pa); -#endif -#ifdef ATTR - pmap_attributes[atop(pa)] &= ~PMAP_ATTR_MOD; -#endif -} - -/* - * pmap_clear_reference: - * - * Clear the reference bit on the specified physical page. - */ -void -pmap_clear_reference(pa) - vm_offset_t pa; -{ - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_clear_reference(%x)\n", pa); -#endif -#ifdef ATTR - pmap_attributes[atop(pa)] &= ~PMAP_ATTR_REF; -#endif -} - -/* - * pmap_is_referenced: - * - * Return whether or not the specified physical page is referenced - * by any physical maps. - */ -boolean_t -pmap_is_referenced(pa) - vm_offset_t pa; -{ -#ifdef ATTR - return (pmap_attributes[atop(pa)] & PMAP_ATTR_REF); -#else - return (FALSE); -#endif -} - -/* - * pmap_is_modified: - * - * Return whether or not the specified physical page is modified - * by any physical maps. - */ -boolean_t -pmap_is_modified(pa) - vm_offset_t pa; -{ -#ifdef ATTR - return (pmap_attributes[atop(pa)] & PMAP_ATTR_MOD); -#else - return (FALSE); -#endif -} - -vm_offset_t -pmap_phys_address(ppn) - int ppn; -{ - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_phys_address(%x)\n", ppn); -#endif - return (pica_ptob(ppn)); -} - -/* - * Miscellaneous support routines - */ - -/* - * Allocate a hardware PID and return it. - * It takes almost as much or more time to search the TLB for a - * specific PID and flush those entries as it does to flush the entire TLB. - * Therefore, when we allocate a new PID, we just take the next number. When - * we run out of numbers, we flush the TLB, increment the generation count - * and start over. PID zero is reserved for kernel use. - * This is called only by switch(). - */ -int -pmap_alloc_tlbpid(p) - register struct proc *p; -{ - register pmap_t pmap; - register int id; - - pmap = &p->p_vmspace->vm_pmap; - if (pmap->pm_tlbgen != tlbpid_gen) { - id = tlbpid_cnt; - if (id == VMMACH_NUM_PIDS) { - MachTLBFlush(); - /* reserve tlbpid_gen == 0 to alway mean invalid */ - if (++tlbpid_gen == 0) - tlbpid_gen = 1; - id = 1; - } - tlbpid_cnt = id + 1; - pmap->pm_tlbpid = id; - pmap->pm_tlbgen = tlbpid_gen; - } else - id = pmap->pm_tlbpid; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_TLBPID)) { - if (curproc) - printf("pmap_alloc_tlbpid: curproc %d '%s' ", - curproc->p_pid, curproc->p_comm); - else - printf("pmap_alloc_tlbpid: curproc "); - printf("segtab %x tlbpid %d pid %d '%s'\n", - pmap->pm_segtab, id, p->p_pid, p->p_comm); - } -#endif - return (id); -} - -/* - * Remove a physical to virtual address translation. - * Returns TRUE if it was the last mapping and cached, else FALSE. - */ -int -pmap_remove_pv(pmap, va, pa) - pmap_t pmap; - vm_offset_t va, pa; -{ - register pv_entry_t pv, npv; - int s, last; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_PVENTRY)) - printf("pmap_remove_pv(%x, %x, %x)\n", pmap, va, pa); -#endif - /* - * Remove page from the PV table (raise IPL since we - * may be called at interrupt time). - */ - if (!IS_VM_PHYSADDR(pa)) - return(TRUE); - pv = pa_to_pvh(pa); - s = splimp(); - /* - * If it is the first entry on the list, it is actually - * in the header and we must copy the following entry up - * to the header. Otherwise we must search the list for - * the entry. In either case we free the now unused entry. - */ - if (pmap == pv->pv_pmap && va == pv->pv_va) { - last = (pv->pv_flags & PV_UNCACHED) ? FALSE : TRUE; - npv = pv->pv_next; - if (npv) { - *pv = *npv; - free((caddr_t)npv, M_VMPVENT); - } else - pv->pv_pmap = NULL; -#ifdef DEBUG - remove_stats.pvfirst++; -#endif - } else { - last = FALSE; - for (npv = pv->pv_next; npv; pv = npv, npv = npv->pv_next) { -#ifdef DEBUG - remove_stats.pvsearch++; -#endif - if (pmap == npv->pv_pmap && va == npv->pv_va) - goto fnd; - } -#ifdef DIAGNOSTIC - printf("pmap_remove_pv(%x, %x, %x) not found\n", pmap, va, pa); - panic("pmap_remove_pv"); -#endif - fnd: - pv->pv_next = npv->pv_next; - free((caddr_t)npv, M_VMPVENT); - } - splx(s); - return(last); -} - -/* - * vm_page_alloc1: - * - * Allocate and return a memory cell with no associated object. - */ -vm_page_t -vm_page_alloc1() -{ - register vm_page_t mem; - int spl; - - spl = splimp(); /* XXX */ - simple_lock(&vm_page_queue_free_lock); - if (vm_page_queue_free.tqh_first == NULL) { - simple_unlock(&vm_page_queue_free_lock); - splx(spl); - return (NULL); - } - - mem = vm_page_queue_free.tqh_first; - TAILQ_REMOVE(&vm_page_queue_free, mem, pageq); - - cnt.v_free_count--; - simple_unlock(&vm_page_queue_free_lock); - splx(spl); - - mem->flags = PG_BUSY | PG_CLEAN | PG_FAKE; - mem->wire_count = 0; - - /* - * Decide if we should poke the pageout daemon. - * We do this if the free count is less than the low - * water mark, or if the free count is less than the high - * water mark (but above the low water mark) and the inactive - * count is less than its target. - * - * We don't have the counts locked ... if they change a little, - * it doesn't really matter. - */ - - if (cnt.v_free_count < cnt.v_free_min || - (cnt.v_free_count < cnt.v_free_target && - cnt.v_inactive_count < cnt.v_inactive_target)) - thread_wakeup((void *)&vm_pages_needed); - return (mem); -} - -/* - * vm_page_free1: - * - * Returns the given page to the free list, - * disassociating it with any VM object. - * - * Object and page must be locked prior to entry. - */ -void -vm_page_free1(mem) - register vm_page_t mem; -{ - - if (mem->flags & PG_ACTIVE) { - TAILQ_REMOVE(&vm_page_queue_active, mem, pageq); - mem->flags &= ~PG_ACTIVE; - cnt.v_active_count--; - } - - if (mem->flags & PG_INACTIVE) { - TAILQ_REMOVE(&vm_page_queue_inactive, mem, pageq); - mem->flags &= ~PG_INACTIVE; - cnt.v_inactive_count--; - } - - if (!(mem->flags & PG_FICTITIOUS)) { - int spl; - - spl = splimp(); - simple_lock(&vm_page_queue_free_lock); - TAILQ_INSERT_TAIL(&vm_page_queue_free, mem, pageq); - - cnt.v_free_count++; - simple_unlock(&vm_page_queue_free_lock); - splx(spl); - } -} diff --git a/sys/arch/arc/arc/process_machdep.c b/sys/arch/arc/arc/process_machdep.c deleted file mode 100644 index aecc0519640a..000000000000 --- a/sys/arch/arc/arc/process_machdep.c +++ /dev/null @@ -1,116 +0,0 @@ -/* $OpenBSD: process_machdep.c,v 1.2 1997/04/19 17:19:47 pefo Exp $ */ -/* - * Copyright (c) 1994 Adam Glass - * Copyright (c) 1993 The Regents of the University of California. - * Copyright (c) 1993 Jan-Simon Pendry - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * - * From: - * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel - * - * $Id: process_machdep.c,v 1.1.1.1 2000/01/23 20:24:25 soda Exp $ - */ - -/* - * This file may seem a bit stylized, but that so that it's easier to port. - * Functions to be implemented here are: - * - * process_read_regs(proc, regs) - * Get the current user-visible register set from the process - * and copy it into the regs structure (). - * The process is stopped at the time read_regs is called. - * - * process_write_regs(proc, regs) - * Update the current register set from the passed in regs - * structure. Take care to avoid clobbering special CPU - * registers or privileged bits in the PSL. - * The process is stopped at the time write_regs is called. - * - * process_sstep(proc) - * Arrange for the process to trap after executing a single instruction. - * - * process_set_pc(proc) - * Set the process's program counter. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern void cpu_singlestep __P((struct proc *)); -int -process_read_regs(p, regs) - struct proc *p; - struct reg *regs; -{ - bcopy((caddr_t)p->p_md.md_regs, (caddr_t)regs, sizeof(struct reg)); - return (0); -} - -int -process_write_regs(p, regs) - struct proc *p; - struct reg *regs; -{ - bcopy((caddr_t)regs, (caddr_t)p->p_md.md_regs, sizeof(struct reg)); -/*XXX Clear to user set bits!! */ - return (0); -} - -int -process_sstep(p, sstep) - struct proc *p; -{ - if(sstep) - cpu_singlestep(p); - return (0); -} - -int -process_set_pc(p, addr) - struct proc *p; - caddr_t addr; -{ - p->p_md.md_regs[PC] = (int)addr; - return (0); -} - diff --git a/sys/arch/arc/arc/swapgeneric.c b/sys/arch/arc/arc/swapgeneric.c deleted file mode 100644 index 0bd7e4aab2b0..000000000000 --- a/sys/arch/arc/arc/swapgeneric.c +++ /dev/null @@ -1,61 +0,0 @@ -/* $OpenBSD: swapgeneric.c,v 1.4 1996/11/06 01:38:16 deraadt Exp $ */ - -/*- - * Copyright (c) 1994 - * The Regents of the University of California. All rights reserved. - * - * 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. - * - * @(#)swapgeneric.c 8.2 (Berkeley) 3/21/94 - */ - -/* - * fake swapgeneric.c -- should do this differently. - */ - -#include -#include -#include - -int (*mountroot) __P((void)) = NULL; /* tells autoconf.c that we are "generic" */ - -dev_t rootdev = NODEV; -dev_t dumpdev = NODEV; - -struct swdevt swdevt[] = { - { makedev(3, 0*MAXPARTITIONS+1), 0, 0 }, /* sd0b */ - { makedev(3, 1*MAXPARTITIONS+1), 0, 0 }, /* sd1b */ - { makedev(3, 2*MAXPARTITIONS+1), 0, 0 }, /* sd2b */ - { makedev(3, 3*MAXPARTITIONS+1), 0, 0 }, /* sd3b */ - { makedev(3, 4*MAXPARTITIONS+1), 0, 0 }, /* sd4b */ - { makedev(3, 5*MAXPARTITIONS+1), 0, 0 }, /* sd5b */ - { makedev(3, 6*MAXPARTITIONS+1), 0, 0 }, /* sd6b */ - { makedev(3, 7*MAXPARTITIONS+1), 0, 0 }, /* sd7b */ - { NODEV, 0, 0 } -}; diff --git a/sys/arch/arc/arc/sys_machdep.c b/sys/arch/arc/arc/sys_machdep.c deleted file mode 100644 index 1cb891814043..000000000000 --- a/sys/arch/arc/arc/sys_machdep.c +++ /dev/null @@ -1,128 +0,0 @@ -/* $NetBSD: sys_machdep.c,v 1.4 2000/01/23 20:09:17 soda Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * 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. - * - * @(#)sys_machdep.c 8.1 (Berkeley) 6/10/93 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef TRACE -int nvualarm; - -vtrace(p, uap, retval) - struct proc *p; - register struct vtrace_args /* { - syscallarg(int) request; - syscallarg(int) value; - } */ *uap; - register_t *retval; -{ - int vdoualarm(); - - switch (SCARG(uap, request)) { - - case VTR_DISABLE: /* disable a trace point */ - case VTR_ENABLE: /* enable a trace point */ - if (SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS) - return (EINVAL); - *retval = traceflags[SCARG(uap, value)]; - traceflags[SCARG(uap, value)] = SCARG(uap, request); - break; - - case VTR_VALUE: /* return a trace point setting */ - if (SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS) - return (EINVAL); - *retval = traceflags[SCARG(uap, value)]; - break; - - case VTR_UALARM: /* set a real-time ualarm, less than 1 min */ - if (SCARG(uap, value) <= 0 || SCARG(uap, value) > 60 * hz || - nvualarm > 5) - return (EINVAL); - nvualarm++; - timeout(vdoualarm, (caddr_t)p->p_pid, SCARG(uap, value)); - break; - - case VTR_STAMP: - trace(TR_STAMP, SCARG(uap, value), p->p_pid); - break; - } - return (0); -} - -vdoualarm(arg) - int arg; -{ - register struct proc *p; - - p = pfind(arg); - if (p) - psignal(p, 16); - nvualarm--; -} -#endif - -sys_sysarch(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct sys_sysarch_args /* { - syscallarg(int) op; - syscallarg(void *) parms; - } */ *uap = v; - int error = 0; - - switch(SCARG(uap, op)) { - default: - error = EINVAL; - break; - } - return (error); -} diff --git a/sys/arch/arc/arc/trap.c b/sys/arch/arc/arc/trap.c deleted file mode 100644 index 1c60cefefdf5..000000000000 --- a/sys/arch/arc/arc/trap.c +++ /dev/null @@ -1,1741 +0,0 @@ -/* $NetBSD: trap.c,v 1.18 2000/01/23 20:09:20 soda Exp $ */ - -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department 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. - * - * from: Utah Hdr: trap.c 1.32 91/04/06 - * - * @(#)trap.c 8.5 (Berkeley) 1/11/94 - */ - -#include "opt_inet.h" -#include "opt_atalk.h" -#include "opt_iso.h" -#include "opt_ns.h" -#include "opt_ktrace.h" - -#if #defined(CPU_R4000) && !defined(CPU_R3000) -#error Must define at least one of CPU_R3000 or CPU_R4000. -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef KTRACE -#include -#endif -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -/* all this to get prototypes for ipintr() and arpintr() */ -#include -#include -#include -#include -#include - -#ifdef INET6 -# if 0 /*ifndef INET*/ -# include -# endif -#include -#include -#endif - -#ifdef NETATALK -#include -#endif - -struct proc *machFPCurProcPtr; /* pointer to last proc to use FP */ - -/* - * Port-specific hardware interrupt handler - */ - -int (*mips_hardware_intr) __P((u_int mask, u_int pc, u_int status, - u_int cause)) = - ( int (*) __P((u_int, u_int, u_int, u_int)) ) 0; - -/* - * Exception-handling functions, called via machExceptionTable from locore - */ -extern void MachTLBModException __P((void)); -extern void MachTLBInvalidException __P((void)); -extern unsigned MachEmulateBranch __P((unsigned *regsPtr, - unsigned instPC, - unsigned fpcCSR, - int allowNonBranch)); - -extern void mips_r2000_KernGenException __P((void)); -extern void mips_r2000_UserGenException __P((void)); -extern void mips_r2000_KernIntr __P((void)); -extern void mips_r2000_UserIntr __P((void)); -extern void mips_r2000_TLBModException __P((void)); -extern void mips_r2000_TLBMissException __P((void)); - - -extern void mips_r4000_KernGenException __P((void)); -extern void mips_r4000_UserGenException __P((void)); -extern void mips_r4000_KernIntr __P((void)); -extern void mips_r4000_UserIntr __P((void)); -extern void mips_r4000_TLBModException __P((void)); -extern void mips_r4000_TLBMissException __P((void)); -extern void mips_r4000_TLBInvalidException __P((void)); - - -void (*mips_r4000_ExceptionTable[]) __P((void)) = { -/* - * The kernel exception handlers. - */ - mips_r4000_KernIntr, /* external interrupt */ - mips_r4000_KernGenException, /* TLB modification */ - mips_r4000_TLBInvalidException, /* TLB miss (load or instr. fetch) */ - mips_r4000_TLBInvalidException, /* TLB miss (store) */ - mips_r4000_KernGenException, /* address error (load or I-fetch) */ - mips_r4000_KernGenException, /* address error (store) */ - mips_r4000_KernGenException, /* bus error (I-fetch) */ - mips_r4000_KernGenException, /* bus error (load or store) */ - mips_r4000_KernGenException, /* system call */ - mips_r4000_KernGenException, /* breakpoint */ - mips_r4000_KernGenException, /* reserved instruction */ - mips_r4000_KernGenException, /* coprocessor unusable */ - mips_r4000_KernGenException, /* arithmetic overflow */ - mips_r4000_KernGenException, /* trap exception */ - mips_r4000_KernGenException, /* virtual coherence exception inst */ - mips_r4000_KernGenException, /* floating point exception */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* watch exception */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* virtual coherence exception data */ -/* - * The user exception handlers. - */ - mips_r4000_UserIntr, /* 0 */ - mips_r4000_UserGenException, /* 1 */ - mips_r4000_UserGenException, /* 2 */ - mips_r4000_UserGenException, /* 3 */ - mips_r4000_UserGenException, /* 4 */ - mips_r4000_UserGenException, /* 5 */ - mips_r4000_UserGenException, /* 6 */ - mips_r4000_UserGenException, /* 7 */ - mips_r4000_UserGenException, /* 8 */ - mips_r4000_UserGenException, /* 9 */ - mips_r4000_UserGenException, /* 10 */ - mips_r4000_UserGenException, /* 11 */ - mips_r4000_UserGenException, /* 12 */ - mips_r4000_UserGenException, /* 13 */ - mips_r4000_UserGenException, /* 14 */ - mips_r4000_UserGenException, /* 15 */ - mips_r4000_UserGenException, /* 16 */ - mips_r4000_UserGenException, /* 17 */ - mips_r4000_UserGenException, /* 18 */ - mips_r4000_UserGenException, /* 19 */ - mips_r4000_UserGenException, /* 20 */ - mips_r4000_UserGenException, /* 21 */ - mips_r4000_UserGenException, /* 22 */ - mips_r4000_UserGenException, /* 23 */ - mips_r4000_UserGenException, /* 24 */ - mips_r4000_UserGenException, /* 25 */ - mips_r4000_UserGenException, /* 26 */ - mips_r4000_UserGenException, /* 27 */ - mips_r4000_UserGenException, /* 28 */ - mips_r4000_UserGenException, /* 29 */ - mips_r4000_UserGenException, /* 20 */ - mips_r4000_UserGenException, /* 31 */ -}; - -/* - * XXX bug compatibility. Some versions of the locore code still refer - * to the exception vector by the Sprite name. - * Note these are all different from the r2000 equivalents. At the very - * least, the MIPS-1 returns from an exception using rfe, and the - * MIPS-III uses eret. -*/ - -void (*machExceptionTable[]) __P((void)) = { -/* - * The kernel exception handlers. - */ - mips_r4000_KernIntr, /* external interrupt */ - mips_r4000_KernGenException, /* TLB modification */ - mips_r4000_TLBInvalidException, /* TLB miss (load or instr. fetch) */ - mips_r4000_TLBInvalidException, /* TLB miss (store) */ - mips_r4000_KernGenException, /* address error (load or I-fetch) */ - mips_r4000_KernGenException, /* address error (store) */ - mips_r4000_KernGenException, /* bus error (I-fetch) */ - mips_r4000_KernGenException, /* bus error (load or store) */ - mips_r4000_KernGenException, /* system call */ - mips_r4000_KernGenException, /* breakpoint */ - mips_r4000_KernGenException, /* reserved instruction */ - mips_r4000_KernGenException, /* coprocessor unusable */ - mips_r4000_KernGenException, /* arithmetic overflow */ - mips_r4000_KernGenException, /* trap exception */ - mips_r4000_KernGenException, /* virtual coherence exception inst */ - mips_r4000_KernGenException, /* floating point exception */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* watch exception */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* reserved */ - mips_r4000_KernGenException, /* virtual coherence exception data */ -/* - * The user exception handlers. - */ - mips_r4000_UserIntr, /* 0 */ - mips_r4000_UserGenException, /* 1 */ - mips_r4000_UserGenException, /* 2 */ - mips_r4000_UserGenException, /* 3 */ - mips_r4000_UserGenException, /* 4 */ - mips_r4000_UserGenException, /* 5 */ - mips_r4000_UserGenException, /* 6 */ - mips_r4000_UserGenException, /* 7 */ - mips_r4000_UserGenException, /* 8 */ - mips_r4000_UserGenException, /* 9 */ - mips_r4000_UserGenException, /* 10 */ - mips_r4000_UserGenException, /* 11 */ - mips_r4000_UserGenException, /* 12 */ - mips_r4000_UserGenException, /* 13 */ - mips_r4000_UserGenException, /* 14 */ - mips_r4000_UserGenException, /* 15 */ - mips_r4000_UserGenException, /* 16 */ - mips_r4000_UserGenException, /* 17 */ - mips_r4000_UserGenException, /* 18 */ - mips_r4000_UserGenException, /* 19 */ - mips_r4000_UserGenException, /* 20 */ - mips_r4000_UserGenException, /* 21 */ - mips_r4000_UserGenException, /* 22 */ - mips_r4000_UserGenException, /* 23 */ - mips_r4000_UserGenException, /* 24 */ - mips_r4000_UserGenException, /* 25 */ - mips_r4000_UserGenException, /* 26 */ - mips_r4000_UserGenException, /* 27 */ - mips_r4000_UserGenException, /* 28 */ - mips_r4000_UserGenException, /* 29 */ - mips_r4000_UserGenException, /* 20 */ - mips_r4000_UserGenException, /* 31 */ -}; - -char *trap_type[] = { - "external interrupt", - "TLB modification", - "TLB miss (load or instr. fetch)", - "TLB miss (store)", - "address error (load or I-fetch)", - "address error (store)", - "bus error (I-fetch)", - "bus error (load or store)", - "system call", - "breakpoint", - "reserved instruction", - "coprocessor unusable", - "arithmetic overflow", - "r4k trap/r3k reserved 13", - "r4k virtual coherency instruction/r3k reserved 14", - "r4k floating point/ r3k reserved 15", - "reserved 16", - "reserved 17", - "reserved 18", - "reserved 19", - "reserved 20", - "reserved 21", - "reserved 22", - "r4000 watch", - "reserved 24", - "reserved 25", - "reserved 26", - "reserved 27", - "reserved 28", - "reserved 29", - "reserved 30", - "r4000 virtual coherency data", -}; - -#ifdef DEBUG -#define TRAPSIZE 10 -struct trapdebug { /* trap history buffer for debugging */ - u_int status; - u_int cause; - u_int vadr; - u_int pc; - u_int ra; - u_int sp; - u_int code; -} trapdebug[TRAPSIZE], *trp = trapdebug; - -void trapDump __P((char * msg)); -void cpu_getregs __P((int *regs)); -#endif /* DEBUG */ - -#ifdef DEBUG /* stack trace code, also useful for DDB one day */ -extern void stacktrace(); -extern void logstacktrace(); - -/* extern functions printed by name in stack backtraces */ -extern void idle(), cpu_switch(), wbflush(); -extern void MachTLBMiss(); -extern int main __P((void*)); -#endif /* DEBUG */ - -extern volatile struct chiptime *Mach_clock_addr; -extern u_long intrcnt[]; - - -/* - * Handle an exception. - * Called from MachKernGenException() or MachUserGenException() - * when a processor trap occurs. - * In the case of a kernel trap, we return the pc where to resume if - * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc. - */ -unsigned -trap(statusReg, causeReg, vadr, pc, args) - unsigned statusReg; /* status register at time of the exception */ - unsigned causeReg; /* cause register at time of exception */ - unsigned vadr; /* address (if any) the fault occured on */ - unsigned pc; /* program counter where to continue */ -{ - register int type, i; - unsigned ucode = 0; - register struct proc *p = curproc; - u_quad_t sticks; - vm_prot_t ftype; - extern unsigned onfault_table[]; - -#ifdef DEBUG - trp->status = statusReg; - trp->cause = causeReg; - trp->vadr = vadr; - trp->pc = pc; - trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] : - p->p_md.md_regs[RA]; - trp->sp = (int)&args; - trp->code = 0; - if (++trp == &trapdebug[TRAPSIZE]) - trp = trapdebug; -#endif - - cnt.v_trap++; - type = (causeReg & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT; - if (USERMODE(statusReg)) { - type |= T_USER; - sticks = p->p_sticks; - } - - /* - * Enable hardware interrupts if they were on before. - * We only respond to software interrupts when returning to user mode. - */ - if (statusReg & MIPS_SR_INT_IE) - splx((statusReg & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE); - - switch (type) { - case T_TLB_MOD: - /* check for kernel address */ - if ((int)vadr < 0) { - register pt_entry_t *pte; - register unsigned entry; - register vm_offset_t pa; - - pte = kvtopte(vadr); - entry = pte->pt_entry; -#ifdef DIAGNOSTIC - if (!(entry & PG_V) || (entry & PG_M)) - panic("trap: ktlbmod: invalid pte"); -#endif - if (pmap_is_page_ro(pmap_kernel(), pica_trunc_page(vadr), entry)) { - /* write to read only page in the kernel */ - ftype = VM_PROT_WRITE; - goto kernel_fault; - } - entry |= PG_M; - pte->pt_entry = entry; - vadr &= ~PGOFSET; - MachTLBUpdate(vadr, entry); - pa = pfn_to_vad(entry); -#ifdef ATTR - pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD; -#else - if (!IS_VM_PHYSADDR(pa)) - panic("trap: ktlbmod: unmanaged page"); - PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN; -#endif - return (pc); - } - /* FALLTHROUGH */ - - case T_TLB_MOD+T_USER: - { - register pt_entry_t *pte; - register unsigned entry; - register vm_offset_t pa; - pmap_t pmap = &p->p_vmspace->vm_pmap; - - if (!(pte = pmap_segmap(pmap, vadr))) - panic("trap: utlbmod: invalid segmap"); - pte += (vadr >> PGSHIFT) & (NPTEPG - 1); - entry = pte->pt_entry; -#ifdef DIAGNOSTIC - if (!(entry & PG_V) || (entry & PG_M)) { - panic("trap: utlbmod: invalid pte"); - } -#endif - if (pmap_is_page_ro(pmap, pica_trunc_page(vadr), entry)) { - /* write to read only page */ - ftype = VM_PROT_WRITE; - goto dofault; - } - entry |= PG_M; - pte->pt_entry = entry; - vadr = (vadr & ~PGOFSET) | - (pmap->pm_tlbpid << VMMACH_TLB_PID_SHIFT); - MachTLBUpdate(vadr, entry); - pa = pfn_to_vad(entry); -#ifdef ATTR - pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD; -#else - if (!IS_VM_PHYSADDR(pa)) { - panic("trap: utlbmod: unmanaged page"); - } - PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN; -#endif - if (!USERMODE(statusReg)) - return (pc); - goto out; - } - - case T_TLB_LD_MISS: - case T_TLB_ST_MISS: - ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ; - /* check for kernel address */ - if ((int)vadr < 0) { - register vm_offset_t va; - int rv; - - kernel_fault: - /*kernelfaults++;*/ - va = trunc_page((vm_offset_t)vadr); - rv = vm_fault(kernel_map, va, ftype, FALSE); - if (rv == KERN_SUCCESS) - return (pc); - if ((i = ((struct pcb *)UADDR)->pcb_onfault) != 0) { - ((struct pcb *)UADDR)->pcb_onfault = 0; - return (onfault_table[i]); - } - goto err; - } - /* - * It is an error for the kernel to access user space except - * through the copyin/copyout routines. - */ - if ((i = ((struct pcb *)UADDR)->pcb_onfault) == 0) - goto err; - /* check for fuswintr() or suswintr() getting a page fault */ - if (i == 4) - return (onfault_table[i]); - goto dofault; - - case T_TLB_LD_MISS+T_USER: - ftype = VM_PROT_READ; - goto dofault; - - case T_TLB_ST_MISS+T_USER: - ftype = VM_PROT_WRITE; - dofault: - { - register vm_offset_t va; - register struct vmspace *vm; - register vm_map_t map; - int rv; - - vm = p->p_vmspace; - map = &vm->vm_map; - va = trunc_page((vm_offset_t)vadr); - rv = vm_fault(map, va, ftype, FALSE); -#ifdef VMFAULT_TRACE - printf("vm_fault(%x (pmap %x), %x (%x), %x, %d) -> %x at pc %x\n", - map, &vm->vm_pmap, va, vadr, ftype, FALSE, rv, pc); -#endif - /* - * If this was a stack access we keep track of the maximum - * accessed stack size. Also, if vm_fault gets a protection - * failure it is due to accessing the stack region outside - * the current limit and we need to reflect that as an access - * error. - */ - if ((caddr_t)va >= vm->vm_maxsaddr) { - if (rv == KERN_SUCCESS) { - unsigned nss; - - nss = btoc(USRSTACK-(unsigned)va); - if (nss > vm->vm_ssize) - vm->vm_ssize = nss; - } else if (rv == KERN_PROTECTION_FAILURE) - rv = KERN_INVALID_ADDRESS; - } - if (rv == KERN_SUCCESS) { - if (!USERMODE(statusReg)) - return (pc); - goto out; - } - if (!USERMODE(statusReg)) { - if ((i = ((struct pcb *)UADDR)->pcb_onfault) != 0) { - ((struct pcb *)UADDR)->pcb_onfault = 0; - return (onfault_table[i]); - } - goto err; - } - ucode = vadr; - if (rv == KERN_RESOURCE_SHORTAGE) { - printf("UVM: pid %d (%s), uid %d killed: out of swap\n", - p->p_pid, p->p_comm, - p->p_cred && p->p_ucred ? - p->p_ucred->cr_uid : -1); - i = SIGKILL; - } else { - i = SIGSEGV; - } - break; - } - - case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */ - case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */ - case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to cpu */ - case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to cpu */ - i = SIGBUS; - break; - - case T_SYSCALL+T_USER: - { - register int *locr0 = p->p_md.md_regs; - register struct sysent *callp; - unsigned int code; - int numsys; - struct args { - int i[8]; - } args; - int rval[2]; - - cnt.v_syscall++; - /* compute next PC after syscall instruction */ - if ((int)causeReg < 0) - locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0); - else - locr0[PC] += 4; - callp = p->p_emul->e_sysent; - numsys = p->p_emul->e_nsysent; - code = locr0[V0]; - switch (code) { - case SYS_syscall: - /* - * Code is first argument, followed by actual args. - */ - code = locr0[A0]; - if (code >= numsys) - callp += p->p_emul->e_nosys; /* (illegal) */ - else - callp += code; - i = callp->sy_argsize / sizeof(int); - args.i[0] = locr0[A1]; - args.i[1] = locr0[A2]; - args.i[2] = locr0[A3]; - if (i > 3) { - i = copyin((caddr_t)(locr0[SP] + - 4 * sizeof(int)), - (caddr_t)&args.i[3], - (u_int)(i - 3) * sizeof(int)); - if (i) { - locr0[V0] = i; - locr0[A3] = 1; -#ifdef SYSCALL_DEBUG - scdebug_call(p, code, args.i); -#endif -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, - callp->sy_argsize, - args.i); -#endif - goto done; - } - } - break; - - case SYS___syscall: - /* - * Like syscall, but code is a quad, so as to maintain - * quad alignment for the rest of the arguments. - */ - code = locr0[A0 + _QUAD_LOWWORD]; - if (code >= numsys) - callp += p->p_emul->e_nosys; /* (illegal) */ - else - callp += code; - i = callp->sy_argsize / sizeof(int); - args.i[0] = locr0[A2]; - args.i[1] = locr0[A3]; - if (i > 2) { - i = copyin((caddr_t)(locr0[SP] + - 4 * sizeof(int)), - (caddr_t)&args.i[2], - (u_int)(i - 2) * sizeof(int)); - if (i) { - locr0[V0] = i; - locr0[A3] = 1; -#ifdef SYSCALL_DEBUG - scdebug_call(p, code, args.i); -#endif -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, - callp->sy_argsize, - args.i); -#endif - goto done; - } - } - break; - - default: - if (code >= numsys) - callp += p->p_emul->e_nosys; /* (illegal) */ - else - callp += code; - i = callp->sy_narg; - args.i[0] = locr0[A0]; - args.i[1] = locr0[A1]; - args.i[2] = locr0[A2]; - args.i[3] = locr0[A3]; - if (i > 4) { - i = copyin((caddr_t)(locr0[SP] + - 4 * sizeof(int)), - (caddr_t)&args.i[4], - (u_int)(i - 4) * sizeof(int)); - if (i) { - locr0[V0] = i; - locr0[A3] = 1; -#ifdef SYSCALL_DEBUG - scdebug_call(p, code, args.i); -#endif -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, - callp->sy_argsize, - args.i); -#endif - goto done; - } - } - } -#ifdef SYSCALL_DEBUG - scdebug_call(p, code, args.i); -#endif -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, callp->sy_argsize, args.i); -#endif - rval[0] = 0; - rval[1] = locr0[V1]; -#ifdef DEBUG - if (trp == trapdebug) - trapdebug[TRAPSIZE - 1].code = code; - else - trp[-1].code = code; -#endif - i = (*callp->sy_call)(p, &args, rval); - /* - * Reinitialize proc pointer `p' as it may be different - * if this is a child returning from fork syscall. - */ - p = curproc; - locr0 = p->p_md.md_regs; -#ifdef DEBUG - { int s; - s = splhigh(); - trp->status = statusReg; - trp->cause = causeReg; - trp->vadr = locr0[SP]; - trp->pc = locr0[PC]; - trp->ra = locr0[RA]; - /*trp->sp = (int)&args;*/ /* XXX */ - trp->code = -code; - if (++trp == &trapdebug[TRAPSIZE]) - trp = trapdebug; - splx(s); - } -#endif - switch (i) { - case 0: - locr0[V0] = rval[0]; - locr0[V1] = rval[1]; - locr0[A3] = 0; - break; - - case ERESTART: - locr0[PC] = pc; - break; - - case EJUSTRETURN: - break; /* nothing to do */ - - default: - locr0[V0] = i; - locr0[A3] = 1; - } - - /* - * If we modified code or data, flush caches. - * XXX code unyderling ptrace() and/or proc fs should do this? - */ - if(code == SYS_ptrace) - MachFlushCache(); - done: -#ifdef SYSCALL_DEBUG - scdebug_ret(p, code, i, rval); -#endif -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p->p_tracep, code, i, rval[0]); -#endif - goto out; - } - - case T_BREAK+T_USER: - { - register unsigned va, instr; - struct uio uio; - struct iovec iov; - - /* compute address of break instruction */ - va = pc; - if ((int)causeReg < 0) - va += 4; - - /* read break instruction */ - instr = fuiword((caddr_t)va); -#if 0 - printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n", - p->p_comm, p->p_pid, instr, pc, - p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */ -#endif - if (p->p_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) { - i = SIGTRAP; - break; - } - - /* - * Restore original instruction and clear BP - */ - iov.iov_base = (caddr_t)&p->p_md.md_ss_instr; - iov.iov_len = sizeof(int); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)va; - uio.uio_resid = sizeof(int); - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_WRITE; - uio.uio_procp = curproc; - i = procfs_domem(p, p, NULL, &uio); - MachFlushCache(); - - if (i < 0) - printf("Warning: can't restore instruction at %x: %x\n", - p->p_md.md_ss_addr, p->p_md.md_ss_instr); - - p->p_md.md_ss_addr = 0; - i = SIGTRAP; - break; - } - - case T_RES_INST+T_USER: - i = SIGILL; - break; - - case T_COP_UNUSABLE+T_USER: - if ((causeReg & MIPS_CR_COP_ERR) != 0x10000000) { - i = SIGILL; /* only FPU instructions allowed */ - break; - } - MachSwitchFPState(machFPCurProcPtr, - (struct user*)p->p_md.md_regs); - machFPCurProcPtr = p; - p->p_md.md_regs[PS] |= MIPS_SR_COP_1_BIT; - p->p_md.md_flags |= MDP_FPUSED; - goto out; - - case T_FPE: -#ifdef DEBUG - trapDump("fpintr"); -#else - printf("FPU Trap: PC %x CR %x SR %x\n", - pc, causeReg, statusReg); - goto err; -#endif - - case T_FPE+T_USER: - MachFPTrap(statusReg, causeReg, pc); - goto out; - - case T_OVFLOW+T_USER: - i = SIGFPE; - break; - - case T_ADDR_ERR_LD: /* misaligned access */ - case T_ADDR_ERR_ST: /* misaligned access */ - case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ - if ((i = ((struct pcb *)UADDR)->pcb_onfault) != 0) { - ((struct pcb *)UADDR)->pcb_onfault = 0; - return (onfault_table[i]); - } - /* FALLTHROUGH */ - - default: - err: -#ifdef DEBUG - { - extern struct pcb mdbpcb; - - if (USERMODE(statusReg)) - mdbpcb = p->p_addr->u_pcb; - else { - mdbpcb.pcb_regs[ZERO] = 0; - mdbpcb.pcb_regs[AST] = ((int *)&args)[2]; - mdbpcb.pcb_regs[V0] = ((int *)&args)[3]; - mdbpcb.pcb_regs[V1] = ((int *)&args)[4]; - mdbpcb.pcb_regs[A0] = ((int *)&args)[5]; - mdbpcb.pcb_regs[A1] = ((int *)&args)[6]; - mdbpcb.pcb_regs[A2] = ((int *)&args)[7]; - mdbpcb.pcb_regs[A3] = ((int *)&args)[8]; - mdbpcb.pcb_regs[T0] = ((int *)&args)[9]; - mdbpcb.pcb_regs[T1] = ((int *)&args)[10]; - mdbpcb.pcb_regs[T2] = ((int *)&args)[11]; - mdbpcb.pcb_regs[T3] = ((int *)&args)[12]; - mdbpcb.pcb_regs[T4] = ((int *)&args)[13]; - mdbpcb.pcb_regs[T5] = ((int *)&args)[14]; - mdbpcb.pcb_regs[T6] = ((int *)&args)[15]; - mdbpcb.pcb_regs[T7] = ((int *)&args)[16]; - mdbpcb.pcb_regs[T8] = ((int *)&args)[17]; - mdbpcb.pcb_regs[T9] = ((int *)&args)[18]; - mdbpcb.pcb_regs[RA] = ((int *)&args)[19]; - mdbpcb.pcb_regs[MULLO] = ((int *)&args)[21]; - mdbpcb.pcb_regs[MULHI] = ((int *)&args)[22]; - mdbpcb.pcb_regs[PC] = pc; - mdbpcb.pcb_regs[SR] = statusReg; - bzero((caddr_t)&mdbpcb.pcb_regs[F0], 33 * sizeof(int)); - } - if (mdb(causeReg, vadr, p, !USERMODE(statusReg))) - return (mdbpcb.pcb_regs[PC]); - } -#else -#ifdef DEBUG - stacktrace(); - trapDump("trap"); -#endif -#endif - panic("trap"); - } - p->p_md.md_regs [PC] = pc; - p->p_md.md_regs [CAUSE] = causeReg; - p->p_md.md_regs [BADVADDR] = vadr; - trapsignal(p, i, ucode); -out: - /* - * Note: we should only get here if returning to user mode. - */ - /* take pending signals */ - while ((i = CURSIG(p)) != 0) - postsig(i); - p->p_priority = p->p_usrpri; - astpending = 0; - if (want_resched) { - int s; - - /* - * Since we are curproc, clock will normally just change - * our priority without moving us from one queue to another - * (since the running process is not on a queue.) - * If that happened after we put ourselves on the run queue - * but before we switched, we might not be on the queue - * indicated by our priority. - */ - s = splstatclock(); - setrunqueue(p); - p->p_stats->p_ru.ru_nivcsw++; - mi_switch(); - splx(s); - while ((i = CURSIG(p)) != 0) - postsig(i); - } - - /* - * If profiling, charge system time to the trapped pc. - */ - if (p->p_flag & P_PROFIL) { - extern int psratio; - - addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio); - } - - curpriority = p->p_priority; - return (pc); -} - -/* - * Handle an interrupt. - * Called from MachKernIntr() or MachUserIntr() - * Note: curproc might be NULL. - */ -void -interrupt(statusReg, causeReg, pc, what, args) - unsigned statusReg; /* status register at time of the exception */ - unsigned causeReg; /* cause register at time of exception */ - unsigned pc; /* program counter where to continue */ -{ - register unsigned mask; - register int i; - struct clockframe cf; - -#ifdef DEBUG - trp->status = statusReg; - trp->cause = causeReg; - trp->vadr = 0; - trp->pc = pc; - trp->ra = 0; - trp->sp = (int)&args; - trp->code = 0; - if (++trp == &trapdebug[TRAPSIZE]) - trp = trapdebug; -#endif - - cnt.v_intr++; - mask = causeReg & statusReg; /* pending interrupts & enable mask */ - - splx(pica_hardware_intr(mask, pc, statusReg, causeReg)); - - - if (mask & MIPS_SOFT_INT_MASK_0) { - clearsoftclock(); - cnt.v_soft++; - softclock(); - } - /* - * Process network interrupt if we trapped or will very soon - */ - if ((mask & MIPS_SOFT_INT_MASK_1) || - netisr && (statusReg & MIPS_SOFT_INT_MASK_1)) { - clearsoftnet(); - cnt.v_soft++; - intrcnt[1]++; -#ifdef INET -#include "arp.h" -#if NARP > 0 - if (netisr & (1 << NETISR_ARP)) { - netisr &= ~(1 << NETISR_ARP); - arpintr(); - } -#endif - if (netisr & (1 << NETISR_IP)) { - netisr &= ~(1 << NETISR_IP); - ipintr(); - } -#endif -#ifdef INET6 - if (netisr & (1 << NETISR_IPV6)) { - netisr &= ~(1 << NETISR_IPV6); - ip6intr(); - } -#endif -#ifdef NETATALK - if (netisr & (1 << NETISR_ATALK)) { - netisr &= ~(1 << NETISR_ATALK); - atintr(); - } -#endif -#ifdef NS - if (netisr & (1 << NETISR_NS)) { - netisr &= ~(1 << NETISR_NS); - nsintr(); - } -#endif -#ifdef ISO - if (netisr & (1 << NETISR_ISO)) { - netisr &= ~(1 << NETISR_ISO); - clnlintr(); - } -#endif -#include "ppp.h" -#if NPPP > 0 - if (netisr & (1 << NETISR_PPP)) { - netisr &= ~(1 << NETISR_PPP); - pppintr(); - } -#endif - } - - if (mask & MIPS_SOFT_INT_MASK_0) { - clearsoftclock(); - intrcnt[0]++; - cnt.v_soft++; - softclock(); - } -} - - -/* - * This is called from MachUserIntr() if astpending is set. - * This is very similar to the tail of trap(). - */ -void -softintr(statusReg, pc) - unsigned statusReg; /* status register at time of the exception */ - unsigned pc; /* program counter where to continue */ -{ - register struct proc *p = curproc; - int sig; - - cnt.v_soft++; - /* take pending signals */ - while ((sig = CURSIG(p)) != 0) - postsig(sig); - p->p_priority = p->p_usrpri; - astpending = 0; - if (p->p_flag & P_OWEUPC) { - p->p_flag &= ~P_OWEUPC; - ADDUPROF(p); - } - if (want_resched) { - int s; - - /* - * Since we are curproc, clock will normally just change - * our priority without moving us from one queue to another - * (since the running process is not on a queue.) - * If that happened after we put ourselves on the run queue - * but before we switched, we might not be on the queue - * indicated by our priority. - */ - s = splstatclock(); - setrunqueue(p); - p->p_stats->p_ru.ru_nivcsw++; - mi_switch(); - splx(s); - while ((sig = CURSIG(p)) != 0) - postsig(sig); - } - curpriority = p->p_priority; -} - -#ifdef DEBUG -void -trapDump(msg) - char *msg; -{ - register int i; - int s; - - s = splhigh(); - printf("trapDump(%s)\n", msg); - for (i = 0; i < TRAPSIZE; i++) { - if (trp == trapdebug) - trp = &trapdebug[TRAPSIZE - 1]; - else - trp--; - if (trp->cause == 0) - break; - printf("%s: ADR %x PC %x CR %x SR %x\n", - trap_type[(trp->cause & MIPS_CR_EXC_CODE) >> - MIPS_CR_EXC_CODE_SHIFT], - trp->vadr, trp->pc, trp->cause, trp->status); - printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code); - } - splx(s); -} -#endif - - -/* - * Return the resulting PC as if the branch was executed. - */ -unsigned -MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch) - unsigned *regsPtr; - unsigned instPC; - unsigned fpcCSR; - int allowNonBranch; -{ - InstFmt inst; - unsigned retAddr; - int condition; - -#define GetBranchDest(InstPtr, inst) \ - ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2)) - - - if(allowNonBranch == 0) { - inst = *(InstFmt *)instPC; - } - else { - inst = *(InstFmt *)&allowNonBranch; - } -#if 0 - printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC, - inst.word, fpcCSR); /* XXX */ -#endif - switch ((int)inst.JType.op) { - case OP_SPECIAL: - switch ((int)inst.RType.func) { - case OP_JR: - case OP_JALR: - retAddr = regsPtr[inst.RType.rs]; - break; - - default: - if (!allowNonBranch) - panic("MachEmulateBranch: Non-branch"); - retAddr = instPC + 4; - break; - } - break; - - case OP_BCOND: - switch ((int)inst.IType.rt) { - case OP_BLTZ: - case OP_BLTZL: - case OP_BLTZAL: - case OP_BLTZALL: - if ((int)(regsPtr[inst.RType.rs]) < 0) - retAddr = GetBranchDest(instPC, inst); - else - retAddr = instPC + 8; - break; - - case OP_BGEZ: - case OP_BGEZL: - case OP_BGEZAL: - case OP_BGEZALL: - if ((int)(regsPtr[inst.RType.rs]) >= 0) - retAddr = GetBranchDest(instPC, inst); - else - retAddr = instPC + 8; - break; - - default: - panic("MachEmulateBranch: Bad branch cond"); - } - break; - - case OP_J: - case OP_JAL: - retAddr = (inst.JType.target << 2) | - ((unsigned)instPC & 0xF0000000); - break; - - case OP_BEQ: - case OP_BEQL: - if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt]) - retAddr = GetBranchDest(instPC, inst); - else - retAddr = instPC + 8; - break; - - case OP_BNE: - case OP_BNEL: - if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt]) - retAddr = GetBranchDest(instPC, inst); - else - retAddr = instPC + 8; - break; - - case OP_BLEZ: - case OP_BLEZL: - if ((int)(regsPtr[inst.RType.rs]) <= 0) - retAddr = GetBranchDest(instPC, inst); - else - retAddr = instPC + 8; - break; - - case OP_BGTZ: - case OP_BGTZL: - if ((int)(regsPtr[inst.RType.rs]) > 0) - retAddr = GetBranchDest(instPC, inst); - else - retAddr = instPC + 8; - break; - - case OP_COP1: - switch (inst.RType.rs) { - case OP_BCx: - case OP_BCy: - if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE) - condition = fpcCSR & MIPS_FPU_COND_BIT; - else - condition = !(fpcCSR & MIPS_FPU_COND_BIT); - if (condition) - retAddr = GetBranchDest(instPC, inst); - else - retAddr = instPC + 8; - break; - - default: - if (!allowNonBranch) - panic("MachEmulateBranch: Bad coproc branch instruction"); - retAddr = instPC + 4; - } - break; - - default: - if (!allowNonBranch) - panic("MachEmulateBranch: Non-branch instruction"); - retAddr = instPC + 4; - } -#if 0 - printf("Target addr=%x\n", retAddr); /* XXX */ -#endif - return (retAddr); -} - -/* - * This routine is called by procxmt() to single step one instruction. - * We do this by storing a break instruction after the current instruction, - * resuming execution, and then restoring the old instruction. - */ -int -cpu_singlestep(p) - register struct proc *p; -{ - register unsigned va; - register int *locr0 = p->p_md.md_regs; - int i; - int bpinstr = MIPS_BREAK_SSTEP; - int curinstr; - struct uio uio; - struct iovec iov; - - /* - * Fetch what's at the current location. - */ - iov.iov_base = (caddr_t)&curinstr; - iov.iov_len = sizeof(int); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)locr0[PC]; - uio.uio_resid = sizeof(int); - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_procp = curproc; - procfs_domem(curproc, p, NULL, &uio); - - /* compute next address after current location */ - if(curinstr != 0) { - va = MachEmulateBranch(locr0, locr0[PC], locr0[FSR], curinstr); - } - else { - va = locr0[PC] + 4; - } - if (p->p_md.md_ss_addr) { - printf("SS %s (%d): breakpoint already set at %x (va %x)\n", - p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */ - return (EFAULT); - } - p->p_md.md_ss_addr = va; - - /* - * Fetch what's at the current location. - */ - iov.iov_base = (caddr_t)&p->p_md.md_ss_instr; - iov.iov_len = sizeof(int); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)va; - uio.uio_resid = sizeof(int); - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_procp = curproc; - procfs_domem(curproc, p, NULL, &uio); - - /* - * Store breakpoint instruction at the "next" location now. - */ - iov.iov_base = (caddr_t)&bpinstr; - iov.iov_len = sizeof(int); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)va; - uio.uio_resid = sizeof(int); - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_WRITE; - uio.uio_procp = curproc; - i = procfs_domem(curproc, p, NULL, &uio); - MachFlushCache(); /* XXX memory barrier followed by flush icache? */ - - if (i < 0) - return (EFAULT); -#if 0 - printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n", - p->p_comm, p->p_pid, p->p_md.md_ss_addr, - p->p_md.md_ss_instr, locr0[PC], curinstr); /* XXX */ -#endif - return (0); -} - -#ifdef DEBUG -int -kdbpeek(addr) -{ - if (addr & 3) { - printf("kdbpeek: unaligned address %x\n", addr); - return (-1); - } - return (*(int *)addr); -} -#endif - -#ifdef DEBUG -#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ - -/* forward */ -char *fn_name(unsigned addr); -void stacktrace_subr __P((int, int, int, int, void (*)(const char*, ...))); - -/* - * Print a stack backtrace. - */ -void -stacktrace(a0, a1, a2, a3) - int a0, a1, a2, a3; -{ - stacktrace_subr(a0, a1, a2, a3, printf); -} - -void -logstacktrace(a0, a1, a2, a3) - int a0, a1, a2, a3; -{ - stacktrace_subr(a0, a1, a2, a3, addlog); -} - -void -stacktrace_subr(a0, a1, a2, a3, printfn) - int a0, a1, a2, a3; - void (*printfn) __P((const char*, ...)); -{ - unsigned pc, sp, fp, ra, va, subr; - unsigned instr, mask; - InstFmt i; - int more, stksize; - int regs[3]; - extern char start[], edata[]; - unsigned int frames = 0; - - cpu_getregs(regs); - - /* get initial values from the exception frame */ - sp = regs[0]; - pc = regs[1]; - ra = 0; - fp = regs[2]; - -/* Jump here when done with a frame, to start a new one */ -loop: - ra = 0; - -/* Jump here after a nonstandard (interrupt handler) frame */ -specialframe: - stksize = 0; - subr = 0; - if (frames++ > 100) { - (*printfn)("\nstackframe count exceeded\n"); - /* return breaks stackframe-size heuristics with gcc -O2 */ - goto finish; /*XXX*/ - } - - /* check for bad SP: could foul up next frame */ - if (sp & 3 || sp < 0x80000000) { - (*printfn)("SP 0x%x: not in kernel\n", sp); - ra = 0; - subr = 0; - goto done; - } - -/* - * check for PC between two entry points - */ -# define Between(x, y, z) \ - ( ((x) <= (y)) && ((y) < (z)) ) -# define pcBetween(a,b) \ - Between((unsigned)a, pc, (unsigned)b) - - - /* Backtraces should contine through interrupts from kernel mode */ -#ifdef CPU_R3000 - if (pcBetween(mips_r2000_KernIntr, mips_r2000_UserIntr)) { - /* NOTE: the offsets depend on the code in locore.s */ - (*printfn)("r3000 KernIntr+%x: (%x, %x ,%x) -------\n", - pc-(unsigned)mips_r2000_KernIntr, a0, a1, a2); - a0 = kdbpeek(sp + 36); - a1 = kdbpeek(sp + 40); - a2 = kdbpeek(sp + 44); - a3 = kdbpeek(sp + 48); - - pc = kdbpeek(sp + 20); /* exc_pc - pc at time of exception */ - ra = kdbpeek(sp + 92); /* ra at time of exception */ - sp = sp + 108; - goto specialframe; - } -#endif /* CPU_R3000 */ - -#ifdef CPU_R4000 - if (pcBetween(mips_r4000_KernIntr, mips_r4000_UserIntr)) { - /* NOTE: the offsets depend on the code in locore.s */ - (*printfn)("R4000 KernIntr+%x: (%x, %x ,%x) -------\n", - pc-(unsigned)mips_r4000_KernIntr, a0, a1, a2); - a0 = kdbpeek(sp + 36); - a1 = kdbpeek(sp + 40); - a2 = kdbpeek(sp + 44); - a3 = kdbpeek(sp + 48); - - pc = kdbpeek(sp + 20); /* exc_pc - pc at time of exception */ - ra = kdbpeek(sp + 92); /* ra at time of exception */ - sp = sp + 108; - goto specialframe; - } -#endif /* cpu_r4000 */ - - - - /* - * Check for current PC in exception handler code that don't - * have a preceding "j ra" at the tail of the preceding function. - * Depends on relative ordering of functions in locore. - */ - - /* XXX fixup tests after cutting and pasting in locore.S */ - /* R4000 exception handlers */ - -#ifdef CPU_R2000 - if (pcBetween(mips_r2000_KernGenException, mips_r2000_UserGenException)) - subr = (unsigned) mips_r2000_KernGenException; - else if (pcBetween(mips_r2000_UserGenException,mips_r2000_KernIntr)) - subr = (unsigned) mips_r2000_UserGenException; - else if (pcBetween(mips_r2000_KernIntr, mips_r2000_UserIntr)) - subr = (unsigned) mips_r2000_KernIntr; - else if (pcBetween(mips_r2000_UserIntr, mips_r2000_TLBMissException)) - subr = (unsigned) mips_r2000_UserIntr; - - else if (pcBetween(mips_r2000_UserIntr, mips_r2000_TLBMissException)) - subr = (unsigned) mips_r2000_UserIntr; - else -#endif /* CPU_R2000 */ - - -#ifdef CPU_R4000 - /* R4000 exception handlers */ - if (pcBetween(mips_r4000_KernGenException, mips_r4000_UserGenException)) - subr = (unsigned) mips_r4000_KernGenException; - else if (pcBetween(mips_r4000_UserGenException,mips_r4000_KernIntr)) - subr = (unsigned) mips_r4000_UserGenException; - else if (pcBetween(mips_r4000_KernIntr, mips_r4000_UserIntr)) - subr = (unsigned) mips_r4000_KernIntr; - - - else if (pcBetween(mips_r4000_UserIntr, mips_r4000_TLBMissException)) - subr = (unsigned) mips_r4000_UserIntr; - else -#endif /* CPU_R4000 */ - - - if (pcBetween(splx, wbflush)) - subr = (unsigned) splx; - else if (pcBetween(cpu_switch, fuword)) - subr = (unsigned) cpu_switch; - else if (pcBetween(idle, cpu_switch)) { - subr = (unsigned) idle; - ra = 0; - goto done; - } -#ifdef notyet /* XXX FIXME: the order changed with merged locore */ - else if (pc >= (unsigned)MachUTLBMiss && pc < (unsigned)setsoftclock) { - (*printfn)("<>"); - goto done; - } -#endif /* notyet */ - - /* check for bad PC */ - if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) { - (*printfn)("PC 0x%x: not in kernel space\n", pc); - ra = 0; - goto done; - } - if (!pcBetween(start, (unsigned) edata)) { - (*printfn)("PC 0x%x: not in kernel text\n", pc); - ra = 0; - goto done; - } - - /* - * Find the beginning of the current subroutine by scanning backwards - * from the current PC for the end of the previous subroutine. - */ - if (!subr) { - va = pc - sizeof(int); - while ((instr = kdbpeek(va)) != MIPS_JR_RA) - va -= sizeof(int); - va += 2 * sizeof(int); /* skip back over branch & delay slot */ - /* skip over nulls which might separate .o files */ - while ((instr = kdbpeek(va)) == 0) - va += sizeof(int); - subr = va; - } - - /* - * Jump here for locore entry pointsn for which the preceding - * function doesn't end in "j ra" - */ -#if 0 -stackscan: -#endif - /* scan forwards to find stack size and any saved registers */ - stksize = 0; - more = 3; - mask = 0; - for (va = subr; more; va += sizeof(int), - more = (more == 3) ? 3 : more - 1) { - /* stop if hit our current position */ - if (va >= pc) - break; - instr = kdbpeek(va); - i.word = instr; - switch (i.JType.op) { - case OP_SPECIAL: - switch (i.RType.func) { - case OP_JR: - case OP_JALR: - more = 2; /* stop after next instruction */ - break; - - case OP_SYSCALL: - case OP_BREAK: - more = 1; /* stop now */ - }; - break; - - case OP_BCOND: - case OP_J: - case OP_JAL: - case OP_BEQ: - case OP_BNE: - case OP_BLEZ: - case OP_BGTZ: - more = 2; /* stop after next instruction */ - break; - - case OP_COP0: - case OP_COP1: - case OP_COP2: - case OP_COP3: - switch (i.RType.rs) { - case OP_BCx: - case OP_BCy: - more = 2; /* stop after next instruction */ - }; - break; - - case OP_SW: - /* look for saved registers on the stack */ - if (i.IType.rs != 29) - break; - /* only restore the first one */ - if (mask & (1 << i.IType.rt)) - break; - mask |= (1 << i.IType.rt); - switch (i.IType.rt) { - case 4: /* a0 */ - a0 = kdbpeek(sp + (short)i.IType.imm); - break; - - case 5: /* a1 */ - a1 = kdbpeek(sp + (short)i.IType.imm); - break; - - case 6: /* a2 */ - a2 = kdbpeek(sp + (short)i.IType.imm); - break; - - case 7: /* a3 */ - a3 = kdbpeek(sp + (short)i.IType.imm); - break; - - case 30: /* fp */ - fp = kdbpeek(sp + (short)i.IType.imm); - break; - - case 31: /* ra */ - ra = kdbpeek(sp + (short)i.IType.imm); - } - break; - - case OP_ADDI: - case OP_ADDIU: - /* look for stack pointer adjustment */ - if (i.IType.rs != 29 || i.IType.rt != 29) - break; - stksize = - ((short)i.IType.imm); - } - } - -done: - (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n", - fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize); - - if (ra) { - if (pc == ra && stksize == 0) - (*printfn)("stacktrace: loop!\n"); - else { - pc = ra; - sp += stksize; - ra = 0; - goto loop; - } - } else { -finish: - if (curproc) - (*printfn)("User-level: pid %d\n", curproc->p_pid); - else - (*printfn)("User-level: curproc NULL\n"); - } -} - -/* - * Functions ``special'' enough to print by name - */ -#ifdef __STDC__ -#define Name(_fn) { (void*)_fn, # _fn } -#else -#define Name(_fn) { _fn, "_fn"} -#endif -static struct { void *addr; char *name;} names[] = { - Name(stacktrace), - Name(stacktrace_subr), - Name(main), - Name(interrupt), - Name(trap), -#ifdef pmax - Name(am7990_meminit), -#endif -#ifdef CPU_R3000 - Name(mips_r2000_KernGenException), - Name(mips_r2000_UserGenException), - Name(mips_r2000_KernIntr), - Name(mips_r2000_UserIntr), -#endif /* CPU_R3000 */ - -#ifdef CPU_R4000 - Name(mips_r4000_KernGenException), - Name(mips_r4000_UserGenException), - Name(mips_r4000_KernIntr), - Name(mips_r4000_UserIntr), -#endif /* CPU_R4000 */ - - Name(splx), - Name(idle), - Name(cpu_switch), - {0, 0} -}; - -/* - * Map a function address to a string name, if known; or a hex string. - */ -char * -fn_name(unsigned addr) -{ - static char buf[17]; - int i = 0; - - for (i = 0; names[i].name; i++) - if (names[i].addr == (void*)addr) - return (names[i].name); - sprintf(buf, "%x", addr); - return (buf); -} - -#endif /* DEBUG */ diff --git a/sys/arch/arc/arc/vm_machdep.c b/sys/arch/arc/arc/vm_machdep.c deleted file mode 100644 index b9a989250cc4..000000000000 --- a/sys/arch/arc/arc/vm_machdep.c +++ /dev/null @@ -1,468 +0,0 @@ -/* $NetBSD: vm_machdep.c,v 1.9 2000/01/23 20:09:21 soda Exp $ */ - -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department 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. - * - * from: Utah Hdr: vm_machdep.c 1.21 91/04/06 - * - * from: @(#)vm_machdep.c 8.3 (Berkeley) 1/4/94 - */ - - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#if 0 -#include -#endif - -#include -#include - -vm_offset_t kmem_alloc_wait_align(); - -/* - * Finish a fork operation, with process p2 nearly set up. - * Copy and update the kernel stack and pcb, making the child - * ready to run, and marking it so that it can return differently - * than the parent. Returns 1 in the child process, 0 in the parent. - * We currently double-map the user area so that the stack is at the same - * address in each process; in the future we will probably relocate - * the frame pointers on the stack after copying. - */ -cpu_fork(p1, p2) - register struct proc *p1, *p2; -{ - register struct user *up = p2->p_addr; - register pt_entry_t *pte; - register int i; - extern struct proc *machFPCurProcPtr; - - p2->p_md.md_regs = up->u_pcb.pcb_regs; - p2->p_md.md_flags = p1->p_md.md_flags & MDP_FPUSED; - - /* - * Cache the PTEs for the user area in the machine dependent - * part of the proc struct so cpu_switch() can quickly map in - * the user struct and kernel stack. Note: if the virtual address - * translation changes (e.g. swapout) we have to update this. - */ - pte = kvtopte(up); - for (i = 0; i < UPAGES; i++) { - p2->p_md.md_upte[i] = pte->pt_entry & ~(PG_G | PG_RO | PG_WIRED); - pte++; - } - - /* - * Copy floating point state from the FP chip if this process - * has state stored there. - */ - if (p1 == machFPCurProcPtr) - MachSaveCurFPState(p1); - - /* - * Copy pcb and stack from proc p1 to p2. - * We do this as cheaply as possible, copying only the active - * part of the stack. The stack and pcb need to agree; - */ - p2->p_addr->u_pcb = p1->p_addr->u_pcb; - /* cache segtab for ULTBMiss() */ - p2->p_addr->u_pcb.pcb_segtab = (void *)p2->p_vmspace->vm_pmap.pm_segtab; - - /* - * Arrange for a non-local goto when the new process - * is started, to resume here, returning nonzero from setjmp. - */ -#ifdef DIAGNOSTIC - if (p1 != curproc && p1 != &proc0) - panic("cpu_fork: curproc"); -#endif - if (copykstack(up)) { - /* - * Return 1 in child. - */ - return (1); - } - return (0); -} - -/* - * Finish a swapin operation. - * We neded to update the cached PTEs for the user area in the - * machine dependent part of the proc structure. - */ -void -cpu_swapin(p) - register struct proc *p; -{ - register struct user *up = p->p_addr; - register pt_entry_t *pte; - register int i; - - /* - * Cache the PTEs for the user area in the machine dependent - * part of the proc struct so cpu_switch() can quickly map in - * the user struct and kernel stack. - */ - pte = kvtopte(up); - for (i = 0; i < UPAGES; i++) { - p->p_md.md_upte[i] = pte->pt_entry & ~(PG_G | PG_RO | PG_WIRED); - pte++; - } -} - -/* - * cpu_exit is called as the last action during exit. - * We release the address space and machine-dependent resources, - * including the memory for the user structure and kernel stack. - * Once finished, we call switch_exit, which switches to a temporary - * pcb and stack and never returns. We block memory allocation - * until switch_exit has made things safe again. - */ -void cpu_exit(p) - struct proc *p; -{ - extern struct proc *machFPCurProcPtr; - - if (machFPCurProcPtr == p) - machFPCurProcPtr = (struct proc *)0; - - vmspace_free(p->p_vmspace); - - (void) splhigh(); - kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES)); - switch_exit(); - /* NOTREACHED */ -} - -/* - * Dump the machine specific header information at the start of a core dump. - */ -cpu_coredump(p, vp, cred) - struct proc *p; - struct vnode *vp; - struct ucred *cred; -{ - extern struct proc *machFPCurProcPtr; - - /* - * Copy floating point state from the FP chip if this process - * has state stored there. - */ - if (p == machFPCurProcPtr) - MachSaveCurFPState(p); - - return (vn_rdwr(UIO_WRITE, vp, (caddr_t)p->p_addr, ctob(UPAGES), - (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, - p)); -} - -/* - * Move pages from one kernel virtual address to another. - * Both addresses are assumed to reside in the Sysmap, - * and size must be a multiple of CLSIZE. - */ -pagemove(from, to, size) - register caddr_t from, to; - int size; -{ - register pt_entry_t *fpte, *tpte; - - if (size % NBPG) - panic("pagemove"); - fpte = kvtopte(from); - tpte = kvtopte(to); - if(((int)from & machCacheAliasMask) != ((int)to & machCacheAliasMask)) { - MachHitFlushDCache(from, size); - } - while (size > 0) { - MachTLBFlushAddr(from); - MachTLBUpdate(to, *fpte); - *tpte++ = *fpte; - fpte->pt_entry = PG_NV | PG_G; - fpte++; - size -= NBPG; - from += NBPG; - to += NBPG; - } -} - -extern vm_map_t phys_map; - -/* - * Map a user I/O request into kernel virtual address space. - * Note: the pages are already locked by uvm_vslock(), so we - * do not need to pass an access_type to pmap_enter(). - */ -vmapbuf(bp) - register struct buf *bp; -{ - register caddr_t addr; - register vm_size_t sz; - struct proc *p; - int off; - vm_offset_t kva; - register vm_offset_t pa; - - if ((bp->b_flags & B_PHYS) == 0) - panic("vmapbuf"); - addr = bp->b_saveaddr = bp->b_un.b_addr; - off = (int)addr & PGOFSET; - p = bp->b_proc; - sz = round_page(bp->b_bcount + off); - kva = kmem_alloc_wait_align(phys_map, sz, (vm_size_t)addr & machCacheAliasMask); - bp->b_un.b_addr = (caddr_t) (kva + off); - sz = atop(sz); - while (sz--) { - pa = pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map), - (vm_offset_t)addr); - if (pa == 0) - panic("vmapbuf: null page frame"); - pmap_enter(vm_map_pmap(phys_map), kva, trunc_page(pa), - VM_PROT_READ|VM_PROT_WRITE, TRUE, 0); - addr += PAGE_SIZE; - kva += PAGE_SIZE; - } -} - -/* - * Unmap a previously-mapped user I/O request. - */ -vunmapbuf(bp) - register struct buf *bp; -{ - register caddr_t addr = bp->b_un.b_addr; - register vm_size_t sz; - vm_offset_t kva; - - if ((bp->b_flags & B_PHYS) == 0) - panic("vunmapbuf"); - sz = round_page(bp->b_bcount + ((int)addr & PGOFSET)); - kva = (vm_offset_t)((int)addr & ~PGOFSET); - kmem_free_wakeup(phys_map, kva, sz); - bp->b_un.b_addr = bp->b_saveaddr; - bp->b_saveaddr = NULL; -} - - -/* - * SAVE_HINT: - * - * Saves the specified entry as the hint for - * future lookups. Performs necessary interlocks. - */ -#define SAVE_HINT(map,value) \ - simple_lock(&(map)->hint_lock); \ - (map)->hint = (value); \ - simple_unlock(&(map)->hint_lock); - - -/* - * kmem_alloc_upage: - * - * Allocate pageable memory to the kernel's address map. - * map must be "kernel_map" below. - * (Currently only used when allocating U pages). - */ -vm_offset_t -kmem_alloc_upage(map, size) - vm_map_t map; - register vm_size_t size; -{ - vm_offset_t addr; - register int result; - - - size = round_page(size); - - addr = vm_map_min(map); - result = vm_map_find_U(map, NULL, (vm_offset_t) 0, - &addr, size, TRUE); - if (result != KERN_SUCCESS) { - return(0); - } - - return(addr); -} - -/* - * vm_map_find finds an unallocated region in the target address - * map with the given length aligned on U viritual address. - * The search is defined to be first-fit from the specified address; - * the region found is returned in the same parameter. - * - */ -int -vm_map_find_U(map, object, offset, addr, length, find_space) - vm_map_t map; - vm_object_t object; - vm_offset_t offset; - vm_offset_t *addr; /* IN/OUT */ - vm_size_t length; - boolean_t find_space; -{ - register vm_offset_t start; - int result; - - start = *addr; - vm_map_lock(map); - if (find_space) { - if (vm_map_findspace_align(map, start, length, addr, 0)) { - vm_map_unlock(map); - return (KERN_NO_SPACE); - } - start = *addr; - } - result = vm_map_insert(map, object, offset, start, start + length); - vm_map_unlock(map); - return (result); -} - -/* - * Find sufficient space for `length' bytes in the given map, starting at - * `start'. The map must be locked. Returns 0 on success, 1 on no space. - */ -int -vm_map_findspace_align(map, start, length, addr, align) - register vm_map_t map; - register vm_offset_t start; - vm_size_t length; - vm_offset_t *addr; - vm_size_t align; -{ - register vm_map_entry_t entry, next; - register vm_offset_t end; - - if (start < map->min_offset) - start = map->min_offset; - if (start > map->max_offset) - return (1); - - /* - * Look for the first possible address; if there's already - * something at this address, we have to start after it. - */ - if (start == map->min_offset) { - if ((entry = map->first_free) != &map->header) - start = entry->end; - } else { - vm_map_entry_t tmp; - if (vm_map_lookup_entry(map, start, &tmp)) - start = tmp->end; - entry = tmp; - } - - /* - * Look through the rest of the map, trying to fit a new region in - * the gap between existing regions, or after the very last region. - */ - for (;; start = (entry = next)->end) { - /* - * Find the end of the proposed new region. Be sure we didn't - * go beyond the end of the map, or wrap around the address; - * if so, we lose. Otherwise, if this is the last entry, or - * if the proposed new region fits before the next entry, we - * win. - */ - start = ((start + NBPG -1) & ~(NBPG - 1)); /* Paranoia */ - if((start & machCacheAliasMask) <= align) { - start += align - (start & machCacheAliasMask); - } - else { - start = ((start + machCacheAliasMask) & ~machCacheAliasMask); - start += align; - } - - end = start + length; - if (end > map->max_offset || end < start) - return (1); - next = entry->next; - if (next == &map->header || next->start >= end) - break; - } - SAVE_HINT(map, entry); - *addr = start; - return (0); -} - -/* - * kmem_alloc_wait_align - * - * Allocates pageable memory from a sub-map of the kernel. If the submap - * has no room, the caller sleeps waiting for more memory in the submap. - * - */ -vm_offset_t -kmem_alloc_wait_align(map, size, align) - vm_map_t map; - vm_size_t size; - vm_size_t align; -{ - vm_offset_t addr; - - size = round_page(size); - - for (;;) { - /* - * To make this work for more than one map, - * use the map's lock to lock out sleepers/wakers. - */ - vm_map_lock(map); - if (vm_map_findspace_align(map, 0, size, &addr, align) == 0) - break; - /* no space now; see if we can ever get space */ - if (vm_map_max(map) - vm_map_min(map) < size) { - vm_map_unlock(map); - return (0); - } - assert_wait(map, TRUE); - vm_map_unlock(map); - thread_block(); - } - vm_map_insert(map, NULL, (vm_offset_t)0, addr, addr + size); - vm_map_unlock(map); - return (addr); -} diff --git a/sys/arch/arc/compile/.cvsignore b/sys/arch/arc/compile/.cvsignore deleted file mode 100644 index 4c3e9acdf39b..000000000000 --- a/sys/arch/arc/compile/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -ARCTIC -GENERIC -P4032 -PICA -RAMDISK diff --git a/sys/arch/arc/conf/ld.script b/sys/arch/arc/conf/ld.script deleted file mode 100644 index 3c59f13f80b9..000000000000 --- a/sys/arch/arc/conf/ld.script +++ /dev/null @@ -1,74 +0,0 @@ -OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips", - "elf32-littlemips") -OUTPUT_ARCH(mips) -ENTRY(_start) -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x80100000 + SIZEOF_HEADERS; - .text : - { - _ftext = . ; - *(.text) - *(.rodata) - *(.rodata1) - *(.reginfo) - *(.init) - *(.stub) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } =0 - _etext = .; - PROVIDE (etext = .); - .fini : { *(.fini) } =0 - .data : - { - _fdata = . ; - *(.data) - CONSTRUCTORS - } - .data1 : { *(.data1) } - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - _gp = ALIGN(16) + 0x7ff0; - .got : - { - *(.got.plt) *(.got) - } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - _fbss = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); - /* These are needed for ELF backends which have not yet been - converted to the new style linker. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - /* DWARF debug sections. - Symbols in the .debug DWARF section are relative to the beginning of the - section so we begin .debug at 0. It's not clear yet what needs to happen - for the others. */ - .debug 0 : { *(.debug) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .line 0 : { *(.line) } - /* These must appear regardless of . */ - .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } - .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -} diff --git a/sys/arch/arc/include/dlfcn.h b/sys/arch/arc/include/dlfcn.h deleted file mode 100644 index 33ebe265ddc9..000000000000 --- a/sys/arch/arc/include/dlfcn.h +++ /dev/null @@ -1,42 +0,0 @@ -/* $OpenBSD: dlfcn.h,v 1.1 1996/10/06 19:59:57 pefo Exp $ */ - -/* - * Copyright (c) 1996 Per Fogelstrom - * - * 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 under OpenBSD by - * Per Fogelstrom. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - */ - -#ifndef _DLFCN_H -#define _DLFCN_H 1 - -/* - * This is a dummy file. Empty until libdl has been done. - */ - -#endif /* _DLFCN_H */ diff --git a/sys/arch/arc/include/ecoff.h b/sys/arch/arc/include/ecoff.h deleted file mode 100644 index 1013f4bd2d6c..000000000000 --- a/sys/arch/arc/include/ecoff.h +++ /dev/null @@ -1,94 +0,0 @@ -/* $OpenBSD: ecoff.h,v 1.3 1996/10/02 21:47:53 pefo Exp $ */ -/* $NetBSD: ecoff.h,v 1.1.1.1 2000/01/23 20:24:28 soda Exp $ */ - -/* - * Copyright (c) 1994 Adam Glass - * All rights reserved. - * - * 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 Adam Glass. - * 4. The name of the Author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Adam Glass ``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 Adam Glass 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. - */ - -#define ECOFF_LDPGSZ 4096 - -#define ECOFF_PAD - -#define ECOFF_MACHDEP \ - u_long ea_gprmask; \ - u_long ea_cprmask[4]; \ - u_long ea_gp_value - -#define ECOFF_MAGIC_MIPSEL 0x0162 -#define ECOFF_BADMAG(ex) ((ex)->f.f_magic != ECOFF_MAGIC_MIPSEL) - -#define ECOFF_SEGMENT_ALIGNMENT(ep) ((ep)->a.vstamp < 23 ? 8 : 16) - -struct ecoff_symhdr { - int16_t sh_magic; - int16_t sh_vstamp; - int32_t sh_linemax; - int32_t sh_densenummax; - int32_t sh_procmax; - int32_t sh_lsymmax; - int32_t sh_optsymmax; - int32_t sh_auxxymmax; - int32_t sh_lstrmax; - int32_t sh_estrmax; - int32_t sh_fdmax; - int32_t sh_rfdmax; - int32_t sh_esymmax; - long sh_linesize; - long sh_lineoff; - long sh_densenumoff; - long sh_procoff; - long sh_lsymoff; - long sh_optsymoff; - long sh_auxsymoff; - long sh_lstroff; - long sh_estroff; - long sh_fdoff; - long sh_rfdoff; - long sh_esymoff; -}; -/* Some day they will make up their minds.... */ -#define esymMax sh_esymmax -#define cbExtOffset sh_esymoff -#define cbSsExtOffset sh_estroff - -struct ecoff_extsym { - long es_value; - int es_strindex; - unsigned es_type:6; - unsigned es_class:5; - unsigned :1; - unsigned es_symauxindex:20; - unsigned es_jmptbl:1; - unsigned es_cmain:1; - unsigned es_weakext:1; - unsigned :29; - int es_indexfld; -}; - diff --git a/sys/arch/arc/include/elf_abi.h b/sys/arch/arc/include/elf_abi.h deleted file mode 100644 index 4290c15563a1..000000000000 --- a/sys/arch/arc/include/elf_abi.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $OpenBSD: elf_abi.h,v 1.2 1996/12/11 05:55:34 imp Exp $ */ - -/* - * Copyright (c) 1996 Per Fogelstrom - * - * 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 under OpenBSD by - * Per Fogelstrom. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - */ - -/* From MIPS ABI supplemental */ - -/* Architecture dependent Segment types - p_type */ -#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ - -/* Architecture dependent d_tag field for Elf32_Dyn. */ -#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime Linker Interface ID */ -#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ -#define DT_MIPS_ICHECKSUM 0x70000003 /* Cksum of ext. str. and com. sizes */ -#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ -#define DT_MIPS_FLAGS 0x70000005 /* Flags */ -#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Segment base address */ -#define DT_MIPS_CONFLICT 0x70000008 /* Adr of .conflict section */ -#define DT_MIPS_LIBLIST 0x70000009 /* Address of .liblist section */ -#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local .GOT entries */ -#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of .conflict entries */ -#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of .liblist entries */ -#define DT_MIPS_SYMTABNO 0x70000011 /* Number of .dynsym entries */ -#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ -#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in .dynsym */ -#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ -#define DT_MIPS_RLD_MAP 0x70000016 /* Address of debug map pointer */ - -#define DT_PROCNUM (DT_MIPS_HIPAGENO - DT_LOPROC + 1) diff --git a/sys/arch/arc/include/exec.h b/sys/arch/arc/include/exec.h deleted file mode 100644 index 3b14e8294114..000000000000 --- a/sys/arch/arc/include/exec.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $OpenBSD: exec.h,v 1.2 1996/12/23 02:42:26 deraadt Exp $ */ -/* $NetBSD: exec.h,v 1.1.1.1 2000/01/23 20:24:28 soda Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * 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. - * - * @(#)exec.h 8.1 (Berkeley) 6/10/93 - */ - -#define __LDPGSZ 4096 - -/* - * Define what exec "formats" we should handle. - */ -#define NATIVE_EXEC_ELF -#define EXEC_SCRIPT - -#define ELF_TARG_CLASS ELFCLASS32 -#define ELF_TARG_DATA ELFDATA2LSB -#define ELF_TARG_MACH EM_MIPS - -#define _NLIST_DO_AOUT -#define _NLIST_DO_ELF -#define _NLIST_DO_ECOFF - -#define _KERN_DO_ECOFF -#define _KERN_DO_ELF diff --git a/sys/arch/arc/include/frame.h b/sys/arch/arc/include/frame.h deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/sys/arch/arc/include/link.h b/sys/arch/arc/include/link.h deleted file mode 100644 index 39e137ff1914..000000000000 --- a/sys/arch/arc/include/link.h +++ /dev/null @@ -1,125 +0,0 @@ -/* $OpenBSD: link.h,v 1.2 1996/12/11 05:55:35 imp Exp $ */ - -/* - * Copyright (c) 1996 Per Fogelstrom - * - * 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 under OpenBSD by - * Per Fogelstrom. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - */ - -#ifndef _LINK_H -#define _LINK_H 1 - -#include -#include - -/* - * Debug rendezvous struct. Pointer to this is set up in the - * target code pointed by the DT_MIPS_RLD_MAP tag. If it is - * defined. - */ - -struct r_debug { - int r_version; /* Protocol version. */ - struct link_map *r_map; /* Head of list of loaded objects. */ - - /* This is the address of a function internal to the run-time linker, - that will always be called when the linker begins to map in a - library or unmap it, and again when the mapping change is complete. - The debugger can set a breakpoint at this address if it wants to - notice shared object mapping changes. */ - Elf32_Addr r_brk; - enum { - /* This state value describes the mapping change taking place when - the `r_brk' address is called. */ - RT_CONSISTENT, /* Mapping change is complete. */ - RT_ADD, /* Adding a new object. */ - RT_DELETE, /* Removing an object mapping. */ - } r_state; - - Elf32_Addr r_ldbase; /* Base address the linker is loaded at. */ - }; - -/* This symbol refers to the "dynamic structure" in the `.dynamic' section - of whatever module refers to `_DYNAMIC'. So, to find its own - `struct r_debug', a program could do: - for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL) - if (dyn->d_tag == DT_MIPS_RLD_MAP) r_debug = (struct r_debug) dyn->d_un.d_ptr; - */ - -extern Elf32_Dyn _DYNAMIC[]; - - -/* Structure describing a loaded shared object. The `l_next' and `l_prev' - members form a chain of all the shared objects loaded at startup. - - These data structures exist in space used by the run-time dynamic linker; - modifying them may have disastrous results. */ - -struct link_map - { - /* These first few members are part of the protocol with the debugger. - This is the same format used in SVR4. */ - - Elf32_Addr l_addr; /* Base address shared object is loaded at. */ - Elf32_Addr l_offs; /* Offset */ - char *l_name; /* Absolute file name object was found in. */ - Elf32_Dyn *l_ld; /* Dynamic section of the shared object. */ - struct link_map *l_next, *l_prev; /* Chain of loaded objects. */ - - /* All following members are internal to the dynamic linker. - They may change without notice. */ - - const char *l_libname; /* Name requested (before search). */ - - /* Indexed pointers to dynamic section. */ - Elf32_Dyn *l_info[DT_NUM + DT_PROCNUM]; - - const Elf32_Phdr *l_phdr; /* Pointer to program header table in core. */ - Elf32_Word l_phnum; /* Number of program header entries. */ - Elf32_Addr l_entry; /* Entry point location. */ - - /* Symbol hash table. */ - Elf32_Word l_nbuckets; - const Elf32_Word *l_buckets, *l_chain; - - unsigned int l_opencount; /* Reference count for dlopen/dlclose. */ - enum /* Where this object came from. */ - { - lt_executable, /* The main executable program. */ - lt_interpreter, /* The interpreter: the dynamic linker. */ - lt_library, /* Library needed by main executable. */ - lt_loaded, /* Extra run-time loaded shared object. */ - } l_type:2; - unsigned int l_deps_loaded:1; /* Nonzero if DT_NEEDED items loaded. */ - unsigned int l_relocated:1; /* Nonzero if object's relocations done. */ - unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */ - unsigned int l_init_running:1; /* Nonzero while DT_INIT function runs. */ - }; - -#endif /* _LINK_H */ diff --git a/sys/arch/arc/include/memconf.h b/sys/arch/arc/include/memconf.h deleted file mode 100644 index 3064c1a04cd1..000000000000 --- a/sys/arch/arc/include/memconf.h +++ /dev/null @@ -1,50 +0,0 @@ -/* $OpenBSD: memconf.h,v 1.2 1996/09/14 15:58:26 pefo Exp $ */ - -/* - * Copyright (c) 1996 Per Fogelstrom - * All rights reserved. - * - * 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 Per Fogelstrom. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -/* - * Memory config list used by pmap_bootstrap. - */ - -#ifndef _MEMCONF_H_ -#define _MEMCONF_H_ - -struct mem_descriptor { - vm_offset_t mem_start; - u_int mem_size; -}; - -#ifdef _KERNEL -#define MAXMEMSEGS 16 -extern struct mem_descriptor mem_layout[]; -#endif - -#endif