diff options
Diffstat (limited to 'sys/arch')
31 files changed, 80 insertions, 6809 deletions
diff --git a/sys/arch/luna88k/conf/GENERIC b/sys/arch/luna88k/conf/GENERIC index 6be78a4d132..d0baea0be60 100644 --- a/sys/arch/luna88k/conf/GENERIC +++ b/sys/arch/luna88k/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.2 2004/04/26 12:34:02 miod Exp $ +# $OpenBSD: GENERIC,v 1.3 2004/04/29 14:33:24 miod Exp $ machine luna88k m88k @@ -8,6 +8,9 @@ option "NCPUS=1" # number of CPUs supported (max 4) #option DEBUG # print debugging statements #option EH_DEBUG # debugging code for exception handlers +# Processor type +option M88100 # 88100 support; mandatory + # Define this if your processor has the xxx.usr bug (mask C82N) option ERRATA__XXX_USR diff --git a/sys/arch/luna88k/conf/Makefile.luna88k b/sys/arch/luna88k/conf/Makefile.luna88k index 9c67c8fca69..992cc4979e7 100644 --- a/sys/arch/luna88k/conf/Makefile.luna88k +++ b/sys/arch/luna88k/conf/Makefile.luna88k @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.luna88k,v 1.1 2004/04/21 15:23:47 aoyama Exp $ +# $OpenBSD: Makefile.luna88k,v 1.2 2004/04/29 14:33:24 miod Exp $ # # Makefile for OpenBSD # @@ -32,6 +32,7 @@ STRIP?= strip S!= cd ../../../..; pwd .endif LUNA88K= $S/arch/luna88k +M88K= $S/arch/m88k INCLUDES= -nostdinc -I. -I$S/arch -I$S CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dluna88k -Dm88k @@ -52,10 +53,6 @@ HOSTCC?= ${CC} HOSTED_CPPFLAGS?=${CPPFLAGS:S/^-nostdinc$//} HOSTED_CFLAGS?= ${CFLAGS} -### CPU configuration - -CPPFLAGS+= -DM88100 - ### find out what to use for libkern .include "$S/lib/libkern/Makefile.inc" .ifndef PROF @@ -119,9 +116,9 @@ LINKFLAGS+= -x %LOAD -assym.h: $S/kern/genassym.sh ${LUNA88K}/luna88k/genassym.cf Makefile +assym.h: $S/kern/genassym.sh ${M88K}/m88k/genassym.cf Makefile sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} \ - ${PARAM} < ${LUNA88K}/luna88k/genassym.cf > assym.h.tmp && \ + ${PARAM} < ${M88K}/m88k/genassym.cf > assym.h.tmp && \ mv -f assym.h.tmp assym.h param.c: $S/conf/param.c diff --git a/sys/arch/luna88k/conf/RAMDISK b/sys/arch/luna88k/conf/RAMDISK index d579558fd61..e066edb7d52 100644 --- a/sys/arch/luna88k/conf/RAMDISK +++ b/sys/arch/luna88k/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.2 2004/04/26 12:34:02 miod Exp $ +# $OpenBSD: RAMDISK,v 1.3 2004/04/29 14:33:24 miod Exp $ machine luna88k m88k @@ -8,6 +8,9 @@ option RAMDISK_HOOKS option "NCPUS=1" # number of CPUs supported (max 4) +# Processor type +option M88100 # 88100 support; mandatory + # Define this if your processor has the xxx.usr bug (mask C82N) option ERRATA__XXX_USR diff --git a/sys/arch/luna88k/conf/files.luna88k b/sys/arch/luna88k/conf/files.luna88k index b60d9268090..3b2c8d3547b 100644 --- a/sys/arch/luna88k/conf/files.luna88k +++ b/sys/arch/luna88k/conf/files.luna88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.luna88k,v 1.1 2004/04/21 15:23:47 aoyama Exp $ +# $OpenBSD: files.luna88k,v 1.2 2004/04/29 14:33:24 miod Exp $ # maxpartitions 16 @@ -76,23 +76,16 @@ file arch/luna88k/luna88k/clock.c file arch/luna88k/luna88k/autoconf.c file arch/luna88k/luna88k/conf.c -file arch/luna88k/luna88k/cmmu.c file arch/luna88k/luna88k/m8820x.c file arch/luna88k/luna88k/disksubr.c #file arch/luna88k/luna88k/dkbad.c file arch/luna88k/luna88k/eh.S file arch/luna88k/luna88k/isr.c -file arch/luna88k/luna88k/locore_asm_routines.S file arch/luna88k/luna88k/locore_c_routines.c -file arch/luna88k/luna88k/m88100_fp.S file arch/luna88k/luna88k/machdep.c file arch/luna88k/luna88k/mem.c file arch/luna88k/luna88k/pmap.c file arch/luna88k/luna88k/pmap_table.c -file arch/luna88k/luna88k/process.S -file arch/luna88k/luna88k/process_machdep.c -file arch/luna88k/luna88k/trap.c -file arch/luna88k/luna88k/vectors_88100.S file arch/luna88k/luna88k/vm_machdep.c file arch/luna88k/ddb/db_disasm.c ddb file arch/luna88k/ddb/db_interface.c ddb diff --git a/sys/arch/luna88k/luna88k/cmmu.c b/sys/arch/luna88k/luna88k/cmmu.c deleted file mode 100644 index 375a8241e99..00000000000 --- a/sys/arch/luna88k/luna88k/cmmu.c +++ /dev/null @@ -1,78 +0,0 @@ -/* $OpenBSD: cmmu.c,v 1.1 2004/04/21 15:23:58 aoyama Exp $ */ -/* - * Copyright (c) 1998 Steve Murphree, Jr. - * Copyright (c) 1996 Nivas Madhur - * 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 Nivas Madhur. - * 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. - * - */ -/* - * Mach Operating System - * Copyright (c) 1993-1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/simplelock.h> -#include <machine/cmmu.h> -#include <machine/cpu_number.h> - -/* - * This lock protects the cmmu SAR and SCR's; other ports - * can be accessed without locking it. - * - * May be used from "db_interface.c". - */ -struct simplelock cmmu_cpu_lock; - -unsigned cpu_sets[MAX_CPUS]; -unsigned master_cpu = 0; -int max_cpus, max_cmmus; - -struct cmmu_p *cmmu; diff --git a/sys/arch/luna88k/luna88k/genassym.cf b/sys/arch/luna88k/luna88k/genassym.cf deleted file mode 100644 index dfe4af42192..00000000000 --- a/sys/arch/luna88k/luna88k/genassym.cf +++ /dev/null @@ -1,144 +0,0 @@ -# $OpenBSD: genassym.cf,v 1.1 2004/04/21 15:24:00 aoyama Exp $ -# -# Copyright (c) 1982, 1990 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. 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. -# -# @(#)genassym.c 7.8 (Berkeley) 5/7/91 -# $Id: genassym.cf,v 1.1 2004/04/21 15:24:00 aoyama Exp $ -# - -include <sys/param.h> -include <sys/buf.h> -include <sys/time.h> -include <sys/proc.h> -include <sys/mbuf.h> -include <sys/msgbuf.h> -include <machine/cpu.h> -include <machine/trap.h> -include <machine/psl.h> -include <machine/vmparam.h> -include <sys/syscall.h> -include <sys/user.h> - -# proc fields and values -struct proc -member p_forw -member p_back -member p_addr -member p_stat -member p_wchan - -export SRUN - -# general constants -export UPAGES -define USIZE USPACE - -# pcb fields -struct pcb -member pcb_onfault -member PCB_USER_STATE user_state - -# system calls -export SYS_exit -export SYS_sigreturn - -# trapframe element indexes -define EF_R0 offsetof(struct trapframe, tf_r[0]) / sizeof(int) -define EF_FPSR offsetof(struct trapframe, tf_fpsr) / sizeof(int) -define EF_FPCR offsetof(struct trapframe, tf_fpcr) / sizeof(int) -define EF_EPSR offsetof(struct trapframe, tf_epsr) / sizeof(int) -define EF_SXIP offsetof(struct trapframe, tf_sxip) / sizeof(int) -define EF_SFIP offsetof(struct trapframe, tf_sfip) / sizeof(int) -define EF_SNIP offsetof(struct trapframe, tf_snip) / sizeof(int) -define EF_SSBR offsetof(struct trapframe, tf_ssbr) / sizeof(int) -define EF_DMT0 offsetof(struct trapframe, tf_dmt0) / sizeof(int) -define EF_DMD0 offsetof(struct trapframe, tf_dmd0) / sizeof(int) -define EF_DMA0 offsetof(struct trapframe, tf_dma0) / sizeof(int) -define EF_DMT1 offsetof(struct trapframe, tf_dmt1) / sizeof(int) -define EF_DMD1 offsetof(struct trapframe, tf_dmd1) / sizeof(int) -define EF_DMA1 offsetof(struct trapframe, tf_dma1) / sizeof(int) -define EF_DMT2 offsetof(struct trapframe, tf_dmt2) / sizeof(int) -define EF_DMD2 offsetof(struct trapframe, tf_dmd2) / sizeof(int) -define EF_DMA2 offsetof(struct trapframe, tf_dma2) / sizeof(int) -define EF_FPECR offsetof(struct trapframe, tf_fpecr) / sizeof(int) -define EF_FPHS1 offsetof(struct trapframe, tf_fphs1) / sizeof(int) -define EF_FPLS1 offsetof(struct trapframe, tf_fpls1) / sizeof(int) -define EF_FPHS2 offsetof(struct trapframe, tf_fphs2) / sizeof(int) -define EF_FPLS2 offsetof(struct trapframe, tf_fpls2) / sizeof(int) -define EF_FPPT offsetof(struct trapframe, tf_fppt) / sizeof(int) -define EF_FPRH offsetof(struct trapframe, tf_fprh) / sizeof(int) -define EF_FPRL offsetof(struct trapframe, tf_fprl) / sizeof(int) -define EF_FPIT offsetof(struct trapframe, tf_fpit) / sizeof(int) -define EF_VECTOR offsetof(struct trapframe, tf_vector) / sizeof(int) -define EF_MASK offsetof(struct trapframe, tf_mask) / sizeof(int) -define EF_MODE offsetof(struct trapframe, tf_mode) / sizeof(int) -define EF_RET offsetof(struct trapframe, tf_scratch1) / sizeof(int) -define EF_IPFSR offsetof(struct trapframe, tf_ipfsr) / sizeof(int) -define EF_DPFSR offsetof(struct trapframe, tf_dpfsr) / sizeof(int) -define EF_CPU offsetof(struct trapframe, tf_cpu) / sizeof(int) - -# m88110 trapframe element indexes -define EF_EXIP offsetof(struct trapframe, tf_exip) / sizeof(int) -define EF_ENIP offsetof(struct trapframe, tf_enip) / sizeof(int) -define EF_DSR offsetof(struct trapframe, tf_dsr) / sizeof(int) -define EF_DLAR offsetof(struct trapframe, tf_dlar) / sizeof(int) -define EF_DPAR offsetof(struct trapframe, tf_dpar) / sizeof(int) -define EF_ISR offsetof(struct trapframe, tf_isr) / sizeof(int) -define EF_ILAR offsetof(struct trapframe, tf_ilar) / sizeof(int) -define EF_IPAR offsetof(struct trapframe, tf_ipar) / sizeof(int) -define EF_ISAP offsetof(struct trapframe, tf_isap) / sizeof(int) -define EF_DSAP offsetof(struct trapframe, tf_dsap) / sizeof(int) -define EF_IUAP offsetof(struct trapframe, tf_iuap) / sizeof(int) -define EF_DUAP offsetof(struct trapframe, tf_duap) / sizeof(int) - -define SIZEOF_EF sizeof(struct trapframe) - -# more (machine-dependent) pcb fields -struct m88100_pcb -member pcb_pc -member pcb_ipl -member pcb_r14 -member pcb_r15 -member pcb_r16 -member pcb_r17 -member pcb_r18 -member pcb_r19 -member pcb_r20 -member pcb_r21 -member pcb_r22 -member pcb_r23 -member pcb_r24 -member pcb_r25 -member pcb_r26 -member pcb_r27 -member pcb_r28 -member pcb_r29 -member pcb_r30 -member pcb_sp -member pcb_fcr62 -member pcb_fcr63 diff --git a/sys/arch/luna88k/luna88k/locore_asm_routines.S b/sys/arch/luna88k/luna88k/locore_asm_routines.S deleted file mode 100644 index d8b52dce159..00000000000 --- a/sys/arch/luna88k/luna88k/locore_asm_routines.S +++ /dev/null @@ -1,1621 +0,0 @@ -/* $OpenBSD: locore_asm_routines.S,v 1.1 2004/04/21 15:24:01 aoyama Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1993-1992 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * Copyright (c) 1996 Nivas Madhur - * Copyright (c) 1998 Steve Murphree, Jr. - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -#include "assym.h" - -#include <sys/errno.h> - -#include <machine/asm.h> -#include <machine/board.h> -#include <machine/cpu_number.h> -#include <machine/trap.h> - -/***************************************************************************** - * DO_LOAD_ADDRESS - * - * unsigned int do_load_word(address, supervisor_mode) - * vaddr_t address; \\ in r2 - * boolean_t supervisor_mode; \\ in r3 - * - * Return the word at ADDRESS (from user space if SUPERVISOR_MODE is zero, - * supervisor space if non-zero). - * - */ - -ENTRY(do_load_word) /* do_load_word(address, supervisor) */ - bcnd ne0,r3,1f -#ifdef ERRATA__XXX_USR - NOP - ld.usr r2,r2,r0 - NOP - NOP - NOP -#else - ld.usr r2,r2,r0 -#endif - br 2f -1: ld r2,r2,r0 -2: jmp r1 - -ENTRY(do_load_half) /* do_load_half(address, supervisor) */ - bcnd ne0,r3,1f -#ifdef ERRATA__XXX_USR - NOP - ld.h.usr r2,r2,r0 - NOP - NOP - NOP -#else - ld.h.usr r2,r2,r0 -#endif - br 2f -1: ld.h r2,r2,r0 -2: jmp r1 - -ENTRY(do_load_byte) /* do_load_byte(address, supervisor) */ - bcnd ne0,r3,1f -#ifdef ERRATA__XXX_USR - NOP - ld.b.usr r2,r2,r0 - NOP - NOP - NOP -#else - ld.b.usr r2,r2,r0 -#endif - br 2f -1: ld.b r2,r2,r0 -2: jmp r1 - -ENTRY(do_store_word) /* do_store_word(address, data, supervisor) */ - bcnd ne0,r4,1f -#ifdef ERRATA__XXX_USR - NOP - st.usr r3,r2,r0 - NOP - NOP - NOP -#else - st.usr r3,r2,r0 -#endif - br 2f -1: st r3,r2,r0 -2: jmp r1 - -ENTRY(do_store_half) /* do_store_half(address, data, supervisor) */ - bcnd ne0,r4,1f -#ifdef ERRATA__XXX_USR - NOP - st.h.usr r3,r2,r0 - NOP - NOP - NOP -#else - st.h.usr r3,r2,r0 -#endif - br 2f -1: st.h r3,r2,r0 -2: jmp r1 - -ENTRY(do_store_byte) /* do_store_byte(address, data, supervisor) */ - bcnd ne0,r4,1f -#ifdef ERRATA__XXX_USR - NOP - st.b.usr r3,r2,r0 - NOP - NOP - NOP -#else - st.b.usr r3,r2,r0 -#endif - br 2f -1: st.b r3,r2,r0 -2: jmp r1 - -ENTRY(do_xmem_word) /* do_xmem_word(address, data, supervisor) */ - bcnd ne0,r4,1f -#ifdef ERRATA__XXX_USR - NOP - xmem.usr r3,r2,r0 - NOP - NOP - NOP -#else - xmem.usr r3,r2,r0 -#endif - br 2f -1: xmem r3,r2,r0 -2: jmp r1 - -ENTRY(do_xmem_byte) /* do_xmem_byte(address, data, supervisor) */ - bcnd ne0,r4,1f -#ifdef ERRATA__XXX_USR - NOP - xmem.bu.usr r3,r2,r0 - NOP - NOP - NOP -#else - xmem.bu.usr r3,r2,r0 -#endif - br 2f -1: xmem.bu r3,r2,r0 -2: jmp r1 - -/* - * Copy specified amount of data from user space into the kernel - * copyin(from, to, len) - * r2 == from (user source address) - * r3 == to (kernel destination address) - * r4 == length - * (r1=return addr) - */ - -#define SRC r2 -#define DEST r3 -#define LEN r4 - -ENTRY(copyin) - /* set up fault handler */ - or.u r5, r0, hi16(_C_LABEL(curpcb)) - ld r6, r5, lo16(_C_LABEL(curpcb)) - or.u r5, r0, hi16(_ASM_LABEL(Lciflt)) - or r5, r5, lo16(_ASM_LABEL(Lciflt)) - st r5, r6, PCB_ONFAULT /* pcb_onfault = Lciflt */ - -#if 0 - bcnd ne0, LEN, 1f /* XXX optimize len = 0 case */ - or r2, r0, 0 - br _ASM_LABEL(Lcidone) -1: bcnd lt0, LEN, _ASM_LABEL(Lciflt) /* EFAULT if len < 0 */ -#endif - - /* If it's a small length (less than 8), then do byte-by-byte */ - cmp r9, LEN, 8 - bb1 lt, r9, _ASM_LABEL(copyin_byte_only) - - /* If they're not aligned similarly, use byte only... */ - xor r9, SRC, DEST - mask r8, r9, 0x3 - bcnd ne0, r8, _ASM_LABEL(copyin_byte_only) - - /* - * At this point, we don't know if they're word aligned or not, - * but we know that what needs to be done to one to align - * it is what's needed for the other. - */ - bb1 0, SRC, _ASM_LABEL(copyin_left_align_to_halfword) -ASLOCAL(copyin_left_aligned_to_halfword) - bb1 1, SRC, _ASM_LABEL(copyin_left_align_to_word) -ASLOCAL(copyin_left_aligned_to_word) - bb1 0, LEN, _ASM_LABEL(copyin_right_align_to_halfword) -ASLOCAL(copyin_right_aligned_to_halfword) - bb1 1, LEN, _ASM_LABEL(copyin_right_align_to_word) -ASLOCAL(copyin_right_aligned_to_word) - - /* At this point, both SRC and DEST are aligned to a word */ - /* boundry, and LEN is an even multiple of 4. */ - bb1.n 2, LEN, _ASM_LABEL(copyin_right_align_to_doubleword) - or r7, r0, 4 - -ASLOCAL(copyin_right_aligned_to_doubleword) -#ifdef ERRATA__XXX_USR - NOP - ld.usr r5, SRC, r0 - NOP - NOP - NOP - ld.usr r6, SRC, r7 - NOP - NOP - NOP -#else - ld.usr r5, SRC, r0 - ld.usr r6, SRC, r7 -#endif - subu LEN, LEN, 8 - st r5, DEST, r0 - addu SRC, SRC, 8 - st r6, DEST, r7 - bcnd.n ne0, LEN, _ASM_LABEL(copyin_right_aligned_to_doubleword) - addu DEST, DEST, 8 - br.n _ASM_LABEL(Lcidone) - or r2, r0, r0 /* successful return */ - - /***************************************************/ - -ASLOCAL(copyin_left_align_to_halfword) -#ifdef ERRATA__XXX_USR - NOP - ld.b.usr r5, SRC, r0 - NOP - NOP - NOP -#else - ld.b.usr r5, SRC, r0 -#endif - subu LEN, LEN, 1 - st.b r5, DEST, r0 - addu SRC, SRC, 1 - br.n _ASM_LABEL(copyin_left_aligned_to_halfword) - addu DEST, DEST, 1 - -ASLOCAL(copyin_left_align_to_word) -#ifdef ERRATA__XXX_USR - NOP - ld.h.usr r5, SRC, r0 - NOP - NOP - NOP -#else - ld.h.usr r5, SRC, r0 -#endif - subu LEN, LEN, 2 - st.h r5, DEST, r0 - addu SRC, SRC, 2 - br.n _ASM_LABEL(copyin_left_aligned_to_word) - addu DEST, DEST, 2 - -ASLOCAL(copyin_right_align_to_halfword) - subu LEN, LEN, 1 -#ifdef ERRATA__XXX_USR - NOP - ld.b.usr r5, SRC, LEN - NOP - NOP - NOP -#else - ld.b.usr r5, SRC, LEN -#endif - br.n _ASM_LABEL(copyin_right_aligned_to_halfword) - st.b r5, DEST, LEN - -ASLOCAL(copyin_right_align_to_word) - subu LEN, LEN, 2 -#ifdef ERRATA__XXX_USR - NOP - ld.h.usr r5, SRC, LEN - NOP - NOP - NOP -#else - ld.h.usr r5, SRC, LEN -#endif - br.n _ASM_LABEL(copyin_right_aligned_to_word) - st.h r5, DEST, LEN - -ASLOCAL(copyin_right_align_to_doubleword) - subu LEN, LEN, 4 -#ifdef ERRATA__XXX_USR - NOP - ld.usr r5, SRC, LEN - NOP - NOP - NOP -#else - ld.usr r5, SRC, LEN -#endif - bcnd.n ne0, LEN, _ASM_LABEL(copyin_right_aligned_to_doubleword) - st r5, DEST, LEN - br.n _ASM_LABEL(Lcidone) - or r2, r0, r0 /* successful return */ - -ASLOCAL(copyin_byte_only) - bcnd eq0, LEN, 2f -1: - subu LEN, LEN, 1 -#ifdef ERRATA__XXX_USR - NOP - ld.b.usr r5, SRC, LEN - NOP - NOP - NOP -#else - ld.b.usr r5, SRC, LEN -#endif - bcnd.n ne0, LEN, 1b - st.b r5, DEST, LEN -2: - br.n _ASM_LABEL(Lcidone) - or r2, r0, r0 /* successful return */ - -ASLOCAL(Lcidone) - or.u r5,r0,hi16(_C_LABEL(curpcb)) - ld r6,r5,lo16(_C_LABEL(curpcb)) - jmp.n r1 - st r0,r6,PCB_ONFAULT - -ASLOCAL(Lciflt) - br.n _ASM_LABEL(Lcidone) - or r2, r0, EFAULT /* return fault */ - -#undef SRC -#undef DEST -#undef LEN -/*######################################################################*/ -/*######################################################################*/ - -/* - * Copy a null terminated string from the user space to the kernel - * address space. - * - * copyinstr(from, to, maxlen, &lencopied) - * r2 == from - * r3 == to - * r4 == maxlen - * r5 == len actually transferred (includes the terminating NULL!!!) - * r6 & r7 - used as temporaries - */ -#define SRC r2 -#define DEST r3 -#define CNT r4 -#define LEN r5 - -ENTRY(copyinstr) - - /* setup fault handler */ - or.u r6, r0, hi16(_C_LABEL(curpcb)) - ld r7, r6, lo16(_C_LABEL(curpcb)) - or.u r6, r0, hi16(_ASM_LABEL(Lcisflt)) - or r6, r6, lo16(_ASM_LABEL(Lcisflt)) - st r6, r7, PCB_ONFAULT - or r6, r0, 0 - bcnd lt0, CNT, _ASM_LABEL(Lcisflt) - bcnd eq0, CNT, _ASM_LABEL(Lcistoolong) -1: -#ifdef ERRATA__XXX_USR - NOP - ld.bu.usr r7, SRC, r6 - NOP - NOP - NOP -#else - ld.bu.usr r7, SRC, r6 -#endif - st.b r7, DEST, r6 - bcnd.n eq0, r7, 2f /* all done */ - addu r6, r6, 1 - cmp r7, r6, CNT - bb1 lt, r7, 1b - -ASLOCAL(Lcistoolong) - or r2, r0, ENAMETOOLONG /* overflow */ - -ASLOCAL(Lcisnull) - bcnd eq0,r6, _ASM_LABEL(Lcisdone) /* do not attempt to clear last byte */ - /* if we did not write to the string */ - subu r6, r6, 1 - st.b r0, DEST, r6 /* clear last byte */ - br.n _ASM_LABEL(Lcisdone) - addu r6, r6, 1 -2: /* all done */ - or r2, r0, 0 - -ASLOCAL(Lcisdone) - bcnd eq0, LEN, 3f - st r6, r0, LEN -3: - or.u r5,r0,hi16(_C_LABEL(curpcb)) - ld r6,r5,lo16(_C_LABEL(curpcb)) - jmp.n r1 - st r0,r6,PCB_ONFAULT /* clear the handler */ - -ASLOCAL(Lcisflt) - br.n _ASM_LABEL(Lcisnull) - or r2, r0, EFAULT /* return fault */ - -#undef SRC -#undef DEST -#undef CNT -#undef LEN - -/* - * Copy specified amount of data from kernel to the user space - * Copyout(from, to, len) - * r2 == from (kernel source address) - * r3 == to (user destination address) - * r4 == length - */ - -#define SRC r2 -#define DEST r3 -#define LEN r4 - -ENTRY(copyout) - /* setup fault handler */ - or.u r5, r0, hi16(_C_LABEL(curpcb)) - ld r6, r5, lo16(_C_LABEL(curpcb)) - or.u r5, r0, hi16(_ASM_LABEL(Lcoflt)) - or r5, r5, lo16(_ASM_LABEL(Lcoflt)) - st r5, r6, PCB_ONFAULT /* pcb_onfault = Lcoflt */ -#if 0 - bcnd ne0, LEN, 1f /* XXX optimize len = 0 case */ - or r2, r0, 0 - br _ASM_LABEL(Lcodone) -1: bcnd lt0, LEN, _ASM_LABEL(Lcoflt) /* EFAULT if len < 0 */ -#endif - /* If it's a small length (less than 8), then do byte-by-byte */ - cmp r9, LEN, 8 - bb1 lt, r9, _ASM_LABEL(copyout_byte_only) - - /* If they're not aligned similarly, use byte only... */ - xor r9, SRC, DEST - mask r8, r9, 0x3 - bcnd ne0, r8, _ASM_LABEL(copyout_byte_only) - - /* - * At this point, we don't know if they're word aligned or not, - * but we know that what needs to be done to one to align - * it is what's needed for the other. - */ - bb1 0, SRC, _ASM_LABEL(copyout_left_align_to_halfword) -ASLOCAL(copyout_left_aligned_to_halfword) - bb1 1, SRC, _ASM_LABEL(copyout_left_align_to_word) -ASLOCAL(copyout_left_aligned_to_word) - bb1 0, LEN, _ASM_LABEL(copyout_right_align_to_halfword) -ASLOCAL(copyout_right_aligned_to_halfword) - bb1 1, LEN, _ASM_LABEL(copyout_right_align_to_word) -ASLOCAL(copyout_right_aligned_to_word) - - /* - * At this point, both SRC and DEST are aligned to a word - * boundry, and LEN is an even multiple of 4. - */ - bb1.n 2, LEN, _ASM_LABEL(copyout_right_align_to_doubleword) - or r7, r0, 4 - -ASLOCAL(copyout_right_aligned_to_doubleword) - ld r5, SRC, r0 - ld r6, SRC, r7 - subu LEN, LEN, 8 -#ifdef ERRATA__XXX_USR - NOP - st.usr r5, DEST, r0 - NOP - NOP - NOP -#else - st.usr r5, DEST, r0 -#endif - addu SRC, SRC, 8 -#ifdef ERRATA__XXX_USR - NOP - st.usr r6, DEST, r7 - NOP - NOP - NOP -#else - st.usr r6, DEST, r7 -#endif - bcnd.n ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword) - addu DEST, DEST, 8 - or r2, r0, r0 /* successful return */ - br _ASM_LABEL(Lcodone) - - /***************************************************/ -ASLOCAL(copyout_left_align_to_halfword) - ld.b r5, SRC, r0 - subu LEN, LEN, 1 -#ifdef ERRATA__XXX_USR - NOP - st.b.usr r5, DEST, r0 - NOP - NOP - NOP -#else - st.b.usr r5, DEST, r0 -#endif - addu SRC, SRC, 1 - br.n _ASM_LABEL(copyout_left_aligned_to_halfword) - addu DEST, DEST, 1 - -ASLOCAL(copyout_left_align_to_word) - ld.h r5, SRC, r0 - subu LEN, LEN, 2 -#ifdef ERRATA__XXX_USR - NOP - st.h.usr r5, DEST, r0 - NOP - NOP - NOP -#else - st.h.usr r5, DEST, r0 -#endif - addu SRC, SRC, 2 - br.n _ASM_LABEL(copyout_left_aligned_to_word) - addu DEST, DEST, 2 - -ASLOCAL(copyout_right_align_to_halfword) - subu LEN, LEN, 1 - ld.b r5, SRC, LEN -#ifdef ERRATA__XXX_USR - NOP - st.b.usr r5, DEST, LEN - NOP - NOP - NOP - br _ASM_LABEL(copyout_right_aligned_to_halfword) -#else - br.n _ASM_LABEL(copyout_right_aligned_to_halfword) - st.b.usr r5, DEST, LEN -#endif - -ASLOCAL(copyout_right_align_to_word) - subu LEN, LEN, 2 - ld.h r5, SRC, LEN -#ifdef ERRATA__XXX_USR - NOP - st.h.usr r5, DEST, LEN - NOP - NOP - NOP - br _ASM_LABEL(copyout_right_aligned_to_word) -#else - br.n _ASM_LABEL(copyout_right_aligned_to_word) - st.h.usr r5, DEST, LEN -#endif - -ASLOCAL(copyout_right_align_to_doubleword) - subu LEN, LEN, 4 - ld r5, SRC, LEN -#ifdef ERRATA__XXX_USR - NOP - st.usr r5, DEST, LEN - NOP - NOP - NOP - bcnd ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword) -#else - bcnd.n ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword) - st.usr r5, DEST, LEN -#endif - br.n _ASM_LABEL(Lcodone) - or r2, r0, r0 /* successful return */ - -ASLOCAL(copyout_byte_only) - bcnd eq0, LEN, 2f -1: - subu LEN, LEN, 1 - ld.b r5, SRC, LEN -#ifdef ERRATA__XXX_USR - NOP - st.b.usr r5, DEST, LEN - NOP - NOP - NOP - bcnd ne0, LEN, 1b -#else - bcnd.n ne0, LEN, 1b - st.b.usr r5, DEST, LEN -#endif - -2: - br.n _ASM_LABEL(Lcodone) - or r2, r0, r0 /* successful return */ - -ASLOCAL(Lcodone) - or.u r5,r0,hi16(_C_LABEL(curpcb)) - ld r6,r5,lo16(_C_LABEL(curpcb)) - jmp.n r1 - st r0,r6,PCB_ONFAULT /* clear the handler */ - -ASLOCAL(Lcoflt) - br.n _ASM_LABEL(Lcodone) - or r2, r0, EFAULT /* return fault */ - -#undef SRC -#undef DEST -#undef LEN - -/* - * Copy a null terminated string from the kernel space to the user - * address space. - * - * copyoutstr(from, to, maxlen, &lencopied) - * r2 == from - * r3 == to - * r4 == maxlen that can be copied - * r5 == len actually copied (including the terminating NULL!!!) - */ - -#define SRC r2 -#define DEST r3 -#define CNT r4 -#define LEN r5 - -ENTRY(copyoutstr) - /* setup fault handler */ - or.u r6, r0, hi16(_C_LABEL(curpcb)) - ld r7, r6, lo16(_C_LABEL(curpcb)) - or.u r6, r0, hi16(_ASM_LABEL(Lcosflt)) - or r6, r6, lo16(_ASM_LABEL(Lcosflt)) - st r6, r7, PCB_ONFAULT - bcnd lt0, CNT, _ASM_LABEL(Lcosflt) - bcnd eq0, CNT, _ASM_LABEL(Lcosdone) - or r6, r0, 0 -1: - ld.bu r7, SRC, r6 -#ifdef ERRATA__XXX_USR - NOP - st.b.usr r7, DEST, r6 - NOP - NOP - NOP -#else - st.b.usr r7, DEST, r6 -#endif - bcnd.n eq0, r7, 2f /* all done */ - addu r6, r6, 1 - cmp r7, r6, CNT - bb1 lt, r7, 1b - br.n _ASM_LABEL(Lcosdone) - or r2, r0, ENAMETOOLONG -2: - br.n _ASM_LABEL(Lcosdone) - or r2, r0, 0 - -ASLOCAL(Lcosflt) - br.n _ASM_LABEL(Lcosdone) - or r2, r0, EFAULT - -ASLOCAL(Lcosdone) - bcnd eq0, LEN, 3f - st r6, r0, LEN -3: or.u r5,r0,hi16(_C_LABEL(curpcb)) - ld r6,r5,lo16(_C_LABEL(curpcb)) - jmp.n r1 - st r0,r6,PCB_ONFAULT /* clear the handler */ - -#undef SRC -#undef DEST -#undef CNT -#undef LEN - -/*######################################################################*/ - -/* - * kcopy(const void *src, void *dst, size_t len); - * - * Copy len bytes from src to dst, aborting if we encounter a page fault. - */ -ENTRY(kcopy) - or.u r5, r0, hi16(_C_LABEL(curpcb)) - ld r6, r5, lo16(_C_LABEL(curpcb)) - or.u r5, r0, hi16(_ASM_LABEL(kcopy_fault)) - or r5, r5, lo16(_ASM_LABEL(kcopy_fault)) - st r5, r6, PCB_ONFAULT /* pcb_onfault = kcopy_fault */ - bcnd le0,r4,_ASM_LABEL(kcopy_out) /* nothing to do if <= 0 */ -/* - * check position of source and destination data - */ - cmp r9,r2,r3 /* compare source address to destination */ - bb1 eq,r9,_ASM_LABEL(kcopy_out) /* nothing to do if equal */ - bb1 lo,r9,_ASM_LABEL(kcopy_revers)e /* reverse copy if src < dest */ -/* - * source address is greater than destination address, copy forward - */ - cmp r9,r4,16 /* see if we have at least 16 bytes */ - bb1 lt,r9,_ASM_LABEL(kf_byte_copy) /* copy bytes for small length */ -/* - * determine copy strategy based on alignment of source and destination - */ - mask r6,r2,3 /* get 2 low order bits of source address */ - mask r7,r3,3 /* get 2 low order bits of destintation addr */ - mak r6,r6,0<4> /* convert source bits to table offset */ - mak r7,r7,0<2> /* convert destination bits to table offset */ - or.u r12,r0,hi16(_ASM_LABEL(kf_strat)) - or r12,r12,lo16(_ASM_LABEL(kf_strat)) - addu r6,r6,r7 /* compute final table offset for strategy */ - ld r12,r12,r6 /* load the strategy routine */ - jmp r12 /* branch to strategy routine */ - -/* - * Copy three bytes from src to destination then copy words - */ -ASLOCAL(kf_3byte_word_copy) - ld.bu r6,r2,0 /* load byte from source */ - ld.bu r7,r2,1 /* load byte from source */ - ld.bu r8,r2,2 /* load byte from source */ - st.b r6,r3,0 /* store byte to destination */ - st.b r7,r3,1 /* store byte to destination */ - st.b r8,r3,2 /* store byte to destination */ - addu r2,r2,3 /* increment source pointer */ - addu r3,r3,3 /* increment destination pointer */ - br.n _ASM_LABEL(kf_word_copy) /* copy full words */ - subu r4,r4,3 /* decrement length */ - -/* - * Copy 1 halfword from src to destination then copy words - */ -ASLOCAL(kf_1half_word_copy) - ld.hu r6,r2,0 /* load half-word from source */ - st.h r6,r3,0 /* store half-word to destination */ - addu r2,r2,2 /* increment source pointer */ - addu r3,r3,2 /* increment destination pointer */ - br.n _ASM_LABEL(kf_word_copy) /* copy full words */ - subu r4,r4,2 /* decrement remaining length */ - -/* - * Copy 1 byte from src to destination then copy words - */ -ASLOCAL(kf_1byte_word_copy) - ld.bu r6,r2,0 /* load 1 byte from source */ - st.b r6,r3,0 /* store 1 byte to destination */ - addu r2,r2,1 /* increment source pointer */ - addu r3,r3,1 /* increment destination pointer */ - subu r4,r4,1 /* decrement remaining length */ - /* fall through to word copy */ -/* - * Copy as many full words as possible, 4 words per loop - */ -ASLOCAL(kf_word_copy) - cmp r10,r4,16 /* see if we have 16 bytes remaining */ - bb1 lo,r10,_ASM_LABEL(kf_byte_copy) /* not enough left, copy bytes */ - ld r6,r2,0 /* load first word */ - ld r7,r2,4 /* load second word */ - ld r8,r2,8 /* load third word */ - ld r9,r2,12 /* load fourth word */ - st r6,r3,0 /* store first word */ - st r7,r3,4 /* store second word */ - st r8,r3,8 /* store third word */ - st r9,r3,12 /* store fourth word */ - addu r2,r2,16 /* increment source pointer */ - addu r3,r3,16 /* increment destination pointer */ - br.n _ASM_LABEL(kf_word_copy) /* copy another block */ - subu r4,r4,16 /* decrement remaining length */ - -ASLOCAL(kf_1byte_half_copy) - ld.bu r6,r2,0 /* load 1 byte from source */ - st.b r6,r3,0 /* store 1 byte to destination */ - addu r2,r2,1 /* increment source pointer */ - addu r3,r3,1 /* increment destination pointer */ - subu r4,r4,1 /* decrement remaining length */ - /* fall through to half copy */ - -ASLOCAL(kf_half_copy) - cmp r10,r4,16 /* see if we have 16 bytes remaining */ - bb1 lo,r10,_ASM_LABEL(kf_byte_copy) /* not enough left, copy bytes */ - ld.hu r6,r2,0 /* load first half-word */ - ld.hu r7,r2,2 /* load second half-word */ - ld.hu r8,r2,4 /* load third half-word */ - ld.hu r9,r2,6 /* load fourth half-word */ - ld.hu r10,r2,8 /* load fifth half-word */ - ld.hu r11,r2,10 /* load sixth half-word */ - ld.hu r12,r2,12 /* load seventh half-word */ - ld.hu r13,r2,14 /* load eighth half-word */ - st.h r6,r3,0 /* store first half-word */ - st.h r7,r3,2 /* store second half-word */ - st.h r8,r3,4 /* store third half-word */ - st.h r9,r3,6 /* store fourth half-word */ - st.h r10,r3,8 /* store fifth half-word */ - st.h r11,r3,10 /* store sixth half-word */ - st.h r12,r3,12 /* store seventh half-word */ - st.h r13,r3,14 /* store eighth half-word */ - addu r2,r2,16 /* increment source pointer */ - addu r3,r3,16 /* increment destination pointer */ - br.n _ASM_LABEL(kf_half_copy) /* copy another block */ - subu r4,r4,16 /* decrement remaining length */ - -ASLOCAL(kf_byte_copy) - bcnd eq0,r4,_ASM_LABEL(kcopy_out) /* branch if nothing left to copy */ - ld.bu r6,r2,0 /* load byte from source */ - st.b r6,r3,0 /* store byte in destination */ - addu r2,r2,1 /* increment source pointer */ - addu r3,r3,1 /* increment destination pointer */ - br.n _ASM_LABEL(kf_byte_copy) /* branch for next byte */ - subu r4,r4,1 /* decrement remaining length */ - -/* - * source address is less than destination address, copy in reverse - */ -ASLOCAL(kcopy_reverse) -/* - * start copy pointers at end of data - */ - addu r2,r2,r4 /* start source at end of data */ - addu r3,r3,r4 /* start destination at end of data */ -/* - * check for short data - */ - cmp r9,r4,16 /* see if we have at least 16 bytes */ - bb1 lt,r9,_ASM_LABEL(kr_byte_copy) /* copy bytes for small data length */ -/* - * determine copy strategy based on alignment of source and destination - */ - mask r6,r2,3 /* get 2 low order bits of source address */ - mask r7,r3,3 /* get 2 low order bits of destintation addr */ - mak r6,r6,0<4> /* convert source bits to table offset */ - mak r7,r7,0<2> /* convert destination bits to table offset */ - or.u r12,r0,hi16(_ASM_LABEL(kr_strat)) - or r12,r12,lo16(_ASM_LABEL(kr_strat)) - addu r6,r6,r7 /* compute final table offset for strategy */ - ld r12,r12,r6 /* load the strategy routine */ - jmp r12 /* branch to strategy routine */ - -/* - * Copy three bytes from src to destination then copy words - */ -ASLOCAL(kr_3byte_word_copy) - subu r2,r2,3 /* decrement source pointer */ - subu r3,r3,3 /* decrement destination pointer */ - ld.bu r6,r2,0 /* load byte from source */ - ld.bu r7,r2,1 /* load byte from source */ - ld.bu r8,r2,2 /* load byte from source */ - st.b r6,r3,0 /* store byte to destination */ - st.b r7,r3,1 /* store byte to destination */ - st.b r8,r3,2 /* store byte to destination */ - br.n _ASM_LABEL(kr_word_copy) /* copy full words */ - subu r4,r4,3 /* decrement length */ - -/* - * Copy 1 halfword from src to destination then copy words - */ -ASLOCAL(kr_1half_word_copy) - subu r2,r2,2 /* decrement source pointer */ - subu r3,r3,2 /* decrement destination pointer */ - ld.hu r6,r2,0 /* load half-word from source */ - st.h r6,r3,0 /* store half-word to destination */ - br.n _ASM_LABEL(kr_word_copy) /* copy full words */ - subu r4,r4,2 /* decrement remaining length */ - -/* - * Copy 1 byte from src to destination then copy words - */ -ASLOCAL(kr_1byte_word_copy) - subu r2,r2,1 /* decrement source pointer */ - subu r3,r3,1 /* decrement destination pointer */ - ld.bu r6,r2,0 /* load 1 byte from source */ - st.b r6,r3,0 /* store 1 byte to destination */ - subu r4,r4,1 /* decrement remaining length */ - /* fall through to word copy */ -/* - * Copy as many full words as possible, 4 words per loop - */ -ASLOCAL(kr_word_copy) - cmp r10,r4,16 /* see if we have 16 bytes remaining */ - bb1 lo,r10,_ASM_LABEL(kr_byte_copy) /* not enough left, copy bytes */ - subu r2,r2,16 /* decrement source pointer */ - subu r3,r3,16 /* decrement destination pointer */ - ld r6,r2,0 /* load first word */ - ld r7,r2,4 /* load second word */ - ld r8,r2,8 /* load third word */ - ld r9,r2,12 /* load fourth word */ - st r6,r3,0 /* store first word */ - st r7,r3,4 /* store second word */ - st r8,r3,8 /* store third word */ - st r9,r3,12 /* store fourth word */ - br.n _ASM_LABEL(kr_word_copy) /* copy another block */ - subu r4,r4,16 /* decrement remaining length */ - -ASLOCAL(kr_1byte_half_copy) - subu r2,r2,1 /* decrement source pointer */ - subu r3,r3,1 /* decrement destination pointer */ - ld.bu r6,r2,0 /* load 1 byte from source */ - st.b r6,r3,0 /* store 1 byte to destination */ - subu r4,r4,1 /* decrement remaining length */ - /* fall through to half copy */ - -ASLOCAL(kr_half_copy) - cmp r10,r4,16 /* see if we have 16 bytes remaining */ - bb1 lo,r10,_ASM_LABEL(kr_byte_copy) /* not enough left, copy bytes */ - subu r2,r2,16 /* decrement source pointer */ - subu r3,r3,16 /* decrement destination pointer */ - ld.hu r6,r2,0 /* load first half-word */ - ld.hu r7,r2,2 /* load second half-word */ - ld.hu r8,r2,4 /* load third half-word */ - ld.hu r9,r2,6 /* load fourth half-word */ - ld.hu r10,r2,8 /* load fifth half-word */ - ld.hu r11,r2,10 /* load sixth half-word */ - ld.hu r12,r2,12 /* load seventh half-word */ - ld.hu r13,r2,14 /* load eighth half-word */ - st.h r6,r3,0 /* store first half-word */ - st.h r7,r3,2 /* store second half-word */ - st.h r8,r3,4 /* store third half-word */ - st.h r9,r3,6 /* store fourth half-word */ - st.h r10,r3,8 /* store fifth half-word */ - st.h r11,r3,10 /* store sixth half-word */ - st.h r12,r3,12 /* store seventh half-word */ - st.h r13,r3,14 /* store eighth half-word */ - br.n _ASM_LABEL(kr_half_copy) /* copy another block */ - subu r4,r4,16 /* decrement remaining length */ - -ASLOCAL(kr_byte_copy) - bcnd eq0,r4,_ASM_LABEL(kcopy_out) /* branch if nothing left to copy */ - subu r2,r2,1 /* decrement source pointer */ - subu r3,r3,1 /* decrement destination pointer */ - ld.bu r6,r2,0 /* load byte from source */ - st.b r6,r3,0 /* store byte in destination */ - br.n _ASM_LABEL(kr_byte_copy) /* branch for next byte */ - subu r4,r4,1 /* decrement remaining length */ - -ASLOCAL(kcopy_out) - or r2, r0, 0 /* return success */ -ASLOCAL(kcopy_out_fault) - or.u r5,r0,hi16(_C_LABEL(curpcb)) - ld r6,r5,lo16(_C_LABEL(curpcb)) - st r0,r6,PCB_ONFAULT /* clear the handler */ - jmp r1 /* all done, return to caller */ - -ASLOCAL(kcopy_fault) - or r2, r0, EFAULT /* return fault */ - br _ASM_LABEL(kcopy_out_fault) - - data - align 4 -ASLOCAL(kf_strat) - word _ASM_LABEL(kf_word_copy) - word _ASM_LABEL(kf_byte_copy) - word _ASM_LABEL(kf_half_copy) - word _ASM_LABEL(kf_byte_copy) - word _ASM_LABEL(kf_byte_copy) - word _ASM_LABEL(kf_3byte_word_copy) - word _ASM_LABEL(kf_byte_copy) - word _ASM_LABEL(kf_1byte_half_copy) - word _ASM_LABEL(kf_half_copy) - word _ASM_LABEL(kf_byte_copy) - word _ASM_LABEL(kf_1half_word_copy) - word _ASM_LABEL(kf_byte_copy) - word _ASM_LABEL(kf_byte_copy) - word _ASM_LABEL(kf_1byte_half_copy) - word _ASM_LABEL(kf_byte_copy) - word _ASM_LABEL(kf_1byte_word_copy) - -ASLOCAL(kr_strat) - word _ASM_LABEL(kr_word_copy) - word _ASM_LABEL(kr_byte_copy) - word _ASM_LABEL(kr_half_copy) - word _ASM_LABEL(kr_byte_copy) - word _ASM_LABEL(kr_byte_copy) - word _ASM_LABEL(kr_1byte_word_copy) - word _ASM_LABEL(kr_byte_copy) - word _ASM_LABEL(kr_1byte_half_copy) - word _ASM_LABEL(kr_half_copy) - word _ASM_LABEL(kr_byte_copy) - word _ASM_LABEL(kr_1half_word_copy) - word _ASM_LABEL(kr_byte_copy) - word _ASM_LABEL(kr_byte_copy) - word _ASM_LABEL(kr_1byte_half_copy) - word _ASM_LABEL(kr_byte_copy) - word _ASM_LABEL(kr_3byte_word_copy) - -/* - * Gcc 2 generates calls to memcpy for bcopies of unknown size. memcpy can - * simply be implemented as ovbcopy but the src (r2, r3) and dst args need to - * be switched. - */ -/* - * void memcpy(dest, source, count) - * - */ -ENTRY(memcpy) - or r5, r0, r2 /* dst -> tmp */ - or r2, r0, r3 /* src -> 1st arg */ - br.n _C_LABEL(ovbcopy) - or r3, r0, r5 /* dst -> 2nd arg */ - -/* - * void bcopy(source, destination, count) - * - * copy count bytes of data from source to destination - * Don Harper (don@omron.co.jp), Omron Corporation. - * - */ - -ENTRY(bcopy) -ENTRY(ovbcopy) - bcnd le0,r4,_ASM_LABEL(bcopy_out) /* nothing to do if <= 0 */ -/* - * check position of source and destination data - */ - cmp r9,r2,r3 /* compare source address to destination */ - bb1 eq,r9,_ASM_LABEL(bcopy_out) /* nothing to do if equal */ - bb1 lo,r9,_ASM_LABEL(bcopy_reverse) /* reverse copy if src < dest */ -/* - * source address is greater than destination address, copy forward - */ - cmp r9,r4,16 /* see if we have at least 16 bytes */ - bb1 lt,r9,_ASM_LABEL(f_byte_copy) /* copy bytes for small data length */ -/* - * determine copy strategy based on alignment of source and destination - */ - mask r6,r2,3 /* get 2 low order bits of source address */ - mask r7,r3,3 /* get 2 low order bits of destintation addr */ - mak r6,r6,0<4> /* convert source bits to table offset */ - mak r7,r7,0<2> /* convert destination bits to table offset */ - or.u r12,r0,hi16(_ASM_LABEL(f_strat)) - or r12,r12,lo16(_ASM_LABEL(f_strat)) - addu r6,r6,r7 /* compute final table offset for strategy */ - ld r12,r12,r6 /* load the strategy routine */ - jmp r12 /* branch to strategy routine */ - - -/* - * Copy three bytes from src to destination then copy words - */ -ASLOCAL(f_3byte_word_copy) - ld.bu r6,r2,0 /* load byte from source */ - ld.bu r7,r2,1 /* load byte from source */ - ld.bu r8,r2,2 /* load byte from source */ - st.b r6,r3,0 /* store byte to destination */ - st.b r7,r3,1 /* store byte to destination */ - st.b r8,r3,2 /* store byte to destination */ - addu r2,r2,3 /* increment source pointer */ - addu r3,r3,3 /* increment destination pointer */ - br.n _ASM_LABEL(f_word_copy) /* copy full words */ - subu r4,r4,3 /* decrement length */ - -/* - * Copy 1 halfword from src to destination then copy words - */ -ASLOCAL(f_1half_word_copy) - ld.hu r6,r2,0 /* load half-word from source */ - st.h r6,r3,0 /* store half-word to destination */ - addu r2,r2,2 /* increment source pointer */ - addu r3,r3,2 /* increment destination pointer */ - br.n _ASM_LABEL(f_word_copy) /* copy full words */ - subu r4,r4,2 /* decrement remaining length */ - -/* - * Copy 1 byte from src to destination then copy words - */ -ASLOCAL(f_1byte_word_copy) - ld.bu r6,r2,0 /* load 1 byte from source */ - st.b r6,r3,0 /* store 1 byte to destination */ - addu r2,r2,1 /* increment source pointer */ - addu r3,r3,1 /* increment destination pointer */ - subu r4,r4,1 /* decrement remaining length */ - /* fall through to word copy */ -/* - * Copy as many full words as possible, 4 words per loop - */ -ASLOCAL(f_word_copy) - cmp r10,r4,16 /* see if we have 16 bytes remaining */ - bb1 lo,r10,_ASM_LABEL(f_byte_copy) /* not enough left, copy bytes */ - ld r6,r2,0 /* load first word */ - ld r7,r2,4 /* load second word */ - ld r8,r2,8 /* load third word */ - ld r9,r2,12 /* load fourth word */ - st r6,r3,0 /* store first word */ - st r7,r3,4 /* store second word */ - st r8,r3,8 /* store third word */ - st r9,r3,12 /* store fourth word */ - addu r2,r2,16 /* increment source pointer */ - addu r3,r3,16 /* increment destination pointer */ - br.n _ASM_LABEL(f_word_copy) /* branch to copy another block */ - subu r4,r4,16 /* decrement remaining length */ - -ASLOCAL(f_1byte_half_copy) - ld.bu r6,r2,0 /* load 1 byte from source */ - st.b r6,r3,0 /* store 1 byte to destination */ - addu r2,r2,1 /* increment source pointer */ - addu r3,r3,1 /* increment destination pointer */ - subu r4,r4,1 /* decrement remaining length */ - /* fall through to half copy */ - -ASLOCAL(f_half_copy) - cmp r10,r4,16 /* see if we have 16 bytes remaining */ - bb1 lo,r10,_ASM_LABEL(f_byte_copy) /* not enough left, copy bytes */ - ld.hu r6,r2,0 /* load first half-word */ - ld.hu r7,r2,2 /* load second half-word */ - ld.hu r8,r2,4 /* load third half-word */ - ld.hu r9,r2,6 /* load fourth half-word */ - ld.hu r10,r2,8 /* load fifth half-word */ - ld.hu r11,r2,10 /* load sixth half-word */ - ld.hu r12,r2,12 /* load seventh half-word */ - ld.hu r13,r2,14 /* load eighth half-word */ - st.h r6,r3,0 /* store first half-word */ - st.h r7,r3,2 /* store second half-word */ - st.h r8,r3,4 /* store third half-word */ - st.h r9,r3,6 /* store fourth half-word */ - st.h r10,r3,8 /* store fifth half-word */ - st.h r11,r3,10 /* store sixth half-word */ - st.h r12,r3,12 /* store seventh half-word */ - st.h r13,r3,14 /* store eighth half-word */ - addu r2,r2,16 /* increment source pointer */ - addu r3,r3,16 /* increment destination pointer */ - br.n _ASM_LABEL(f_half_copy) /* branch to copy another block */ - subu r4,r4,16 /* decrement remaining length */ - -ASLOCAL(f_byte_copy) - bcnd eq0,r4,_ASM_LABEL(bcopy_out) /* branch if nothing left to copy */ - ld.bu r6,r2,0 /* load byte from source */ - st.b r6,r3,0 /* store byte in destination */ - addu r2,r2,1 /* increment source pointer */ - addu r3,r3,1 /* increment destination pointer */ - br.n _ASM_LABEL(f_byte_copy) /* branch for next byte */ - subu r4,r4,1 /* decrement remaining length */ - -/* - * source address is less than destination address, copy in reverse - */ -ASLOCAL(bcopy_reverse) -/* - * start copy pointers at end of data - */ - addu r2,r2,r4 /* start source at end of data */ - addu r3,r3,r4 /* start destination at end of data */ -/* - * check for short data - */ - cmp r9,r4,16 /* see if we have at least 16 bytes */ - bb1 lt,r9,_ASM_LABEL(r_byte_copy) /* copy bytes for small data length */ -/* - * determine copy strategy based on alignment of source and destination - */ - mask r6,r2,3 /* get 2 low order bits of source address */ - mask r7,r3,3 /* get 2 low order bits of destintation addr */ - mak r6,r6,0<4> /* convert source bits to table offset */ - mak r7,r7,0<2> /* convert destination bits to table offset */ - or.u r12,r0,hi16(_ASM_LABEL(r_strat)) - or r12,r12,lo16(_ASM_LABEL(r_strat)) - addu r6,r6,r7 /* compute final table offset for strategy */ - ld r12,r12,r6 /* load the strategy routine */ - jmp r12 /* branch to strategy routine */ - -/* - * Copy three bytes from src to destination then copy words - */ -ASLOCAL(r_3byte_word_copy) - subu r2,r2,3 /* decrement source pointer */ - subu r3,r3,3 /* decrement destination pointer */ - ld.bu r6,r2,0 /* load byte from source */ - ld.bu r7,r2,1 /* load byte from source */ - ld.bu r8,r2,2 /* load byte from source */ - st.b r6,r3,0 /* store byte to destination */ - st.b r7,r3,1 /* store byte to destination */ - st.b r8,r3,2 /* store byte to destination */ - br.n _ASM_LABEL(r_word_copy) /* copy full words */ - subu r4,r4,3 /* decrement length */ - -/* - * Copy 1 halfword from src to destination then copy words - */ -ASLOCAL(r_1half_word_copy) - subu r2,r2,2 /* decrement source pointer */ - subu r3,r3,2 /* decrement destination pointer */ - ld.hu r6,r2,0 /* load half-word from source */ - st.h r6,r3,0 /* store half-word to destination */ - br.n _ASM_LABEL(r_word_copy) /* copy full words */ - subu r4,r4,2 /* decrement remaining length */ - -/* - * Copy 1 byte from src to destination then copy words - */ -ASLOCAL(r_1byte_word_copy) - subu r2,r2,1 /* decrement source pointer */ - subu r3,r3,1 /* decrement destination pointer */ - ld.bu r6,r2,0 /* load 1 byte from source */ - st.b r6,r3,0 /* store 1 byte to destination */ - subu r4,r4,1 /* decrement remaining length */ - /* fall through to word copy */ -/* - * Copy as many full words as possible, 4 words per loop - */ -ASLOCAL(r_word_copy) - cmp r10,r4,16 /* see if we have 16 bytes remaining */ - bb1 lo,r10,_ASM_LABEL(r_byte_copy) /* not enough left, copy bytes */ - subu r2,r2,16 /* decrement source pointer */ - subu r3,r3,16 /* decrement destination pointer */ - ld r6,r2,0 /* load first word */ - ld r7,r2,4 /* load second word */ - ld r8,r2,8 /* load third word */ - ld r9,r2,12 /* load fourth word */ - st r6,r3,0 /* store first word */ - st r7,r3,4 /* store second word */ - st r8,r3,8 /* store third word */ - st r9,r3,12 /* store fourth word */ - br.n _ASM_LABEL(r_word_copy) /* branch to copy another block */ - subu r4,r4,16 /* decrement remaining length */ - -ASLOCAL(r_1byte_half_copy) - subu r2,r2,1 /* decrement source pointer */ - subu r3,r3,1 /* decrement destination pointer */ - ld.bu r6,r2,0 /* load 1 byte from source */ - st.b r6,r3,0 /* store 1 byte to destination */ - subu r4,r4,1 /* decrement remaining length */ - /* fall through to half copy */ - -ASLOCAL(r_half_copy) - cmp r10,r4,16 /* see if we have 16 bytes remaining */ - bb1 lo,r10,_ASM_LABEL(r_byte_copy) /* not enough left, copy bytes */ - subu r2,r2,16 /* decrement source pointer */ - subu r3,r3,16 /* decrement destination pointer */ - ld.hu r6,r2,0 /* load first half-word */ - ld.hu r7,r2,2 /* load second half-word */ - ld.hu r8,r2,4 /* load third half-word */ - ld.hu r9,r2,6 /* load fourth half-word */ - ld.hu r10,r2,8 /* load fifth half-word */ - ld.hu r11,r2,10 /* load sixth half-word */ - ld.hu r12,r2,12 /* load seventh half-word */ - ld.hu r13,r2,14 /* load eighth half-word */ - st.h r6,r3,0 /* store first half-word */ - st.h r7,r3,2 /* store second half-word */ - st.h r8,r3,4 /* store third half-word */ - st.h r9,r3,6 /* store fourth half-word */ - st.h r10,r3,8 /* store fifth half-word */ - st.h r11,r3,10 /* store sixth half-word */ - st.h r12,r3,12 /* store seventh half-word */ - st.h r13,r3,14 /* store eighth half-word */ - br.n _ASM_LABEL(r_half_copy) /* branch to copy another block */ - subu r4,r4,16 /* decrement remaining length */ - -ASLOCAL(r_byte_copy) - bcnd eq0,r4,_ASM_LABEL(bcopy_out) /* branch if nothing left to copy */ - subu r2,r2,1 /* decrement source pointer */ - subu r3,r3,1 /* decrement destination pointer */ - ld.bu r6,r2,0 /* load byte from source */ - st.b r6,r3,0 /* store byte in destination */ - br.n _ASM_LABEL(r_byte_copy) /* branch for next byte */ - subu r4,r4,1 /* decrement remaining length */ - -ASLOCAL(bcopy_out) - jmp r1 /* all done, return to caller */ - - data - align 4 -ASLOCAL(f_strat) - word _ASM_LABEL(f_word_copy) - word _ASM_LABEL(f_byte_copy) - word _ASM_LABEL(f_half_copy) - word _ASM_LABEL(f_byte_copy) - word _ASM_LABEL(f_byte_copy) - word _ASM_LABEL(f_3byte_word_copy) - word _ASM_LABEL(f_byte_copy) - word _ASM_LABEL(f_1byte_half_copy) - word _ASM_LABEL(f_half_copy) - word _ASM_LABEL(f_byte_copy) - word _ASM_LABEL(f_1half_word_copy) - word _ASM_LABEL(f_byte_copy) - word _ASM_LABEL(f_byte_copy) - word _ASM_LABEL(f_1byte_half_copy) - word _ASM_LABEL(f_byte_copy) - word _ASM_LABEL(f_1byte_word_copy) - -ASLOCAL(r_strat) - word _ASM_LABEL(r_word_copy) - word _ASM_LABEL(r_byte_copy) - word _ASM_LABEL(r_half_copy) - word _ASM_LABEL(r_byte_copy) - word _ASM_LABEL(r_byte_copy) - word _ASM_LABEL(r_1byte_word_copy) - word _ASM_LABEL(r_byte_copy) - word _ASM_LABEL(r_1byte_half_copy) - word _ASM_LABEL(r_half_copy) - word _ASM_LABEL(r_byte_copy) - word _ASM_LABEL(r_1half_word_copy) - word _ASM_LABEL(r_byte_copy) - word _ASM_LABEL(r_byte_copy) - word _ASM_LABEL(r_1byte_half_copy) - word _ASM_LABEL(r_byte_copy) - word _ASM_LABEL(r_3byte_word_copy) - - text - -/*######################################################################*/ - -/* - * April 1990, Omron Corporation - * jfriedl@nff.ncl.omron.co.jp - * - * void bzero(destination, length) - * - * Clear (set to zero) LENGTH bytes of memory starting at DESTINATION. - * Note that there is no return value. - * - * This is fast. Really fast. Especially for long lengths. - */ -#define R_dest r2 -#define R_len r3 - -#define R_bytes r4 -#define R_mark_address r5 -#define R_addr r6 /* R_addr && R_temp SHARE */ -#define R_temp r6 /* R_addr && R_temp SHARE */ - -ENTRY(bzero) - /* - * If the destination is not word aligned, we'll word align - * it first to make things easier. - * - * We'll check to see first if bit #0 is set and then bit #1 - * (of the destination address). If either are set, it's - * not word aligned. - */ - bb1 0, R_dest, _ASM_LABEL(not_initially_word_aligned) - bb1 1, R_dest, _ASM_LABEL(not_initially_word_aligned) - -ASLOCAL(now_word_aligned) - /* - * before we get into the main loop, grab the - * address of the label "mark" below. - */ - or.u R_mark_address, r0, hi16(_ASM_LABEL(mark)) - or R_mark_address, R_mark_address, lo16(_ASM_LABEL(mark)) - -ASLOCAL(top_of_main_loop) -#define MAX_AT_ONE_TIME 128 - /* - * Now we find out how many words we can zero-fill in a row. - * We do this by doing something like: - * - * bytes &= 0xfffffffc; - * if (bytes > MAX_AT_ONE_TIME) - * bytes = MAX_AT_ONE_TIME; - */ - - /* - * Clear lower two bits of length to give us the number of bytes - * ALIGNED TO THE WORD LENGTH remaining to move. - */ - clr R_bytes, R_len, 2<0> - - /* if we're done clearing WORDS, jump out */ - bcnd eq0, R_bytes, _ASM_LABEL(done_doing_words) - - /* if the number of bytes > MAX_AT_ONE_TIME, do only the max */ - cmp R_temp, R_bytes, MAX_AT_ONE_TIME - bb1 lt, R_temp, 1f - - /* - * Since we're doing the max, we know exactly where we're - * jumping (the first one in the list!), so we can jump - * right there. However, we've still got to adjust - * the length, so we'll jump to where we ajust the length - * which just happens to fall through to the first store zero - * in the list. - * - * Note, however, that we're jumping to an instruction that - * would be in the delay slot for the jump in front of it, - * so if you change things here, WATCH OUT. - */ - br.n do_max - or R_bytes, r0, MAX_AT_ONE_TIME - -1: - /* - * Now we have the number of bytes to zero during this iteration, - * (which, as it happens, is the last iteration if we're here). - * We'll calculate the proper place to jump and then jump there, - * after adjusting the length. NOTE that there is a label between - * the "jmp.n" and the "subu" below... the "subu" is NOT always - * executed in the delay slot of the "jmp.n". - */ - subu R_addr, R_mark_address, R_bytes - - /* and go there (after adjusting the length via ".n") */ - jmp.n R_addr -ASLOCAL(do_max) - subu R_len, R_len, R_bytes /* NOTE: this is in the delay slot! */ - - st r0, R_dest, 0x7c /* 128 */ - st r0, R_dest, 0x78 /* 124 */ - st r0, R_dest, 0x74 /* 120 */ - st r0, R_dest, 0x70 /* 116 */ - st r0, R_dest, 0x6c /* 112 */ - st r0, R_dest, 0x68 /* 108 */ - st r0, R_dest, 0x64 /* 104 */ - st r0, R_dest, 0x60 /* 100 */ - st r0, R_dest, 0x5c /* 96 */ - st r0, R_dest, 0x58 /* 92 */ - st r0, R_dest, 0x54 /* 88 */ - st r0, R_dest, 0x50 /* 84 */ - st r0, R_dest, 0x4c /* 80 */ - st r0, R_dest, 0x48 /* 76 */ - st r0, R_dest, 0x44 /* 72 */ - st r0, R_dest, 0x40 /* 68 */ - st r0, R_dest, 0x3c /* 64 */ - st r0, R_dest, 0x38 /* 60 */ - st r0, R_dest, 0x34 /* 56 */ - st r0, R_dest, 0x30 /* 52 */ - st r0, R_dest, 0x2c /* 44 */ - st r0, R_dest, 0x28 /* 40 */ - st r0, R_dest, 0x24 /* 36 */ - st r0, R_dest, 0x20 /* 32 */ - st r0, R_dest, 0x1c /* 28 */ - st r0, R_dest, 0x18 /* 24 */ - st r0, R_dest, 0x14 /* 20 */ - st r0, R_dest, 0x10 /* 16 */ - st r0, R_dest, 0x0c /* 12 */ - st r0, R_dest, 0x08 /* 8 */ - st r0, R_dest, 0x04 /* 4 */ - st r0, R_dest, 0x00 /* 0 */ - -ASLOCAL(mark) - br.n _ASM_LABEL(top_of_main_loop) - addu R_dest, R_dest, R_bytes /* bump up the dest address */ - -ASLOCAL(done_doing_words) - bcnd ne0, R_len, 1f - jmp r1 - -1: - subu R_len, R_len, 1 - bcnd.n ne0, R_len, 1b - st.b r0, R_dest, R_len -1: - jmp r1 - -ASLOCAL(not_initially_word_aligned) - /* - * Bzero to word-align the address (at least if the length allows it). - */ - bcnd eq0, R_len, 1b - st.b r0, R_dest, 0 - addu R_dest, R_dest, 1 - mask R_temp, R_dest, 0x3 - bcnd.n eq0, R_temp, _ASM_LABEL(now_word_aligned) - subu R_len, R_len, 1 - br _ASM_LABEL(not_initially_word_aligned) - -#undef R_dest -#undef R_len -#undef R_bytes -#undef R_mark_address -#undef R_addr -#undef R_temp -#undef MAX_AT_ONE_TIME - -/* - * non-local goto - * int setjmp(label_t *); - * void longjmp(label_t*); - */ -ENTRY(setjmp) - st r1,r2,0 - st r14,r2,4 - st r15,r2,2*4 - st r16,r2,3*4 - st r17,r2,4*4 - st r18,r2,5*4 - st r19,r2,6*4 - st r20,r2,7*4 - st r21,r2,8*4 - st r22,r2,9*4 - st r23,r2,10*4 - st r24,r2,11*4 - st r25,r2,12*4 - st r26,r2,13*4 - st r27,r2,14*4 - st r28,r2,15*4 - st r29,r2,16*4 - st r30,r2,17*4 - st r31,r2,18*4 - jmp.n r1 - or r2,r0,r0 - -ENTRY(longjmp) - ld r1,r2,0 - ld r14,r2,4 - ld r15,r2,2*4 - ld r16,r2,3*4 - ld r17,r2,4*4 - ld r18,r2,5*4 - ld r19,r2,6*4 - ld r20,r2,7*4 - ld r21,r2,8*4 - ld r22,r2,9*4 - ld r23,r2,10*4 - ld r24,r2,11*4 - ld r25,r2,12*4 - ld r26,r2,13*4 - ld r27,r2,14*4 - ld r28,r2,15*4 - ld r29,r2,16*4 - ld r30,r2,17*4 - ld r31,r2,18*4 - jmp.n r1 - or r2,r0,1 - -ENTRY(read_processor_identification_register) - jmp.n r1 - ldcr r2, PID - -GLOBAL(guarded_access_start) -ENTRY(guarded_access) - cmp r9,r3,4 - bb1 eq,r9,@L145 - cmp r9,r3,2 - bb1 eq,r9,@L144 - cmp r9,r3,1 - bb1 eq,r9,@L143 - br _C_LABEL(guarded_access_bad) -@L143: - ld.b r9,r0,r2 - tb1 0, r0, 0 - st.b r9,r0,r4 - br @L142 -@L144: - ld.h r9,r0,r2 - tb1 0, r0, 0 - st.h r9,r0,r4 - br @L142 -@L145: - ld r9,r0,r2 - tb1 0, r0, 0 - st r9,r0,r4 - br @L142 - -GLOBAL(guarded_access_bad) - jmp.n r1 - or r2,r0,EFAULT - -@L142: - jmp.n r1 - or r2,r0,0 - -GLOBAL(guarded_access_end) - -/* - * void set_cpu_number(unsigned number); - * - * Sets the kernel cpu number for this cpu to the given value. - * - * Input: - * r1 return address - * r2 the number (should be 0, 1, 2, or 3). - * - * Other registers used: - * r3 temp - * r4 original PSR - * r5 temporary new PSR - */ -ENTRY(set_cpu_number) -#ifdef DEBUG - /* make sure the CPU number is valid */ - clr r3, r2, FLAG_CPU_FIELD_WIDTH<0> - bcnd ne0, r3, 1f /* bad cpu number */ -#endif - - /* going to change a control register -- disable interrupts */ - ldcr r4, PSR - set r5, r4, 1<PSR_INTERRUPT_DISABLE_BIT> - stcr r5, PSR - FLUSH_PIPELINE - - /* put in the cpu number */ - ldcr r3, SR1 /* get the flags */ - clr r3, r3, FLAG_CPU_FIELD_WIDTH<0> /* clean the slate */ - or r3, r3, r2 /* add the cpu number */ - stcr r3, SR1 /* put back */ - - /* put back the PSR to what it was before and return */ - stcr r4, PSR - FLUSH_PIPELINE - jmp r1 - -#ifdef DEBUG -1: /* bad cpu number*/ - or.u r2, r0, hi16(9f) - bsr.n _C_LABEL(panic) - or r2, r2, lo16(9f) - - data -9: string "set_cpu_number: bad CPU number %x\0" -#endif diff --git a/sys/arch/luna88k/luna88k/m88100_fp.S b/sys/arch/luna88k/luna88k/m88100_fp.S deleted file mode 100644 index c3959e4879f..00000000000 --- a/sys/arch/luna88k/luna88k/m88100_fp.S +++ /dev/null @@ -1,2516 +0,0 @@ -/* $OpenBSD: m88100_fp.S,v 1.1 2004/04/21 15:24:02 aoyama Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -/* Floating point trouble routines */ -#include "assym.h" -#include <machine/trap.h> -#include <machine/asm.h> - -#define destsize 10 - -/* Floating-Point Status Register bits */ -#define inexact 0 -#define overflow 1 -#define underflow 2 -#define divzero 3 -#define oper 4 - -#define sign 31 -#define s1size 9 -#define s2size 7 -#define dsize 5 - -#define FADDop 0x05 -#define FSUBop 0x06 -#define FCMPop 0x07 -#define FMULop 0x00 -#define FDIVop 0x0e -#define FSQRTop 0x0f -#define INTop 0x09 -#define NINTop 0x0a -#define TRNCop 0x0b - -#define s1nan 7 -#define s2nan 6 -#define s1inf 5 -#define s2inf 4 -#define s1zero 3 -#define s2zero 2 -#define sigbit 19 - -#define modehi 30 -#define modelo 29 -#define rndhi 15 -#define rndlo 14 -#define efunf 7 -#define efovf 6 -#define efinx 5 - -ASENTRY(m88100_Xfp_precise) - or r29, r3, r0 /* r29 is now the E.F. */ - subu r31, r31, 40 - st r1, r31, 32 - st r29, r31, 36 - - ld r2, r29, EF_FPSR * 4 - ld r3, r29, EF_FPCR * 4 - ld r4, r29, EF_FPECR * 4 - ld r5, r29, EF_FPHS1 * 4 - ld r6, r29, EF_FPLS1 * 4 - ld r7, r29, EF_FPHS2 * 4 - ld r8, r29, EF_FPLS2 * 4 - ld r9, r29, EF_FPPT * 4 - - - /* - * Load into r1 the return address for the 0 handlers. Looking at - * FPECR, branch to the appropriate 0 handler. However, if none of the - * 0 bits are enabled, then a floating point instruction was issued - * with the floating point unit disabled. This will cause an - * unimplemented opcode 0. - */ - - or.u r1,r0,hi16(wrapup) /* load return address of function */ - or r1,r1,lo16(wrapup) - - bb0 6,r4, 3f /* branch to FPunimp if bit set */ - br FPuimp -3: - bb0 7,r4, 4f /* branch to FPintover if bit set */ - br FPintover -4: -#if 0 - bb0 5,r4, 5f /* branch to FPpriviol if bit set */ - br FPpriviol -#endif -5: - bb0 4,r4, 6f /* branch to FPresoper if bit set */ - br FPresoper -6: - bb0 3,r4, 7f /* branch to FPdivzero if bit set */ - br FPdivzero -7: - or.u r4, r4, 0xffff - -ASLOCAL(FPuimp) - subu r31,r31,40 /* allocate stack */ - st r1,r31,36 /* save return address */ - st r3,r31,32 /* save exception frame */ - or r2,r0,T_FPEPFLT /* load trap type */ - or r3, r29, r0 - bsr _C_LABEL(m88100_trap) - ld r1,r31,36 /* recover return address */ - addu r31,r31,40 /* deallocate stack */ - jmp r1 - - /* - * To write back the results to the user registers, disable exceptions - * and the floating point unit. Write FPSR and FPCR and load the SNIP - * and SFIP. - * r5 will contain the upper word of the result - * r6 will contain the lower word of the result - */ - -ASLOCAL(wrapup) - tb1 0,r0,0 /* make sure all floating point operations */ - /* have finished */ - ldcr r10, cr1 /* load the PSR */ -#if 0 - set r10, r10, 1<PSR_FPU_DISABLE_BIT> -#endif - set r10, r10, 1<PSR_INTERRUPT_DISABLE_BIT> - stcr r10, cr1 - - ld r1, r31, 32 - ld r29, r31, 36 - addu r31, r31, 40 - - fstcr r2, FPSR /* write revised value of FPSR */ - fstcr r3, FPCR /* write revised value of FPCR */ - - /* result writeback routine */ - addu r3, r29, EF_R0 * 4 - extu r2, r9, 5<0> /* get 5 bits of destination register */ - bb0 5, r9, writesingle /* branch if destination is single */ - -/* writedouble here */ - st r5, r3 [r2] /* write high word */ - add r2, r2, 1 /* for double, the low word is the */ - /* unspecified register */ - clr r2, r2, 27<5> /* perform equivalent of mod 32 */ -ASLOCAL(writesingle) - st r6, r3 [r2] /* write low word into memory */ - jmp r1 - -/* - * Check if the numerator is zero. If the numerator is zero, then handle - * this instruction as you would a 0/0 invalid operation. - */ - -ASLOCAL(FPdivzero) - st r1,r31,0 /* save return address */ - bb1 s1size,r9,1f /* branch if numerator double */ -/* single number */ - clr r10,r5,1<sign> /* clear sign bit */ - extu r11,r6,3<29> /* grab upper bits of lower word */ - or r10,r10,r11 /* combine ones of mantissa */ - bcnd eq0,r10,resoper /* numerator is zero, handle reserved operand */ - br setbit /* set divzero bit */ -1: -/* double number */ - clr r10,r5,1<sign> /* clear sign bit */ - or r10,r10,r6 /* or high and low words */ - bcnd ne0,r10,setbit /* set divzero bit */ - -/* - * The numerator is zero, so handle the invalid operation by setting the - * invalid operation bit and branching to the user handler if there is one - * or writing a quiet NaN to the destination. - */ - -ASLOCAL(resoper) - set r2,r2,1<oper> -#ifdef HANDLER - bb0 oper,r3,noreshand /* branch to execute default handling */ - /* for reserved operands */ - bsr _handler /* branch to user handler */ - br FP_div_return -#endif - -noreshand: - set r5,r0,0<0> /* put a NaN in high word */ - set r6,r0,0<0> /* put a NaN in low word */ - br FP_div_return - /* writing to a word which may be ignored */ - /* is just as quick as checking the precision */ - /* of the destination */ - -/* - * The operation is divide by zero, so set the divide by zero bit in the - * FPSR. If the user handler is set, then go to the user handler, else - * go to the default mode. - */ - -setbit: - set r2,r2,1<divzero> -#ifdef HANDLER - bb0 divzero,r3,default /* go to default routine if no hdlr */ - bsr _handler /* execute handler routine */ - br FP_div_return -#endif - -/* - * Considering the sign of the numerator and zero, write a correctly - * signed infinity of the proper precision into the destination. - */ - -default: - bb1 dsize,r9,FPzero_double /* branch to handle double result */ -FPzero_single: - clr r10,r5,31<0> /* clear all of S1HI except sign bit */ - xor r10,r7,r10 /* xor the sign bits of the operands */ - or.u r6,r0,0x7f80 /* load single precision infinity */ - br.n FP_div_return - or r6,r6,r10 /* load correctly signed infinity */ - -FPzero_double: - clr r10,r5,31<0> /* clear all of S1HI except sign bit */ - xor r10,r7,r10 /* xor the sign bits of the operands */ - or.u r5,r0,0x7ff0 /* load double precision infinity */ - or r5,r5,r10 /* load correctly signed infinity */ - or r6,r0,r0 /* clear lower word of double */ - -FP_div_return: - ld r1,r31,0 /* load return address */ - jmp r1 - -/* - * Both NINT and TRNC require a certain rounding mode, so check which - * instruction caused the integer conversion overflow. Use a substitute - * FPCR in r1, and modify the rounding mode if the instruction is NINT - * or TRNC. - */ -ASLOCAL(FPintover) - extu r10,r9,5<11> /* extract opcode */ - cmp r11,r10,INTop /* see if instruction is INT */ - st r1,r31,0 /* save return address */ - bb1.n eq,r11,checksize /* instruction is INT, do not modify */ - /* rounding mode */ - or r1,r0,r3 /* load FPCR into r1 */ - cmp r11,r10,NINTop /* see if instruction is NINT */ - bb1 eq,r11,NINT /* instruction is NINT */ -TRNC: - clr r1,r1,2<rndlo> /* clear rounding mode bits, */ - /* instruction is TRNC */ - br.n checksize /* branch to check size */ - set r1,r1,1<rndlo> /* make rounding mode round towards */ - /* zero */ -NINT: - clr r1,r1,2<rndlo> /* make rounding mode round to */ - /* nearest */ - -/* See whether the source is single or double precision. */ - -checksize: - bb1 s2size,r9,checkdoub /* S2 is double, branch to see if */ - /* there is a false alarm */ - -/* - * An integer has more bits than the mantissa of a single precision floating - * point number, so to check for false alarms (i.e. valid conversion), simply - * check the exponents. False alarms are detected for 2**30 to (2**30) - 1 - * and -2**30 to -2**31. Only seven bits need to be looked at since an - * exception will not occur for the other half of the numbering system. - * To speed up the processing, first check to see if the exponent is 32 or - * greater. - * - * This code was originally written for the exponent in the control - * register to have the most significant bit (8 - single, 11 - double) - * flipped and sign extended. For precise exceptions, however, the most - * significant bit is only sign extended. Therefore, the code was chopped - * up so that it would work for positive values of real exponent which were - * only sign extended. - */ - -checksing: - extu r10,r7,7<20> /* internal representation for single */ - /* precision is IEEE 8 bits sign extended */ - /* to 11 bits; for real exp. = 30, the */ - /* above instruction gives a result exp. */ - /* that has the MSB flipped and sign */ - /* extended like in the IMPCR */ - cmp r11,r10,31 /* compare to 32,but exp. off by 1 */ - /* these 2 instructions to speed up valid */ - /* execution of valid cases */ - bb1 ge,r11,overflw /* valid case, perform overflow routine */ - bb1 sign,r7,checksingn /* source operand is negative */ - -/* - * If the number is positve and the exponent is greater than 30, than it is - * overflow. - */ -checksingp: - cmp r10,r10,29 /* compare to 30, but exp. off by 1 */ - bb1 gt,r10,overflw /* no false alarm, its overflow */ - br conversionsp /* finish single precision conversion */ - -/* - * If the number is negative, and the exponent is 30, or 31 with a mantissa - * of 0, then it is a false alarm. - */ -checksingn: - cmp r11,r10,30 /* compare to 31,but exp. off by 1 */ - bb1 lt,r11,conversionsn /* exp. less than 31, so convert */ - extu r10,r8,3<29> /* get upper three bits of lower */ - /* mantissa */ - mak r12,r7,20<3> /* get upper 20 bits of mantissa */ - or r10,r10,r12 /* form complete mantissa */ - bcnd eq0,r10,conversionsn /* complete conversion if mantissa */ - /* is 0 */ - br overflw /* no false alarm, its overflow */ - -/* - * False alarms are detected for 2**30 to (2**30) - 1 and -2**30 to -2**31. - * Only seven bits need to be looked at since an exception will not occur - * for the other half of the numbering system. - * To speed up the processing, first check to see if the exponent is 32 or - * greater. Since there are more mantissa bits than integer bits, rounding - * could cause overflow. (2**31) - 1 needs to be checked so that it does - * not round to 2**31, and -2**31 needs to be checked in case it rounds to - * -((2**31) + 1). - */ -checkdoub: - extu r10,r7,10<20> /* internal representation for double */ - /* precision is the same IEEE 11 bits */ - /* for real exp. = 30, the */ - /* above instruction gives a result exp. */ - /* that has the MSB flipped and sign */ - /* extended like in the IMPCR */ - cmp r11,r10,31 /* compare to 32,but exp. off by 1 */ - /* these 2 instructions to speed up valid */ - /* execution of valid cases */ - bb1 ge,r11,overflw /* valid case, perform overflow routine */ - bb1 sign,r7,checkdoubn /* source operand is negative */ - -/* - * If the exponent is not 31, then the floating point number will be rounded - * before the conversion is done. A branch table is set up with bits 4 and 3 - * being the rounding mode, and bits 2, 1, and 0 are the guard, round, and - * sticky bits. - */ -checkdoubp: - cmp r11,r10,30 /* compare to 31, but exponent off by 1 */ - bb1 eq,r11,overflw /* no false alarm, its overflow */ - extu r12,r8,1<22> /* get LSB for integer with exp. = 30 */ - mak r12,r12,1<2> /* start to set up field for branch table */ - extu r11,r8,1<21> /* get guard bit */ - mak r11,r11,1<1> /* set up field for branch table */ - or r12,r11,r12 /* set up field for branch table */ - extu r11,r8,21<0> /* get bits for sticky bit */ - bcnd eq0,r11,nostickyp /* do not set sticky */ - set r12,r12,1<0> /* set sticky bit */ -nostickyp: - rot r11,r1,0<rndlo> /* shift rounding mode to 2 LSB''s */ - mak r11,r11,2<3> /* set up field, clear other bits */ - or r12,r11,r12 /* set up field for branch table */ - lda r12,r0[r12] /* scale r12 */ - or.u r12,r12,hi16(ptable) /* load pointer into table */ - addu r12,r12,lo16(ptable) - jmp r12 - -ptable: - br conversiondp - br conversiondp - br conversiondp - br paddone - br conversiondp - br conversiondp - br paddone - br paddone - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br conversiondp - br paddone - br paddone - br paddone - br conversiondp - br paddone - br paddone - br paddone - -/* - * Add one to the bit of the mantissa which corresponds to the LSB of an - * integer. If the mantissa overflows, then there is a valid integer - * overflow conversion; otherwise, the mantissa can be converted to the - * integer. - */ -paddone: - or r10,r0,r0 /* clear r10 */ - set r10,r10,1<22> /* set LSB bit to 1 for adding */ - addu.co r8,r8,r10 /* add the 1 obtained from rounding */ - clr r11,r7,12<20> /* clear exponent and sign */ - addu.ci r11,r0,r11 /* add carry */ - bb1 20,r11,overflw /* overflow to 2**31, abort the rest */ - br.n conversiondp /* since the exp. was 30, and the exp. */ - /* did not round up to 31, the largest */ - /* number that S2 could become is 2**31-1 */ - or r7,r0,r11 /* store r11 into r7 for conversion */ - -/* - * Now check for negative double precision sources. If the exponent is 30, - * then convert the false alarm. If the exponent is 31, then check the - * mantissa bits which correspond to integer bits. If any of them are a one, - * then there is overflow. If they are zero, then check the guard, round, - * and sticky bits. - * Round toward zero and positive will not cause a roundup, but round toward - * nearest and negative may, so perform those roundings. If there is no - * overflow, then convert and return. - */ -checkdoubn: - cmp r11,r10,29 /* compare to 30, but exp. off by 1 */ - bb1 eq,r11,conversiondn /* false alarm if exp. = 30 */ - extu r10,r8,11<21> /* check upper bits of lower mantissa */ - bcnd ne0,r10,overflw /* one of the bits is a 1, so oflow */ - extu r10,r7,20<0> /* check upper bits of upper mantissa */ - bcnd ne0,r10,overflw /* one of the bits is a 1, so oflow */ - bb0 rndlo,r1,possround /* rounding mode is either round near */ - /* or round negative, which may cause */ - /* a round */ - br.n FPintov_return /* round positive, which will not */ - /* cause a round */ - set r6,r0,1<sign> -possround: - extu r12,r8,1<20> /* get guard bit */ - extu r11,r8,20<0> /* get bits for sticky bit */ - bcnd.n eq0,r11,nostickyn /* do not set sticky */ - mak r12,r12,1<1> /* set up field for branch table */ - set r12,r12,1<0> /* set sticky bit */ -nostickyn: - bb1 rndhi,r1,negative /* rounding mode is negative */ -nearest: - cmp r12,r12,3 /* are both guard and sticky set */ - bb1 eq,r12,overflw /* both guard and sticky are set, */ - /* so signal overflow */ - or r6,r0,r0 /* clear destination register r6 */ - br.n FPintov_return - set r6,r6,1<sign> /* set the sign bit and take care of */ - /* this special case */ -negative: - bcnd ne0,r12,overflw /* -2**31 will be rounded to */ - /* -(2**31+1), so signal overflow */ - or r6,r0,r0 /* clear destination register r6 */ - br.n FPintov_return - set r6,r6,1<sign> /* set the sign bit and take care of */ - /* this special case */ - - /* - * Since the exp. was 30, and there was no round-up, the largest - * number that S2 could have been was 2**31 - 1 - */ - - - /* Convert the single precision positive floating point number. */ - -conversionsp: - extu r6,r8,3<29> /* extract lower bits of integer */ - mak r6,r6,3<7> /* shift left to correct place in integer */ - mak r10,r7,20<10> /* shift left upper bits of integer */ - or r6,r6,r10 /* form most of integer */ - br.n FPintov_return - set r6,r6,1<30> /* set hidden one */ - - /* Convert the single precision negative floating point number. */ - -conversionsn: - bb1 eq,r11,exp31s /* use old r11 to see if exp. is 31 */ - extu r6,r8,3<29> /* extract lower bits of mantissa */ - mak r6,r6,3<7> /* shift left to correct place in integer */ - mak r10,r7,20<10> /* shift left upper bits of integer */ - or r6,r6,r10 /* form most of integer */ - set r6,r6,1<30> /* set hidden one */ - or.c r6,r0,r6 /* negate result */ - br.n FPintov_return - addu r6,r6,1 /* add 1 to get 2''s complement */ -exp31s: - or r6,r0,r0 /* clear r6 */ - br.n FPintov_return - set r6,r6,1<sign> /* set sign bit */ - - /* Convert the double precision positive floating point number. */ - -conversiondp: - extu r6,r8,10<22> /* extract lower bits of integer */ - mak r10,r7,20<10> /* shift left upper bits of integer */ - or r6,r6,r10 /* form most of integer */ - br.n FPintov_return - set r6,r6,1<30> /* set hidden one */ - - /* - * Convert the double precision negative floating point number. - * The number, whose exponent is 30, must be rounded before converting. - * Bits 4 and 3 are the rounding mode, and bits 2, 1, and 0 are the - * guard, round, and sticky bits for the branch table. - */ - -conversiondn: - extu r12,r8,1<22> /* get LSB for integer with exp. = 30 */ - mak r12,r12,1<2> /* start to set up field for branch table */ - extu r11,r8,1<21> /* get guard bit */ - mak r11,r11,1<1> /* set up field for branch table */ - or r12,r11,r12 /* set up field for branch table */ - extu r11,r8,21<0> /* get bits for sticky bit */ - bcnd eq0,r11,nostkyn /* do not set sticky */ - set r12,r12,1<0> /* set sticky bit */ -nostkyn: - rot r11,r1,0<rndlo> /* shift rounding mode to 2 LSB''s */ - mak r11,r11,2<3> /* set up field, clear other bits */ - or r12,r11,r12 /* set up field for branch table */ - lda r12,r0[r12] /* scale r12 */ - or.u r12,r12,hi16(ntable) /* load pointer into table */ - addu r12,r12,lo16(ntable) - jmp r12 - -ntable: - br nnoaddone - br nnoaddone - br nnoaddone - br naddone - br nnoaddone - br nnoaddone - br naddone - br naddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br naddone - br naddone - br naddone - br nnoaddone - br naddone - br naddone - br naddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - br nnoaddone - -/* - * Add one to the mantissa, and check to see if it overflows to -2**31. - * The conversion is done in nnoaddone. - */ - -naddone: - or r10,r0,r0 /* clear r10 */ - set r10,r10,1<22> /* set LSB bit to 1 for adding */ - add.co r8,r8,r10 /* add the 1 obtained from rounding */ - clr r7,r7,12<20> /* clear exponent and sign */ - add.ci r7,r0,r7 /* add carry */ - bb1 20,r7,maxneg /* rounded to -2**31,handle separately */ - /* the exponent was originally 30 */ -nnoaddone: - extu r6,r8,11<22> /* extract lower bits of integer */ - mak r10,r7,20<10> /* shift left upper bits of integer */ - or r6,r6,r10 /* form most of integer */ - set r6,r6,1<30> /* set hidden one */ - or.c r6,r0,r6 /* negate integer */ - br.n FPintov_return - addu r6,r6,1 /* add 1 to get 2''s complement */ - -maxneg: - or r6,r0,r0 /* clear integer */ - br.n FPintov_return - set r6,r6,1<sign> /* set sign bit */ - - /* - * For valid overflows, check to see if the integer overflow user - * handler is set. If it is set, then go to user handler, else write - * the correctly signed largest integer. - */ - -overflw: - set r2,r2,1<oper> -#ifdef HANDLER - bb0 oper,r3,nohandler /* do not go to user handler routine */ - bsr _handler /* go to user handler routine */ - br FPintov_return -nohandler: -#endif - bb0.n sign,r7,FPintov_return /* if positive then return */ - set r6,r6,31<0> /* set result to largest positive int */ - or.c r6,r0,r6 /* negate r6, giving largest negative */ - /* integer */ - -FPintov_return: - ld r1,r31,0 /* load return address from memory */ - jmp r1 - -/* - * Some instructions only have the S2 operations, so clear S1HI and S1LO - * for those instructions so that the previous contents of S1HI and S1LO - * do not influence this instruction. - */ - -ASLOCAL(FPresoper) - st r1, r31, 0 - extu r10,r9,5<11> /* extract opcode */ -#if 0 - cmp r11,r10,FSQRTop /* compare to FSQRT */ - bb1 eq,r11,S1clear /* clear S1 if instruction only had S2 operand */ -#endif - cmp r11,r10,INTop /* compare to INT */ - bb1 eq,r11,S1clear /* clear S1 if instruction only had S2 operand */ - cmp r11,r10,NINTop /* compare to NINT */ - bb1 eq,r11,S1clear /* clear S1 if instruction only had S2 operand */ - cmp r11,r10,TRNCop /* compare to TRNC */ - bb0 eq,r11,opercheck /* check for reserved operands */ - -ASLOCAL(S1clear) - or r5,r0,r0 /* clear any NaN''s, denorms, or infinities */ - or r6,r0,r0 /* that may be left in S1HI,S1LO from a */ - /* previous instruction */ - -/* - * r12 contains the following flags: - * bit 9 -- s1sign - * bit 8 -- s2sign - * bit 7 -- s1nan - * bit 6 -- s2nan - * bit 5 -- s1inf - * bit 4 -- s2inf - * bit 3 -- s1zero - * bit 2 -- s2zero - * bit 1 -- s1denorm - * bit 0 -- s2denorm - */ - -/* - * Using code for both single and double precision, check if S1 is either - * a NaN or infinity and set the appropriate flags in r12. Then check if - * S2 is a NaN or infinity. If it is a NaN, then branch to the NaN routine. - */ - -ASLOCAL(opercheck) - extu r10,r5,11<20> /* internal representation for double */ - bb1.n s1size,r9,S1NaNdoub /* S1 is double precision */ - or r12,r0,r0 /* clear operand flag register */ -ASLOCAL(S1NaNsing) - xor r10,r10,0x0080 /* internal representation for single */ - ext r10,r10,8<0> /* precision is IEEE 8 bits sign extended */ - /* to 11 bits; for real exp. > 0, the */ - /* above instructions gives a result exp. */ - /* that has the MSB flipped and sign */ - /* extended like in the IMPCR */ - cmp r11,r10,127 /* Is exponent equal to IEEE 255 (here 127) */ - bb1 ne,r11,S2NaN /* source 1 is not a NaN or infinity */ - mak r10,r5,20<0> /* load r10 with upper bits of S1 mantissa */ - extu r11,r6,3<29> /* get 3 upper bits of lower word */ - or r11,r10,r11 /* combine any existing 1 */ - bcnd eq0,r11,noS1NaNs /* since r11 can only hold 0 or a */ - /* > 0 number, branch to noS1NaN when eq0 */ - br.n S2NaN /* see if S2 has a NaN */ - set r12,r12,1<s1nan> /* indicate that S1 has a NaN */ -ASLOCAL(noS1NaNs) - br.n S2NaN /* check contents of S2 */ - set r12,r0,1<s1inf> /* indicate that S1 has an infinity */ - -ASLOCAL(S1NaNdoub) - xor r10,r10,0x0400 /* precision is the same IEEE 11 bits */ - /* The above instructions gives a result exp. */ - /* that has the MSB flipped and sign */ - /* extended like in the IMPCR */ - cmp r11,r10,1023 /* Is exp. equal to IEEE 2047 (internal 1023) */ - bb1 ne,r11,S2NaN /* source 1 is not a NaN or infinity */ - mak r10,r5,20<0> /* load r10 with upper bits of S1 mantissa */ - or r11,r6,r10 /* combine existing 1''s of mantissa */ - bcnd eq0,r11,noS1NaNd /* since r11 can only hold 0 or a > 0 */ - /* number, branch to noS1NaN when eq0 */ - br.n S2NaN /* see if S2 has a NaN */ - set r12,r12,1<s1nan> /* indicate that S1 has a NaN */ -ASLOCAL(noS1NaNd) - set r12,r0,1<s1inf> /* indicate that S1 has an infinity */ - -ASLOCAL(S2NaN) - bb1.n s2size,r9,S2NaNdoub /* S1 is double precision */ - extu r10,r7,11<20> /* internal representation for double */ -ASLOCAL(S2NaNsing) - xor r10,r10,0x0080 /* internal representation for single */ - ext r10,r10,8<0> /* precision is IEEE 8 bits sign extended */ - /* to 11 bits; for real exp. > 0, the */ - /* above instruction gives a result exp. */ - /* that has the MSB flipped and sign */ - /* extended like in the IMPCR */ - cmp r11,r10,127 /* Is exponent equal to IEEE 255 (here 127) */ - bb1 ne,r11,inf /* source 2 is not a NaN or infinity */ - mak r10,r7,20<0> /* load r10 with upper bits of S1 mantissa */ - extu r11,r8,3<29> /* get 3 upper bits of lower word */ - or r11,r10,r11 /* combine any existing 1''s */ - bcnd eq0,r11,noS2NaNs /* since r11 can only hold 0 or a > 0 */ - /* number, branch to noS2NaNs when eq0 */ - br.n _ASM_LABEL(NaN) /* branch to NaN routine */ - set r12,r12,1<s2nan> /* indicate that s2 has a NaN */ -ASLOCAL(noS2NaNs) - bb0 s1nan,r12, 1f /* branch to NaN if S1 is a NaN */ - br _ASM_LABEL(NaN) -1: - br.n _ASM_LABEL(infinity) /* If S1 had a NaN we would have */ - /* already branched, and S2 does not have a */ - /* NaN, but it does have an infinity, so */ - /* branch to handle the finity */ - set r12,r12,1<s2inf> /* indicate that S2 has an infinity */ - -ASLOCAL(S2NaNdoub) - xor r10,r10,0x0400 /* precision is the same IEEE 11 bits */ - /* The above instruction gives a result exp. */ - /* that has the MSB flipped and sign */ - /* extended like in the IMPCR */ - cmp r11,r10,1023 /* Is exp. equal to IEEE 2047 (internal 1023) */ - bb1 ne,r11,inf /* source 2 is not a NaN or infinity */ - mak r10,r7,20<0> /* load r10 with upper bits of S2 mantissa */ - or r11,r8,r10 /* combine existing 1''s of mantissa */ - bcnd eq0,r11,noS2NaNd /* since r11 can only hold 0 or a > 0 */ - /* number, branch to noS2NaNd when eq0 */ - br.n _ASM_LABEL(NaN) /* branch to NaN routine */ - set r12,r12,1<s2nan> /* indicate that s2 has a NaN */ -ASLOCAL(noS2NaNd) - bb0 s1nan,r12,1f /* branch to NaN if S1 is a NaN */ - br _ASM_LABEL(NaN) -1: - br.n _ASM_LABEL(infinity) /* If S1 had a NaN we would have */ - /* already branched, and S2 does not have a */ - /* NaN, but it does have an infinity, so */ - /* branch to handle the finity */ - set r12,r12,1<s2inf> /* indicate that S2 has an infinity */ - -/* - * If S2 was a NaN, the routine would have already branched to NaN. If S1 - * is a NaN, then branch to NaN. If S1 is not a NaN and S2 is infinity, then - * we would have already branched to infinity. If S1 is infinity, then branch. - * If the routine still has not branched, then branch to denorm, the only - * reserved operand left. - */ - -ASLOCAL(inf) - bb0 s1nan,r12,1f /* branch if S1 has a NaN and S2 does not */ - br _ASM_LABEL(NaN) -1: - bb0 s1inf,r12,2f /* Neither S1 or S2 has a NaN, and we would */ - /* have branched already if S2 had an */ - /* infinity, so branch if S1 is infinity */ - br _ASM_LABEL(infinity) -2: - br _ASM_LABEL(denorm) /* branch to denorm, the only */ - /* remaining alternative */ - -/* - * First check for an underflow user handler. If there is not one, then - * branch to the routine to make a denormalized number. Before branching - * to the underflow user handler, add 192 to a single precision exponent - * and 1536 to a double precision exponent. - */ - -ASLOCAL(FPunderflow) - st r1,r31,0 /* save return address */ - set r2,r2,1<underflow> - set r2,r2,1<inexact> -#ifdef HANDLER - bb0 efunf,r12,FPU_denorm /* jump to default procedure */ - bb1 destsize,r12,doubleprec /* double precision destination */ -singleprec: - or.u r6,r0,0x0c00 /* load exponent adjust 192 */ - br.n callundhand /* branch to call handler for user handler */ - add r12,r6,r12 /* adjust single precision exponent */ -doubleprec: - or.u r6,r0,0x6000 /* load exponent adjust 1536 */ - add r12,r6,r12 /* adjust double precision exponent */ -callundhand: - bsr _handler /* call handler for user handler */ - br Ureturn -#endif - -/* - * Now the floating point number, which has an exponent smaller than what - * IEEE allows, must be denormalized. Denormalization is done by calculating - * the difference between a denormalized exponent and an underflow exponent - * and shifting the mantissa by that amount. A one may need to be subtracted - * from the LSB if a one was added during rounding. - * r9 is used to contain the guard, round, sticky, and an inaccuracy bit in - * case some bits were shifted off the mantissa during denormalization. - * r9 will contain: - * bit 4 -- new addone if one added during rounding after denormalization - * bit 3 -- inaccuracy flag caused by denormalization or pre-denormalization - * inexactness - * bit 2 -- guard bit of result - * bit 1 -- round bit of result - * bit 0 -- sticky bit of result - */ - -FPU_denorm: - bb1.n destsize,r12,Udouble /* denorm for double */ - extu r9,r10,3<26> /* load r9 with grs */ -Usingle: - mak r5,r10,21<3> /* extract high 21 bits of mantissa */ - extu r6,r11,3<29> /* extract low 3 bits of mantissa */ - or r11,r5,r6 /* form 24 bits of mantissa */ - -/* See if the addone bit is set and unround if it is. */ - bb0.n 25,r10,nounrounds /* do not unround if addone bit clear */ - extu r6,r12,12<20> /* extract signed exponent from IMPCR */ -unrounds: - subu r11,r11,1 /* subtract 1 from mantissa */ - -/* - * If the hidden bit is cleared after subtracting the one, then the one added - * during the rounding must have propagated through the mantissa. The exponent - * will need to be decremented. - */ - bb1 23,r11,nounrounds /* if hidden bit is set,then exponent */ - /* does not need to be decremented */ -decexps: - sub r6,r6,1 /* decrement exponent 1 */ - set r11,r11,1<23> /* set the hidden bit */ - -/* - * For both single and double precision, there are cases where it is easier - * and quicker to make a special case. Examples of this are if the shift - * amount is only 1 or 2, or all the mantissa is shifted off, or all the - * mantissa is shifted off and it is still shifting, or, in the case of - * doubles, if the shift amount is around the boundary of MANTLO and MANTHI. - */ - -nounrounds: - or r8,r0,lo16(0x00000f81) /* load r8 with -127 in decimal */ - /* for lowest 12 bits */ - sub r7,r8,r6 /* find difference between two exponents, */ - /* this amount is the shift amount */ - cmp r6,r7,3 /* check to see if r7 contains 3 or more */ - bb1 ge,r6,threesing /* br to code that handles shifts of >=3 */ - cmp r6,r7,2 /* check to see if r7 contains 2 */ - bb1 eq,r6,twosing /* br to code that handles shifts of 2 */ -one: - rot r9,r9,0<1> /* rotate roundoff register once, this places */ - /* guard in round and round in sticky */ - bb0 31,r9,nosticky1s /* do not or round and sticky if sticky is */ - /* 0, this lost bit will be cleared later */ - set r9,r9,1<0> /* or round and sticky */ -nosticky1s: - bb0 0,r11,guardclr1s /* do not set guard bit if LSB = 0 */ - set r9,r9,1<2> /* set guard bit */ -guardclr1s: - extu r11,r11,31<1> /* shift mantissa right 1 */ - br.n round /* round result */ - mak r9,r9,3<0> /* clear bits lost during rotation */ - -twosing: - rot r9,r9,0<2> /* rotate roundff register twice, this places */ - /* guard in sticky */ - bb0 30,r9,nosticky2s /* do not or guard and sticky if stick is 0 */ - /* this lost bit will be cleared later */ - br.n noround2s /* skip or old guard and old round if old */ - /* sticky set */ - set r9,r9,1<0> /* or guard and sticky */ -nosticky2s: - bb0 31,r9,noround2s /* do not or guard and round if round is 0 */ - /* this lost bit will be cleared later */ - set r9,r9,1<0> /* or guard and round */ -noround2s: - bb0 0,r11,roundclr2s /* do not set round bit if LSB = 0 */ - set r9,r9,1<1> /* set round bit */ -roundclr2s: - bb0 1,r11,guardclr2s /* do not set guard bit if LSB + 1 = 0 */ - set r9,r9,1<2> /* set guard bit */ -guardclr2s: - extu r11,r11,30<2> /* shift mantissa right 2 */ - br.n round /* round result */ - mak r9,r9,3<0> /* clear bits lost during rotation */ - -threesing: - bb1 0,r9,noguard3s /* check sticky initially */ - /* sticky is set, forget most of the oring */ -nosticky3s: - bb0 1,r9,noround3s /* check round initially, do not set sticky */ - br.n noguard3s /* forget most of the rest of oring */ - set r9,r9,1<0> /* if round is clear,set sticky if round set */ -noround3s: - bb0.n 2,r9,noguard3s /* check guard initially, do not set sticky */ - clr r9,r9,2<1> /* clear the original guard and round for when */ - /* you get to round section */ - set r9,r9,1<0> /* if guard is clear,set sticky if guard set */ -noguard3s: - cmp r6,r7,23 /* check if # of shifts is <=23 */ - bb1 gt,r6,s24 /* branch to see if shifts = 24 */ - sub r6,r7,2 /* get number of bits to check for sticky */ - mak r6,r6,5<5> /* shift width into width field */ - mak r8,r11,r6 /* mask off shifted bits -2 */ - ff1 r8,r8 /* see if r8 has any ones */ - bb1 5,r8,nostky23 /* do not set sticky if no ones found */ - set r9,r9,1<0> /* set sticky bit */ -nostky23: - or r8,r0,34 /* start code to get new mantissa plus two */ - /* extra bits for new round and new guard */ - /* bits */ - subu r8,r8,r7 - mak r8,r8,5<5> /* shift field width into second five bits */ - extu r6,r6,5<5> /* shift previous shifted -2 into offset field */ - or r6,r6,r8 /* complete field */ - extu r11,r11,r6 /* form new mantissa with two extra bits */ - - bb0 0,r11,nornd3s /* do not set new round bit */ - set r9,r9,1<1> /* set new round bit */ -nornd3s: - bb0 1,r11,nogrd3s /* do not set new guard bit */ - set r9,r9,1<2> /* set new guard bit */ -nogrd3s: - br.n round /* round mantissa */ - extu r11,r11,30<2> /* shift off remaining two bits */ - -s24: - cmp r6,r7,24 /* check to see if # of shifts is 24 */ - bb1 gt,r6,s25 /* branch to see if shifts = 25 */ - bb1 0,r9,nostky24 /* skip checking if old sticky set */ - extu r8,r11,22<0> /* prepare to check bits that will be shifted */ - /* into the sticky */ - ff1 r8,r8 /* see if there are any 1''s */ - bb1 5,r8,nostky24 /* do not set sticky if no ones found */ - set r9,r9,1<0> /* set sticky bit */ -nostky24: - bb0 22,r11,nornd24 /* do not set new round bit */ - set r9,r9,1<1> /* set new round bit */ -nornd24: - set r9,r9,1<2> /* set new guard bit,this is hidden bit */ - br.n round /* round mantissa */ - or r11,r0,r0 /* clear r11, all of mantissa shifted off */ - -s25: - cmp r6,r7,25 /* check to see if # of shifts is 25 */ - bb1 gt,r6,s26 /* branch to execute for shifts => 26 */ - bb1 0,r9,nostky25 /* skip checking if old sticky set */ - extu r8,r11,23<0> /* prepare to check bits that will be shifted */ - /* into the sticky */ - ff1 r8,r8 /* see if there are any 1''s */ - bb1 5,r8,nostky25 /* do not set sticky if no ones found */ - set r9,r9,1<0> /* set sticky bit */ -nostky25: - set r9,r9,1<1> /* set new round bit,this is hidden bit */ - clr r9,r9,1<2> /* clear guard bit since nothing shifted in */ - br.n round /* round and assemble result */ - or r11,r0,r0 /* clear r11, all of mantissa shifted off */ - -s26: - set r9,r9,1<0> /* set sticky bit,this contains hidden bit */ - clr r9,r9,2<1> /* clear guard and round bits since nothing */ - /* shifted in */ - br.n round /* round and assemble result */ - or r11,r0,r0 /* clear mantissa */ - -Udouble: - mak r5,r10,21<0> /* extract upper bits of mantissa */ - bb0.n 25,r10,nounroundd /* do not unround if addone bit clear */ - extu r6,r12,12<20> /* extract signed exponenet from IMPCR */ -unroundd: - or r8,r0,1 - subu.co r11,r11,r8 /* subtract 1 from mantissa */ - subu.ci r5,r5,r0 /* subtract borrow from upper word */ - bb1 20,r5,nounroundd /* if hidden bit is set, then exponent does */ - /* not need to be decremented */ -decexpd: - sub r6,r6,1 /* decrement exponent 1 */ - set r5,r5,1<20> /* set the hidden bit */ - -nounroundd: - or r8,r0,lo16(0x00000c01) /* load r8 with -1023 in decimal */ - /* for lowest 12 bits */ - sub r7,r8,r6 /* find difference between two exponents, */ - /* this amount is the shift amount */ - cmp r6,r7,3 /* check to see if r7 contains 3 or more */ - bb1 ge,r6,threedoub /* br to code that handles shifts of >=3 */ - cmp r6,r7,2 /* check to see if r7 contains 2 */ - bb1 eq,r6,twodoub /* br to code that handles shifts of 2 */ - -onedoub: - rot r9,r9,0<1> /* rotate roundoff register once, this places */ - /* guard in round and round in sticky */ - bb0 31,r9,nosticky1d/* do not or round and sticky if sticky is 0 */ - /* this lost bit will be cleared later */ - set r9,r9,1<0> /* or old round and old sticky into new sticky */ -nosticky1d: - bb0 0,r11,guardclr1d /* do not set new guard bit if old LSB = 0 */ - set r9,r9,1<2> /* set new guard bit */ -guardclr1d: - extu r11,r11,31<1> /* shift lower mantissa over 1 */ - mak r6,r5,1<31> /* shift off low bit of high mantissa */ - or r11,r6,r11 /* load high bit onto lower mantissa */ - extu r5,r5,20<1> /* shift right once upper 20 bits of mantissa */ - br.n round /* round mantissa and assemble result */ - mak r9,r9,3<0> /* clear bits lost during rotation */ - -twodoub: - rot r9,r9,0<2> /* rotate roundoff register twice, this places */ - /* old guard into sticky */ - bb0 30,r9,nosticky2d /* do not or old guard and old sticky if */ - /* old sticky is 0 */ - br.n noround2d /* skip or of old guard and old round if old */ - /* sticky set */ - set r9,r9,1<0> /* or old guard and old sticky into new sticky */ -nosticky2d: - bb0 31,r9,noround2d /* do not or old guard and old round if */ - /* old round is 0 */ - set r9,r9,1<0> /* or old guard and old round into new sticky */ -noround2d: - bb0 0,r11,roundclr2d /* do not set round bit if old LSB = 0 */ - set r9,r9,1<1> /* set new round bit */ -roundclr2d: - bb0 1,r11,guardclr2d /* do not set guard bit if old LSB + 1 = 0 */ - set r9,r9,1<2> /* set new guard bit */ -guardclr2d: - extu r11,r11,30<2> /* shift lower mantissa over 2 */ - mak r6,r5,2<30> /* shift off low bits of high mantissa */ - or r11,r6,r11 /* load high bit onto lower mantissa */ - extu r5,r5,19<2> /* shift right twice upper 19 bits of mantissa */ - br.n round /* round mantissa and assemble result */ - mak r9,r9,3<0> /* clear bits lost during rotation */ - -threedoub: - bb1 0,r9,noguard3d /* checky sticky initially */ - /* sticky is set, forget most of rest of oring */ -nosticky3d: - bb0 1,r9,noround3d /* check old round, do not set sticky if */ - /* old round is clear, set otherwise */ - br.n noguard3d /* sticky is set, forget most of rest of oring */ - set r9,r9,1<0> /* set sticky if old round is set */ -noround3d: - bb0 2,r9,noguard3d /* check old guard, do not set sticky if 0 */ - clr r9,r9,2<1> /* clear the original guard and round for when */ - /* you get to round section */ - set r9,r9,1<0> /* set sticky if old guard is set */ -noguard3d: - cmp r6,r7,32 /* do I need to work with a 1 or 2 word mant. */ - /* when forming sticky, round and guard */ - bb1 gt,r6,d33 /* jump to code that handles 2 word mantissas */ - sub r6,r7,2 /* get number of bits to check for sticky */ - mak r6,r6,5<5> /* shift width into width field */ - mak r8,r11,r6 /* mask off shifted bits -2 */ - ff1 r8,r8 /* see if r8 has any ones */ - bb1 5,r8,nostky32 /* do not set sticky if no ones found */ - set r9,r9,1<0> /* set sticky bit */ -nostky32: - or r8,r0,34 /* start code to get new mantissa plus two */ - /* extra bits for new round and new guard bits, */ - /* the upper word bits will be shifted after */ - /* the round and guard bits are handled */ - subu r8,r8,r7 - mak r8,r8,5<5> /* shift field width into second five bits */ - extu r6,r6,5<5> /* shift previous shifted -2 into offset field */ - or r6,r6,r8 /* complete bit field */ - extu r11,r11,r6 /* partially form new low mantissa with 2 more */ - /* bits */ - bb0 0,r11,nornd32d /* do not set new round bit */ - set r9,r9,1<1> /* set new round bit */ -nornd32d: - bb0 1,r11,nogrd32d /* do not set new guard bit */ - set r9,r9,1<2> /* set new guard bit */ -nogrd32d: - extu r11,r11,30<2> /* shift off remaining two bits */ - mak r6,r7,5<5> /* shift field width into second 5 bits, if the */ - /* width is 32, then these bits will be 0 */ - or r8,r0,32 /* load word length into r8 */ - sub r8,r8,r7 /* form offset for high bits moved to low word */ - or r6,r6,r8 /* form complete bit field */ - mak r6,r5,r6 /* get shifted bits of high word */ - or r11,r6,r11 /* form new low word of mantissa */ - bcnd ne0,r8,regular33 /* do not adjust for special case of r8 */ - br.n round /* containing zeros, which would cause */ - or r5,r0,r0 /* all of the bits to be extracted under */ - /* the regular method */ -regular33: - mak r6,r7,5<0> /* place lower 5 bits of shift into r6 */ - mak r8,r8,5<5> /* shift r8 into width field */ - or r6,r6,r8 /* form field for shifting of upper bits */ - br.n round /* round and assemble result */ - extu r5,r5,r6 /* form new high word mantissa */ - -d33: - cmp r6,r7,33 /* is the number of bits to be shifted is 33? */ - bb1 gt,r6,d34 /* check to see if # of bits is 34 */ - bb1 0,r9,nostky33 /* skip checking if old sticky set */ - mak r6,r11,31<0> /* check bits that will be shifted into sticky */ - ff1 r8,r8 /* check for ones */ - bb1 5,r8,nostky33 /* do not set sticky if there are no ones */ - set r9,r9,1<0> /* set new sticky bit */ -nostky33: - bb0 31,r11,nornd33 /* do not set round if bit is not a 1 */ - set r9,r9,1<1> /* set new round bit */ -nornd33: - bb0 0,r5,nogrd33 /* do not set guard bit if bit is not a 1 */ - set r9,r9,1<2> /* set new guard bit */ -nogrd33: - extu r11,r5,31<1> /* shift high bits into low word */ - br.n round /* round and assemble result */ - or r5,r0,r0 /* clear high word */ - -d34: - cmp r6,r7,34 /* is the number of bits to be shifted 34? */ - bb1 gt,r6,d35 /* check to see if # of bits is >= 35 */ - bb1 0,r9,nostky34 /* skip checking if old sticky set */ - ff1 r8,r11 /* check bits that will be shifted into sticky */ - bb1 5,r8,nostky34 /* do not set sticky if there are no ones */ - set r9,r9,1<0> /* set new sticky bit */ -nostky34: - bb0 0,r5,nornd34 /* do not set round if bit is not a 1 */ - set r9,r9,1<1> /* set new round bit */ -nornd34: - bb0 1,r5,nogrd34 /* do not set guard bit if bit is not a 1 */ - set r9,r9,1<2> /* set new guard bit */ -nogrd34: - extu r11,r5,30<2> /* shift high bits into low word */ - br.n round /* round and assemble result */ - or r5,r0,r0 /* clear high word */ - -d35: - cmp r6,r7,52 /* see if # of shifts is 35 <= X <= 52 */ - bb1 gt,r6,d53 /* check to see if # of shifts is 52 */ - bb1.n 0,r9,nostky35 /* skip checking if old sticky set */ - sub r7,r7,34 /* subtract 32 from # of shifts so that opera- */ - /* tions can be done on the upper word, and */ - /* then subtract two more checking guard and */ - /* sticky bits */ - ff1 r8,r11 /* see if lower word has a bit for sticky */ - bb1 5,r8,stkycheck35 /* see if upper word has any sticky bits */ - br.n nostky35 /* quit checking for sticky */ - set r9,r9,1<0> /* set sticky bit */ -stkycheck35: - mak r6,r7,5<5> /* place width into width field */ - mak r8,r5,r6 /* mask off shifted bits - 2 */ - ff1 r8,r8 /* see if r8 has any ones */ - bb1 5,r8,nostky35 /* do not set sticky if no ones found */ - set r9,r9,1<0> /* set sticky bit */ -nostky35: - or r8,r0,32 /* look at what does not get shifted off plus */ - /* round and sticky, remember that the r7 value */ - /* was adjusted so that it did not include */ - /* new round or new sticky in shifted off bits */ - subu r8,r8,r7 /* complement width */ - mak r8,r8,5<5> /* shift width into width field */ - or r8,r7,r8 /* add offset field */ - extu r11,r5,r8 /* extract upper bits into low word */ - bb0 0,r11,nornd35 /* do not set new round bit */ - set r9,r9,1<1> /* set new round bit */ -nornd35: - bb0 1,r11,nogrd35 /* do not set new guard bit */ - set r9,r9,1<2> /* set new guard bit */ -nogrd35: - extu r11,r11,30<2> /* shift off remaining guard and round bits */ - br.n round /* round and assemble result */ - or r5,r0,r0 /* clear high word */ - -d53: - cmp r6,r7,53 /* check to see if # of shifts is 53 */ - bb1 gt,r6,d54 /* branch to see if shifts = 54 */ - bb1 0,r9,nostky53 /* skip checking if old sticky set */ - ff1 r8,r11 /* see if lower word has a bit for sticky */ - bb1 5,r8,stkycheck53 /* see if upper word has any sticky bits */ - br.n nostky53 /* quit checking for sticky */ - set r9,r9,1<0> /* set sticky bit */ -stkycheck53: - mak r6,r5,19<0> /* check bits that are shifted into sticky */ - ff1 r8,r6 /* see if r6 has any ones */ - bb1 5,r8,nostky53 /* do not set sticky if no ones found */ - set r9,r9,1<0> /* set sticky bit */ -nostky53: - bb0 19,r5,nornd53 /* do not set new round bit */ - set r9,r9,1<1> /* set new round bit */ -nornd53: - set r9,r9,1<2> /* set new guard bit,this is hidden bit */ - or r5,r0,r0 /* clear high word */ - br.n round /* round and assemble result */ - or r11,r0,r0 /* clear low word */ - -d54: - cmp r6,r7,54 /* check to see if # of shifts is 54 */ - bb1 gt,r6,d55 /* branch to execute for shifts =>55 */ - bb1 0,r9,nostky54 /* skip checking if old sticky set */ - ff1 r8,r11 /* see if lower word has a bit for sticky */ - bb1 5,r8,stkycheck54 /* see if upper word has any sticky bits */ - br.n nostky54 /* quit checking for sticky */ - set r9,r9,1<0> /* set sticky bit */ -stkycheck54: - mak r6,r5,20<0> /* check bits that are shifted into sticky */ - ff1 r8,r6 /* see if r6 has any ones */ - bb1 5,r8,nostky54 /* do not set sticky if no ones found */ - set r9,r9,1<0> /* set sticky bit */ -nostky54: - set r9,r9,1<1> /* set new round bit,this is hidden bit */ - clr r9,r9,1<2> /* clear guard bit since nothing shifted in */ - or r5,r0,r0 /* clear high word */ - br.n round /* round and assemble result */ - or r11,r0,r0 /* clear low word */ - -d55: - set r9,r9,1<0> /* set new sticky bit,this contains hidden bit */ - clr r9,r9,2<1> /* clear guard and round bits since nothing */ - /* shifted in */ - or r5,r0,r0 /* clear high word */ - or r11,r0,r0 /* clear low word */ - - -/* The first item that the rounding code does is see if either guard, round, */ -/* or sticky is set. If all are clear, then there is no denormalization loss */ -/* and no need to round, then branch to assemble answer. */ -/* For rounding, a branch table is set up. The left two most bits are the */ -/* rounding mode. The third bit is either the LSB of the mantissa or the */ -/* sign bit, depending on the rounding mode. The three LSB''s are the guard, */ -/* round and sticky bits. */ - -round: - ff1 r8,r9 /* see if there is denormalization loss */ - bb1 5,r8,assemble /* no denormalization loss or inexactness */ - extu r6,r10,2<modelo> /* extract rounding mode */ - bb1.n modehi,r10,signext /* use sign bit instead of LSB */ - mak r6,r6,2<4> /* shift over rounding mode */ - extu r7,r11,1<0> /* extract LSB */ - br.n grs /* skip sign extraction */ - mak r7,r7,1<3> /* shift over LSB */ -signext: - extu r7,r10,1<31> /* extract sign bit */ - mak r7,r7,1<3> /* shift sign bit over */ -grs: - or r6,r6,r7 - or r6,r6,r9 /* or in guard, round, and sticky */ - or.u r1,r0,hi16(roundtable) /* form address of branch table */ - or r1,r1,lo16(roundtable) - lda r6,r1[r6] /* scale offset into branch table */ - jmp.n r6 /* jump to branch table */ - set r9,r9,1<3> /* set inexact flag in r9 */ - -roundtable: - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br addone - br addone - br addone - br noaddone - br noaddone - br noaddone - br noaddone - br addone - br addone - br addone - br addone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br addone - br addone - br addone - br addone - br addone - br addone - br addone - br noaddone - br addone - br addone - br addone - br addone - br addone - br addone - br addone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - br noaddone - -/* Round by adding a one to the LSB of the mantissa. */ -addone: - or r6,r0,1 /* load a 1 into r6 so that add.co can be used */ - add.co r11,r11,r6 /* add a one to the lower word of result */ - bb0.n destsize,r12,noaddone /* single result,forget carry */ - set r9,r9,1<4> /* indicate that a 1 has been added */ - add.ci r5,r5,r0 /* propagate carry into high word */ - - -/* Branch to inexact user handler if there is one. */ - -noaddone: - set r2,r2,1<inexact> - set r2,r2,1<underflow> -#ifdef HANDLER - bb1 efinx,r12,modformdef /* branch to modify form for user */ - /* handler */ -#endif - - -/* Assemble the result of the denormalization routine for writeback to the */ -/* destination register. The exponent of a denormalized number is zero, */ -/* so simply assemble the sign and the new mantissa. */ - -assemble: - bb1 destsize,r12,doubassem /* assemble double result */ - bb0 sign,r10,exassems /* exit assemble if sign is zero */ - set r11,r11,1<sign> /* make result negative */ -exassems: - br Ureturn - -doubassem: - bb0.n sign,r10,signclr /* do not set sign in r10 */ - or r10,r5,r0 /* load high word from r5 into r10 */ - set r10,r10,1<sign> /* high word with sign loaded */ -signclr: - br Ureturn - - -/* modfordef modifies the result of denormalization to the input format of */ -/* the inexact user handler. This input format is the same format that */ -/* MANTHI, MANTLO, and IMPCR were initially loaded with. */ - -#ifdef HANDLER -modformdef: - clr r12,r12,12<20> /* clear result exponent,IMPCR complete */ - clr r10,r10,4<25> /* clear old guard,round,sticky,and addone */ - mak r5,r9,3<26> /* make grs field */ - bb0.n 4,r9,newaddone /* do not set new addone in MANTHI */ - or r10,r5,r10 /* or in new grs field */ - set r10,r10,1<25> /* set new addone */ -newaddone: - bb1.n destsize,r12,moddefd /* branch to handle double precision */ - clr r10,r10,21<0> /* clear upper bits of old mantissa */ -moddefs: - extu r5,r11,20<3> /* extract upper bits */ - or r10,r5,r10 /* MANTHI complete */ - bsr.n _handler /* execute user handler for inexact */ - rot r11,r11,0<3> /* MANTLO complete */ - br Ureturn -moddefd: - bsr.n _handler /* execute user handler for inexact */ - or r10,r5,r10 /* MANTHI complete,r5 should be set to OR */ -#endif - -/* Return to fpui. */ - -Ureturn: - ld r1,r31,0 /* load return address */ - jmp r1 - -/* - * FPoverflow - */ -/* If the overflow user handler bit is not set, then the inexact bit in the */ -/* FPSR is set, and the inexact user handler bit is checked. If it is set, */ -/* then the inexact user handler is executed, else the default routine for */ -/* overflow is executed. */ - -ASLOCAL(FPoverflow) - st r1,r31,0 /* save return address */ - set r2,r2,1<overflow> - set r2,r2,1<inexact> -#ifdef HANDLER - bb1 efovf,r12,hand /* go to user handler if bit set for overflow */ - bb0 efinx,r12,nohandler/* if userhandler for inexact not set,then */ - /* round result */ - br callhandler /* branch to user handler for inexact */ - -/* Before the overflow user handler is executed, the exponent is modified */ -/* by subtracting 192 for single precision and 1536 for double precision. */ - -hand: - bb1 10,r12,doubleprec /* double precision result */ -singleprec: - or.u r5,r0,0x0c00 /* load exponent adjust */ - br.n callhandler /* prepare to call user handler */ - subu r12,r12,r5 /* adjust single precision exponent */ -doubleprec: - or.u r5,r0,0x6000 /* load exponent adjust */ - subu r12,r12,r5 /* adjust double precision exponent */ -callhandler: - bsr _handler /* branch to common handler routine */ - br return -#endif - -/* Determine which rounding mode to use for the default procedure. */ - -nohandler: - bb1 modehi,r10,signed /* mode is either round toward pos. or neg. */ - bb0 modelo,r10,OFnearest /* rounding mode is round nearest */ - br OFzero /* rounding mode is round zero */ -signed: - bb0 modelo,r10,OFnegative /* rounding mode is round negative */ - br positive /* rounding mode is round positive */ - - -/* In the round toward nearest mode, positive values are rounded to */ -/* positive infinity and negative values are loaded toward negative infinity. */ -/* The value for single or double precision is loaded from a data table. */ - -OFnearest: - bb1.n destsize,r12,neardouble /* branch to neardouble of */ - /* double result */ - mask.u r5,r10,0x8000 /* mask off sign bit from MANTHI */ - or.u r11,r0,hi16(0x7f800000) /* load single infinity constant */ - or r11,r11,lo16(0x7f800000) - br.n return /* return with result */ - or r11,r5,r11 /* adjust sign */ -neardouble: - or r11,r0,r0 /* load lower word of infinity */ - or.u r10,r0,hi16(0x7ff00000) /* load upper word of infinity */ - or r10,r10,lo16(0x7ff00000) - br.n return /* return with result */ - or r10,r5,r10 /* adjust sign */ - - -/* In the round toward zero mode, positive values are rounded to the largest */ -/* postive finite number and negative values are rounded toward the largest */ -/* negative finite number. */ -/* The value for single or double precision is loaded from a data table. */ - -OFzero: - bb1.n destsize,r12,zerodouble /* branch to zerodouble of */ - /* double result */ - mask.u r5,r10,0x8000 /* mask off sign bit from MANTHI */ - or.u r11,r0,hi16(0x7f7fffff) /* load single finite number constant */ - or r11,r11,lo16(0x7f7fffff) - br.n return /* return with result */ - or r11,r5,r11 /* adjust sign */ -zerodouble: - set r11,r0,0<0> /* load lower word of finite number */ - or.u r10,r0,hi16(0x7fefffff) /* load upper word of finite number */ - or r10,r10,lo16(0x7fefffff) - br.n return /* return with result */ - or r10,r5,r10 /* adjust sign */ - - -/* In the round toward positve mode, positive values are rounded to */ -/* postive infinity and negative values are loaded toward the largest */ -/* negative finite number. */ -/* The value for single or double precision is loaded from a data table. */ - -positive: - bb1 destsize,r12,posdouble /* branch to section for double result */ -possingle: - bb1 sign,r10,possingleneg /* branch to section for negatives */ -possinglepos: - or.u r11,r0,hi16(0x7f800000) /* load single infinity constant */ - br.n return /* return with result */ - or r11,r11,lo16(0x7f800000) -possingleneg: - or.u r11,r0,hi16(0x7f7fffff) /* load single finite number constant */ - or r11,r11,lo16(0x7f7fffff) - br.n return /* return with result */ - set r11,r11,1<sign> /* set sign for negative */ -posdouble: - bb1 sign,r10,posdoubleneg /* branch to negative double results */ -posdoublepos: - or r11,r0,r0 /* load lower word of double infinity */ - or.u r10,r0,hi16(0x7ff00000) /* load upper word of infinity */ - br.n return /* return with result */ - or r10,r10,lo16(0x7ff00000) -posdoubleneg: - set r11,r0,0<0> /* load lower word of finite number */ - or.u r10,r0,hi16(0x7fefffff) /* load upper word of finite number */ - or r10,r10,lo16(0x7fefffff) - br.n return /* return with result */ - set r10,r10,1<sign> /* set sign for negative */ - - -/* In the round toward negative mode, positive values are rounded to the largest */ -/* postive finite number and negative values are rounded to negative infinity. */ -/* The value for single or double precision is loaded from a data table. */ - -OFnegative: - bb1 destsize,r12,negdouble /* branch to section for double result */ -negsingle: - bb1 sign,r10,negsingleneg /* branch to section for negatives */ -negsinglepos: - or.u r11,r0,hi16(0x7f7fffff) /* load single finite number constant */ - br.n return /* return with result */ - or r11,r11,lo16(0x7f7fffff) -negsingleneg: - or.u r11,r0,hi16(0x7f800000) /* load single infinity constant */ - or r11,r11,lo16(0x7f800000) - br.n return /* return with result */ - set r11,r11,1<sign> /* set sign for negative */ -negdouble: - bb1 sign,r10,negdoubleneg /* branch to negative double results */ -negdoublepos: - set r11,r0,0<0> /* load lower word of finite number */ - or.u r10,r0,hi16(0x7fefffff) /* load upper word of finite number */ - br.n return /* return with result */ - or r10,r10,lo16(0x7fefffff) -negdoubleneg: - or r11,r0,r0 /* load lower word of double infinity */ - or.u r10,r0,hi16(0x7ff00000) /* load upper word of infinity */ - or r10,r10,lo16(0x7ff00000) - set r10,r10,1<sign> /* set sign for negative */ - -return: - ld r1,r31,0 /* ld return address */ - jmp r1 - - data - - -/* If either S1 or S2 is a signalling NaN, then set the invalid operation */ -/* bit of the FPSR. If the invalid operation user handler flag is set and */ -/* then NaN is signalling, then branch to the handler routine to go to the */ -/* user handler. */ -/* If S1 is the only NaN or one of two NaN''s, then write */ -/* a quiet S1 to the result. A signalling NaN must be made quiet before */ -/* it can be written, but a signalling S2 is not modified in this routine */ -/* if S1 is a NaN. */ - text -ASLOCAL(NaN) - bb0.n s1nan,r12,S2sigcheck /* S1 is not a NaN */ - st r1,r31,0 /* save return address */ - bb1 sigbit,r5,S2sigcheck /* S1 is not a signaling NaN */ - set r2,r2,1<oper> -#ifdef HANDLER - bb0 oper,r3,S1nohandler /* branch if no user handler */ - bsr _handler /* branch to handler */ - br FPnan_return -ASLOCAL(S1nohandler) -#endif - br.n S1write /* FPSR bit already set, S1 is made quiet, */ - /* and since we always write S1 if it is a */ - /* NaN, write S1 and skip rest of routine */ - set r5,r5,1<sigbit> /* make S1 a quiet NaN */ - -ASLOCAL(S2sigcheck) - bb0 s2nan,r12,S1write /* S2 is not a NaN */ - bb1 sigbit,r7,S1write /* S2 is not a signaling NaN */ - set r2,r2,1<oper> -#ifdef HANDLER - bb0 oper,r3,S2nohandler /* branch if no user handler */ - bsr _handler /* branch to handler */ - br FPnan_return -#endif - -ASLOCAL(S2nohandler) - set r7,r7,1<sigbit> /* make S2 a quiet NaN */ - - -/* Write a single or double precision quiet NaN unless the opeation is FCMP. */ -/* If the operation is FCMP, then set the not comparable bit in the result. */ - -ASLOCAL(S1write) - bb0 s1nan,r12,S2write /* do not write S1 if it is not a NaN */ - extu r10,r9,5<11> /* extract opcode */ - cmp r11,r10,FCMPop /* compare to FCMP */ - bb1 ne,r11,S1noFCMP /* operation is not FCMP */ - set r6,r0,1<nc> /* set the not comparable bit */ - br.n FPnan_return - set r6,r6,1<ne> /* set the not equal bit */ -ASLOCAL(S1noFCMP) - bb1.n dsize,r9,wrdoubS1 /* double destination */ - set r5,r5,11<20> /* set all exponent bits to 1 */ -/* The single result will be formed the same way whether S1 is a single or double */ -ASLOCAL(wrsingS1) - mak r10,r5,28<3> /* wipe out extra exponent bits */ - extu r11,r6,3<29> /* get lower three bits of mantissa */ - or r10,r10,r11 /* combine all of result except sign */ - clr r6,r5,31<0> /* clear all but sign */ - br.n FPnan_return - or r6,r6,r10 /* form result */ - -ASLOCAL(wrdoubS1) - set r6,r6,29<0> /* set extra bits of lower word */ - br FPnan_return /* no modification necessary for writing */ - /* double to double, so return */ - -ASLOCAL(S2write) - extu r10,r9,5<11> /* extract opcode */ - cmp r11,r10,FCMPop /* compare to FCMP */ - bb1.n ne,r11,S2noFCMP /* operation is not FCMP */ - set r7,r7,11<20> /* set all exponent bits to 1 */ - set r6,r0,1<nc> /* set the not comparable bit */ - br.n FPnan_return - set r6,r6,1<ne> /* set the not equal bit */ -ASLOCAL(S2noFCMP) - bb1.n dsize,r9,wrdoubS2 /* double destination */ - set r5,r5,11<20> /* set all exponent bits to 1 */ -/* The single result will be formed the same way whether S1 is a single or double */ -ASLOCAL(wrsingS2) - mak r10,r7,28<3> /* wipe out extra exponent bits */ - extu r11,r8,3<29> /* get lower three bits of mantissa */ - or r10,r10,r11 /* combine all of result except sign */ - clr r6,r7,31<0> /* clear all but sign */ - br.n FPnan_return - or r6,r6,r10 /* form result */ - -ASLOCAL(wrdoubS2) - set r6,r8,29<0> /* set extra bits of lower word */ - -/* Return from this subroutine with the result. */ - -ASLOCAL(FPnan_return) - /* no modification necessary for writing */ - /* double to double, so return */ - ld r1,r31, 0 /* retrieve return address */ - jmp r1 - - data - -/* - * infinity - */ - -/* Extract the opcode, compare to a constant, and branch to the code */ -/* for the instruction. */ - -ASLOCAL(infinity) - extu r10,r9,5<11> /* extract opcode */ - cmp r11,r10,FADDop /* compare to FADD */ - bb1.n eq,r11,FADD /* operation is FADD */ - st r1,r31,0 /* save return address */ - cmp r11,r10,FSUBop /* compare to FSUB */ - bb1 eq,r11,FSUB /* operation is FSUB */ - cmp r11,r10,FCMPop /* compare to FCMP */ - bb1 eq,r11,FCMP /* operation is FCMP */ - cmp r11,r10,FMULop /* compare to FMUL */ - bb1 eq,r11,FMUL /* operation is FMUL */ - cmp r11,r10,FDIVop /* compare to FDIV */ - bb1 eq,r11,FDIV /* operation is FDIV */ -#if 0 - cmp r11,r10,FSQRTop /* compare to FSQRT */ - bb1 eq,r11,FSQRT /* operation is FSQRT */ -#endif - cmp r11,r10,INTop /* compare to INT */ - bb1 eq,r11,FP_inf_overflw /* operation is INT */ - cmp r11,r10,NINTop /* compare to NINT */ - bb1 eq,r11,FP_inf_overflw /* operation is NINT */ - cmp r11,r10,TRNCop /* compare to TRNC */ - bb1 eq,r11,FP_inf_overflw /* operation is TRNC */ - - -/* Adding infinities of opposite signs will cause an exception, */ -/* but all other operands will result in a correctly signed infinity. */ - -FADD: - bb0 s1inf,r12,addS2write /* branch if S1 not infinity */ - bb0 s2inf,r12,addS1write /* S2 is not inf., so branch to write S1 */ - bb1 sign,r5,addS1neg /* handle case of S1 negative */ -addS1pos: - bb1 sign,r7,excpt /* adding infinities of different */ - /* signs causes an exception */ - br poswrinf /* branch to write positive infinity */ -addS1neg: - bb0 sign,r7,excpt /* adding infinities of different */ - /* signs causes an exception */ - br negwrinf /* branch to write negative infinity */ -addS1write: - bb0 sign,r5,poswrinf /* branch to write positive infinity */ - br negwrinf /* branch to write negative infinity */ -addS2write: - bb0 sign,r7,poswrinf /* branch to write positive infinity */ - br negwrinf /* branch to write negative infinity */ - - -/* Subtracting infinities of the same sign will cause an exception, */ -/* but all other operands will result in a correctly signed infinity. */ - -FSUB: - bb0 s1inf,r12,subS2write /* branch if S1 not infinity */ - bb0 s2inf,r12,subS1write /* S2 is not inf., so branch to write S1 */ - bb1 sign,r5,subS1neg /* handle case of S1 negative */ -subS1pos: - bb0 sign,r7,excpt /* subtracting infinities of the same */ - /* sign causes an exception */ - br poswrinf /* branch to write positive infinity */ -subS1neg: - bb1 sign,r7,excpt /* subtracting infinities of the same */ - /* sign causes an exception */ - br negwrinf /* branch to write negative infinity */ -subS1write: - bb0 sign,r5,poswrinf /* branch to write positive infinity */ - br negwrinf /* branch to write negative infinity */ -subS2write: - bb1 sign,r7,poswrinf /* branch to write positive infinity */ - br negwrinf /* branch to write negative infinity */ - - -/* Compare the operands, at least one of which is infinity, and set the */ -/* correct bits in the destination register. */ - -FCMP: - bb0.n s1inf,r12,FCMPS1f /* branch for finite S1 */ - set r4,r0,1<cp> /* since neither S1 or S2 is a NaN, */ - /* set cp */ -FCMPS1i: - bb1 sign,r5,FCMPS1ni /* branch to negative S1i */ -FCMPS1pi: - bb0 s2inf,r12,FCMPS1piS2f /* branch to finite S2 with S1pi */ -FCMPS1piS2i: - bb1 sign,r7,FCMPS1piS2ni /* branch to negative S2i with S1pi */ -FCMPS1piS2pi: - set r4,r4,1<eq> /* set eq bit */ - set r4,r4,1<le> /* set le bit */ - set r4,r4,1<ge> /* set ge bit */ - set r4,r4,1<ib> /* set ib bit */ - br.n move - set r4,r4,1<ob> /* set ob bit */ -FCMPS1piS2ni: - set r4,r4,1<ne> /* set ne bit */ - set r4,r4,1<gt> /* set gt bit */ - br.n move - set r4,r4,1<ge> /* set ge bit */ -FCMPS1piS2f: - set r4,r4,1<ne> /* set ne bit */ - set r4,r4,1<gt> /* set gt bit */ - bsr.n _ASM_LABEL(zero) /* see if any of the operands are zero */ - set r4,r4,1<ge> /* set ge bit */ - bb0 s2zero,r12,FCMPS1piS2nz /* check for negative if s2 not zero */ - set r4,r4,1<ou> /* set ou bit */ - br.n move - set r4,r4,1<ob> /* set ob bit */ -FCMPS1piS2nz: - bb1 sign,r7,move /* return if s2 is negative */ -FCMPS1piS2pf: - set r4,r4,1<ou> /* set ou bit */ - br.n move - set r4,r4,1<ob> /* set ob bit */ -FCMPS1ni: - bb0 s2inf,r12,FCMPS1niS2f /* branch to finite S2 with S1ni */ -FCMPS1niS2i: - bb1 sign,r7,FCMPS1niS2ni /* branch to negative S2i with S1ni */ -FCMPS1niS2pi: - set r4,r4,1<ne> /* set eq bit */ - set r4,r4,1<le> /* set le bit */ - set r4,r4,1<lt> /* set lt bit */ - set r4,r4,1<ou> /* set ou bit */ - br.n move - set r4,r4,1<ob> /* set ob bit */ -FCMPS1niS2ni: - set r4,r4,1<eq> /* set eq bit */ - set r4,r4,1<le> /* set le bit */ - br.n move - set r4,r4,1<ge> /* set ge bit */ -FCMPS1niS2f: - set r4,r4,1<ne> /* set eq bit */ - set r4,r4,1<le> /* set le bit */ - bsr.n _ASM_LABEL(zero) /* see if any of the operands are zero */ - set r4,r4,1<lt> /* set lt bit */ - bb0 s2zero,r12,FCMPS1niS2nz /* branch if s2 is not zero */ - set r4,r4,1<ou> /* set ou bit */ - br.n move - set r4,r4,1<ob> /* set ob bit */ -FCMPS1niS2nz: - bb1 sign,r7,move /* return if s2 is negative */ - set r4,r4,1<ou> /* set ou bit */ - br.n move - set r4,r4,1<ob> /* set ob bit */ -FCMPS1f: - bb1 sign,r5,FCMPS1nf /* branch to negative S1f */ -FCMPS1pf: - bb1.n sign,r7,FCMPS1pfS2ni /* branch to negative S2i with S1pf */ - set r4,r4,1<ne> /* set ne bit */ -FCMPS1pfS2pi: - set r4,r4,1<le> /* set le bit */ - set r4,r4,1<lt> /* set lt bit */ - bsr.n _ASM_LABEL(zero) - set r4,r4,1<ib> /* set ib bit */ - bb0 s1zero,r12,FCMPS1pfS2pinozero -FCMPS1pfS2pizero: - br.n move - set r4,r4,1<ob> /* set ob bit */ -FCMPS1pfS2pinozero: - br.n move - set r4,r4,1<in> /* set in bit */ -FCMPS1pfS2ni: - set r4,r4,1<gt> /* set gt bit */ - br.n move - set r4,r4,1<ge> /* set ge bit */ -FCMPS1nf: - bb1.n sign,r7,FCMPS1nfS2ni /* branch to negative S2i with S1nf */ - set r4,r4,1<ne> /* set ne bit */ - set r4,r4,1<le> /* set gt bit */ - set r4,r4,1<lt> /* set ge bit */ - bsr.n _ASM_LABEL(zero) /* see which of the operands are zero */ - set r4,r4,1<ob> /* set ob bit */ - bb0 s1zero,r12,FCMPS1nfS2pinozero /* no ls and lo */ -FCMPS1nfS2pizero: - br.n move - set r4,r4,1<ib> /* set ib bit */ -FCMPS1nfS2pinozero: - br.n move - set r4,r4,1<ou> /* set ou bit */ -FCMPS1nfS2ni: - set r4,r4,1<gt> /* set gt bit */ - set r4,r4,1<ge> /* set ge bit */ - -move: - br.n inf_return - or r6,r0,r4 /* transfer answer to r6 */ - - -/* Multiplying infinity and zero causes an exception, but all other */ -/* operations produce a correctly signed infinity. */ - -FMUL: - bsr _ASM_LABEL(zero) /* see if any of the operands are zero */ - bb1 s1zero,r12,excpt /* infinity X 0 causes an exception */ - bb1 s2zero,r12,excpt /* infinity X 0 causes an exception */ - bb1 sign,r5,FMULS1neg /* handle negative cases of S1 */ - bb0 sign,r7,poswrinf /* + X + = + */ - br negwrinf /* + X - = - */ -FMULS1neg: - bb1 sign,r7,poswrinf /* - X - = + */ - br negwrinf /* - X + = - */ - - -/* Dividing infinity by infinity causes an exception, but dividing */ -/* infinity by a finite yields a correctly signed infinity, and */ -/* dividing a finite by an infinity produces a correctly signed zero. */ - -FDIV: - bb1 s1inf,r12,FDIVS1inf /* handle case of S1 being infinity */ - bb1 sign,r5,FDIVS1nf /* handle cases of S1 being neg. non-inf. */ - bb1 sign,r7,FDIVS1pfS2mi /* handle case of negative S2 */ -FDIVS1pfS2pi: - br poswrzero /* +f / +inf = +0 */ -FDIVS1pfS2mi: - br negwrzero /* +f / -inf = -0 */ -FDIVS1nf: - bb1 sign,r7,FDIVS1nfS2mi /* handle case of negative S2 */ -FDIVS1nfS2pi: - br negwrzero /* -f / +inf = -0 */ -FDIVS1nfS2mi: - br poswrzero /* -f / -inf = +0 */ -FDIVS1inf: - bb1 s2inf,r12,excpt /* inf / inf = exception */ - bb1 sign,r5,FDIVS1mi /* handle cases of S1 being neg. inf. */ - bb1 sign,r7,FDIVS1piS2nf /* handle case of negative S2 */ -FDIVS1piS2pf: - br poswrinf /* +inf / +f = +inf */ -FDIVS1piS2nf: - br negwrinf /* +inf / -f = -inf */ -FDIVS1mi: - bb1 sign,r7,FDIVS1miS2nf /* handle case of negative S2 */ -FDIVS1miS2pf: - br negwrinf /* -inf / +f = -inf */ -FDIVS1miS2nf: - br poswrinf /* -inf / -f = +inf */ - - -/* The square root of positive infinity is positive infinity, */ -/* but the square root of negative infinity is a NaN */ - -#if 0 -FSQRT: - bb0 sign,r7,poswrinf /* write sqrt(inf) = inf */ - br excpt /* write sqrt(-inf) = NaN */ -#endif - -excpt: - set r2,r2,1<oper> -#ifdef HANDLER - bb0 oper,r3,nohandler /* branch if no user handler */ - bsr _handler /* branch to interface with user handler */ - br inf_return -nohandler: -#endif - set r5,r0,0<0> /* write NaN into r5 */ - br.n inf_return - set r6,r0,0<0> /* write NaN into r6, writing NaN''s into */ - /* both of these registers is quicker than */ - /* checking for single or double precision */ - - -/* Write positive infinity of the correct precision */ - -poswrinf: - bb1 dsize,r9,poswrinfd /* branch to write double precision inf. */ - br.n inf_return - or.u r6,r0,0x7f80 /* load r6 with single precision pos inf. */ -poswrinfd: - or.u r5,r0,0x7ff0 /* load double precision pos inf. */ - br.n inf_return - or r6,r0,r0 - - -/* Write negative infinity of the correct precision */ - -negwrinf: - bb1 dsize,r9,negwrinfd /* branch to write double precision inf. */ - br.n inf_return - or.u r6,r0,0xff80 /* load r6 with single precision pos inf. */ -negwrinfd: - or.u r5,r0,0xfff0 /* load double precision pos inf. */ - br.n inf_return - or r6,r0,r0 - - -/* Write a positive zero disregarding precision. */ - -poswrzero: - or r5,r0,r0 /* write to both high word and low word now */ - br.n inf_return /* it does not matter that both are written */ - or r6,r0,r0 - - -/* Write a negative zero of the correct precision. */ - -negwrzero: - or r6,r0,r0 /* clear low word */ - bb1 dsize,r9,negwrzerod /* branch to write double precision zero */ - br.n inf_return - set r6,r6,1<31> /* set sign bit */ -negwrzerod: - or r5,r0,r0 /* clear high word */ - br.n inf_return - set r5,r5,1<31> /* set sign bit */ - -FP_inf_overflw: - set r2,r2,1<oper> - set r2,r2,1<overflow> - set r2,r2,1<inexact> -#ifdef HANDLER - bb0 oper,r3,nohandlero /* do not go to user handler routine */ - bsr _handler /* go to user handler routine */ - br inf_return -#endif - -nohandlero: - bb0.n sign,r7,inf_return /* if positive then return */ - - set r6,r6,31<0> /* set result to largest positive integer */ - or.c r6,r0,r6 /* negate r6,giving largest negative int. */ - -inf_return: - ld r1,r31,0 /* load return address */ - jmp r1 - - data - -#define FADD denorm_FADD -#define FSUB denorm_FSUB -#define FCMP denorm_FCMP -#define FMUL denorm_FMUL -#define FDIV denorm_FDIV -#define NINT denorm_NINT -#define TRNC denorm_TRNC -#define return denorm_return - -/* - * denorm - */ - -/* Check to see if either S1 or S2 is a denormalized number. First */ -/* extract the exponent to see if it is zero, and then check to see if */ -/* the mantissa is not zero. If the number is denormalized, then set the */ -/* 1 or 0 bit 10 r12. */ - -ASLOCAL(denorm) - st r1,r31,0 /* save return address */ -dnmcheckS1: - extu r10,r5,11<20> /* extract exponent */ - bcnd ne0,r10,dnmsetS2 /* S1 is not a denorm, so S2 must be */ - bb1.n 9,r9,dnmcheckS1d /* S1 is double precision */ - mak r10,r5,20<3> /* mak field with only mantissa bits */ - /* into final result */ -dnmcheckS1s: - extu r11,r6,3<29> /* get three low bits of mantissa */ - or r10,r10,r11 /* assemble all of the mantissa bits */ - bcnd eq0,r10,dnmsetS2 /* S1 is not a denorm, so S2 must be */ - br dnmsetS1 /* S1 is a denorm */ - -dnmcheckS1d: - or r10,r6,r10 /* or all of mantissa bits */ - bcnd eq0,r10,dnmsetS2 /* S1 is not a denorm, so S2 must be */ -dnmsetS1: - set r12,r12,1<1> /* S1 is a denorm */ - -dnmcheckS2: - extu r10,r7,11<20> /* extract exponent */ - bcnd ne0,r10,S1form /* S2 is not a denorm */ - bb1.n 7,r9,dnmcheckS2d /* S2 is double precision */ - mak r10,r7,20<3> /* mak field with only mantissa bits */ -dnmcheckS2s: - extu r11,r8,3<29> /* get three low bits of mantissa */ - or r10,r10,r11 /* assemble all of the mantissa bits */ - bcnd eq0,r10,S1form /* S2 is not a denorm */ - br dnmsetS2 /* S1 is a denorm */ -dnmcheckS2d: - or r10,r8,r10 /* or all or mantissa bits */ - bcnd eq0,r10,S1form /* S2 is not a denorm */ -dnmsetS2: - set r12,r12,1<0> /* S2 is a denorm */ - - -/* Since the operations are going to be reperformed with modified denorms, */ -/* the operands which were initially single precision need to be modified */ -/* back to single precision. */ - -S1form: - bb1 9,r9,S2form /* S1 is double precision, so do not */ - /* modify S1 into single format */ - mak r11,r5,28<3> /* over final exponent and mantissa */ - /* eliminating extra 3 bits of exponent */ - extu r6,r6,3<29> /* get low 3 bits of mantissa */ - or r11,r6,r11 /* form complete mantissa and exponent */ - extu r10,r5,1<31> /* get the 31 bit */ - mak r10,r10,1<31> /* place 31 bit 10 correct position */ - or r6,r10,r11 /* or 31, exponent, and all of mantissa */ - -S2form: - bb1 7,r9,checkop /* S2 is double precision, so do not */ - /* modify S2 into single format */ - mak r11,r7,28<3> /* over final exponent and mantissa */ - /* eliminating extra 3 bits of exponent */ - extu r8,r8,3<29> /* get low 3 bits of mantissa */ - or r11,r8,r11 /* form complete mantissa and exponent */ - extu r10,r7,1<31> /* get the 31 bit */ - mak r10,r10,1<31> /* place 31 bit 10 correct position */ - or r8,r10,r11 /* or 31, exponent, and all of mantissa */ - - -/* Extract the opcode, compare to a constant, and branch to the code that */ -/* deals with that opcode. */ - -checkop: - extu r10,r9,5<11> /* extract opcode */ - cmp r11,r10,0x05 /* compare to FADD */ - bb1 2,r11,FADD /* operation is FADD */ - cmp r11,r10,0x06 /* compare to FSUB */ - bb1 2,r11,FSUB /* operation is FSUB */ - cmp r11,r10,0x07 /* compare to FCMP */ - bb1 2,r11,FCMP /* operation is FCMP */ - cmp r11,r10,0x00 /* compare to FMUL */ - bb1 2,r11,FMUL /* operation is FMUL */ - cmp r11,r10,0x0e /* compare to FDIV */ - bb1 2,r11,FDIV /* operation is FDIV */ -#if 0 - cmp r11,r10,0x0f /* compare to FSQRT */ - bb1 2,r11,FSQRT /* operation is FSQRT */ -#endif - cmp r11,r10,0x09 /* compare to INT */ - bb1 2,r11,INT /* operation is INT */ - cmp r11,r10,0x0a /* compare to NINT */ - bb1 2,r11,NINT /* operation is NINT */ - cmp r11,r10,0x0b /* compare to TRNC */ - bb1 2,r11,TRNC /* operation is TRNC */ - - -/* For all the following operations, the denormalized number is set to */ -/* zero and the operation is reperformed the correct destination and source */ -/* sizes. */ - -FADD: - bb0 1,r12,FADDS2dnm /* S1 is not denorm, so S2 must be */ - or r5,r0,r0 /* set S1 to zero */ - or r6,r0,r0 -FADDS2chk: - bb0 0,r12,FADDcalc /* S2 is not a denorm */ -FADDS2dnm: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -FADDcalc: - bb1 5,r9,FADDdD /* branch for double precision destination */ -FADDsD: - bb1 9,r9,FADDsDdS1 /* branch for double precision S1 */ -FADDsDsS1: - bb1 7,r9,FADDsDsS1dS2 /* branch for double precision S2 */ -FADDsDsS1sS2: - br.n return - fadd.sss r6,r6,r8 /* add the two sources and place result 10 S1 */ -FADDsDsS1dS2: - br.n return - fadd.ssd r6,r6,r7 /* add the two sources and place result 10 S1 */ -FADDsDdS1: - bb1 7,r9,FADDsDdS1dS2 /* branch for double precision S2 */ -FADDsDdS1sS2: - br.n return - fadd.sds r6,r5,r8 /* add the two sources and place result 10 S1 */ -FADDsDdS1dS2: - br.n return - fadd.sdd r6,r5,r7 /* add the two sources and place result 10 S1 */ -FADDdD: - bb1 9,r9,FADDdDdS1 /* branch for double precision S1 */ -FADDdDsS1: - bb1 7,r9,FADDdDsS1dS2 /* branch for double precision S2 */ -FADDdDsS1sS2: - br.n return - fadd.dss r5,r6,r8 /* add the two sources and place result 10 S1 */ -FADDdDsS1dS2: - br.n return - fadd.dsd r5,r6,r7 /* add the two sources and place result 10 S1 */ -FADDdDdS1: - bb1 7,r9,FADDdDdS1dS2 /* branch for double precision S2 */ -FADDdDdS1sS2: - br.n return - fadd.dds r5,r5,r8 /* add the two sources and place result 10 S1 */ -FADDdDdS1dS2: - br.n return - fadd.ddd r5,r5,r7 /* add the two sources and place result 10 S1 */ - -FSUB: - bb0 1,r12,FSUBS2dnm /* S1 is not denorm, so S2 must be */ - or r5,r0,r0 /* set S1 to zero */ - or r6,r0,r0 -FSUBS2chk: - bb0 0,r12,FSUBcalc /* S2 is not a denorm */ -FSUBS2dnm: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -FSUBcalc: - bb1 5,r9,FSUBdD /* branch for double precision destination */ -FSUBsD: - bb1 9,r9,FSUBsDdS1 /* branch for double precision S1 */ -FSUBsDsS1: - bb1 7,r9,FSUBsDsS1dS2 /* branch for double precision S2 */ -FSUBsDsS1sS2: - br.n return - fsub.sss r6,r6,r8 /* add the two sources and place result 10 S1 */ -FSUBsDsS1dS2: - br.n return - fsub.ssd r6,r6,r7 /* add the two sources and place result 10 S1 */ -FSUBsDdS1: - bb1 7,r9,FSUBsDdS1dS2 /* branch for double precision S2 */ -FSUBsDdS1sS2: - br.n return - fsub.sds r6,r5,r8 /* add the two sources and place result 10 S1 */ -FSUBsDdS1dS2: - br.n return - fsub.sdd r6,r5,r7 /* add the two sources and place result 10 S1 */ -FSUBdD: - bb1 9,r9,FSUBdDdS1 /* branch for double precision S1 */ -FSUBdDsS1: - bb1 7,r9,FSUBdDsS1dS2 /* branch for double precision S2 */ -FSUBdDsS1sS2: - br.n return - fsub.dss r5,r6,r8 /* add the two sources and place result 10 S1 */ -FSUBdDsS1dS2: - br.n return - fsub.dsd r5,r6,r7 /* add the two sources and place result 10 S1 */ -FSUBdDdS1: - bb1 7,r9,FSUBdDdS1dS2 /* branch for double precision S2 */ -FSUBdDdS1sS2: - br.n return - fsub.dds r5,r5,r8 /* add the two sources and place result 10 S1 */ -FSUBdDdS1dS2: - br.n return - fsub.ddd r5,r5,r7 /* add the two sources and place result 10 S1 */ - -FCMP: - bb0 1,r12,FCMPS2dnm /* S1 is not denorm, so S2 must be */ - or r5,r0,r0 /* set S1 to zero */ - or r6,r0,r0 -FCMPS2chk: - bb0 0,r12,FCMPcalc /* S2 is not a denorm */ -FCMPS2dnm: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -FCMPcalc: - bb1 9,r9,FCMPdS1 /* branch for double precision S1 */ -FCMPsS1: - bb1 7,r9,FCMPsS1dS2 /* branch for double precision S2 */ -FCMPsS1sS2: - br.n return - fcmp.sss r6,r6,r8 /* add the two sources and place result 10 S1 */ -FCMPsS1dS2: - br.n return - fcmp.ssd r6,r6,r7 /* add the two sources and place result 10 S1 */ -FCMPdS1: - bb1 7,r9,FCMPdS1dS2 /* branch for double precision S2 */ -FCMPdS1sS2: - br.n return - fcmp.sds r6,r5,r8 /* add the two sources and place result 10 S1 */ -FCMPdS1dS2: - br.n return - fcmp.sdd r6,r5,r7 /* add the two sources and place result 10 S1 */ - -FMUL: - bb0 1,r12,FMULS2dnm /* S1 is not denorm, so S2 must be */ - or r5,r0,r0 /* set S1 to zero */ - or r6,r0,r0 -FMULS2chk: - bb0 0,r12,FMULcalc /* S2 is not a denorm */ -FMULS2dnm: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -FMULcalc: - bb1 5,r9,FMULdD /* branch for double precision destination */ -FMULsD: - bb1 9,r9,FMULsDdS1 /* branch for double precision S1 */ -FMULsDsS1: - bb1 7,r9,FMULsDsS1dS2 /* branch for double precision S2 */ -FMULsDsS1sS2: - br.n return - fmul.sss r6,r6,r8 /* add the two sources and place result 10 S1 */ -FMULsDsS1dS2: - br.n return - fmul.ssd r6,r6,r7 /* add the two sources and place result 10 S1 */ -FMULsDdS1: - bb1 7,r9,FMULsDdS1dS2 /* branch for double precision S2 */ -FMULsDdS1sS2: - br.n return - fmul.sds r6,r5,r8 /* add the two sources and place result 10 S1 */ -FMULsDdS1dS2: - br.n return - fmul.sdd r6,r5,r7 /* add the two sources and place result 10 S1 */ -FMULdD: - bb1 9,r9,FMULdDdS1 /* branch for double precision S1 */ -FMULdDsS1: - bb1 7,r9,FMULdDsS1dS2 /* branch for double precision S2 */ -FMULdDsS1sS2: - br.n return - fmul.dss r5,r6,r8 /* add the two sources and place result 10 S1 */ -FMULdDsS1dS2: - br.n return - fmul.dsd r5,r6,r7 /* add the two sources and place result 10 S1 */ -FMULdDdS1: - bb1 7,r9,FMULdDdS1dS2 /* branch for double precision S2 */ -FMULdDdS1sS2: - br.n return - fmul.dds r5,r5,r8 /* add the two sources and place result 10 S1 */ -FMULdDdS1dS2: - br.n return - fmul.ddd r5,r5,r7 /* add the two sources and place result 10 S1 */ - -FDIV: - bb0 1,r12,FDIVS2dnm /* S1 is not denorm, so S2 must be */ - or r5,r0,r0 /* set S1 to zero */ - or r6,r0,r0 -FDIVS2chk: - bb0 0,r12,FDIVcalc /* S2 is not a denorm */ -FDIVS2dnm: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -FDIVcalc: - bb1 5,r9,FDIVdD /* branch for double precision destination */ -FDIVsD: - bb1 9,r9,FDIVsDdS1 /* branch for double precision S1 */ -FDIVsDsS1: - bb1 7,r9,FDIVsDsS1dS2 /* branch for double precision S2 */ -FDIVsDsS1sS2: - fdiv.sss r6,r6,r8 /* add the two sources and place result 10 S1 */ - br return -FDIVsDsS1dS2: - fdiv.ssd r6,r6,r7 /* add the two sources and place result 10 S1 */ - br return -FDIVsDdS1: - bb1 7,r9,FDIVsDdS1dS2 /* branch for double precision S2 */ -FDIVsDdS1sS2: - fdiv.sds r6,r5,r8 /* add the two sources and place result 10 S1 */ - br return -FDIVsDdS1dS2: - fdiv.sdd r6,r5,r7 /* add the two sources and place result 10 S1 */ - br return -FDIVdD: - bb1 9,r9,FDIVdDdS1 /* branch for double precision S1 */ -FDIVdDsS1: - bb1 7,r9,FDIVdDsS1dS2 /* branch for double precision S2 */ -FDIVdDsS1sS2: - fdiv.dss r5,r6,r8 /* add the two sources and place result 10 S1 */ - br return -FDIVdDsS1dS2: - fdiv.dsd r5,r6,r7 /* add the two sources and place result 10 S1 */ - br return -FDIVdDdS1: - bb1 7,r9,FDIVdDdS1dS2 /* branch for double precision S2 */ -FDIVdDdS1sS2: - fdiv.dds r5,r5,r8 /* add the two sources and place result 10 S1 */ - br return -FDIVdDdS1dS2: - fdiv.ddd r5,r5,r7 /* add the two sources and place result 10 S1 */ - br return - -#if 0 -FSQRT: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -FSQRTcalc: - bb1 5,r9,FSQRTdD /* branch for double precision destination */ -FSQRTsD: - bb1 7,r9,FSQRTsDdS2 /* branch for double precision S2 */ -FSQRTsDsS2: - br.n return - fsqrt.ss r6,r8 /* add the two sources and place result 10 S1 */ -FSQRTsDdS2: - br.n return - fsqrt.sd r6,r7 /* add the two sources and place result 10 S1 */ -FSQRTdD: - bb1 7,r9,FSQRTdDdS2 /* branch for double precision S2 */ -FSQRTdDsS2: - br.n return - fsqrt.ds r5,r8 /* add the two sources and place result 10 S1 */ -FSQRTdDdS2: - br.n return - fsqrt.dd r5,r7 /* add the two sources and place result 10 S1 */ -#endif - -INT: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -INTcalc: - bb1 7,r9,INTdS2 /* branch for double precision S2 */ -INTsS2: - br.n return - int.ss r6,r8 /* add the two sources and place result 10 S1 */ -INTdS2: - br.n return - int.sd r6,r7 /* add the two sources and place result 10 S1 */ - -NINT: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -NINTcalc: - bb1 7,r9,NINTdS2 /* branch for double precision S2 */ -NINTsS2: - br.n return - nint.ss r6,r8 /* add the two sources and place result 10 S1 */ -NINTdS2: - br.n return - nint.sd r6,r7 /* add the two sources and place result 10 S1 */ - -TRNC: - or r7,r0,r0 /* set S2 to zero */ - or r8,r0,r0 -TRNCcalc: - bb1 7,r9,TRNCdS2 /* branch for double precision S2 */ -TRNCsS2: - br.n return - trnc.ss r6,r8 /* add the two sources and place result 10 S1 */ -TRNCdS2: - trnc.sd r6,r7 /* add the two sources and place result 10 S1 */ - - -/* Return to the routine that detected the reserved operand. */ - -return: - ld r1,r31,0 /* load return address */ - jmp r1 - - data - - -/* S1 and/or S2 is an infinity, and the other operand may be a zero. */ -/* Knowing which operands are infinity, check the remaining operands for zeros. */ - -ASLOCAL(zero) - bb0 s1inf,r12,S1noinf /* see if S1 is zero */ - bb0 s2inf,r12,S2noinf /* see if S2 is zero */ - jmp r1 - -/* See if S1 is zero. Whether or not S1 is a zero, being in this routine */ -/* implies that S2 is infinity, so return to subroutine infinity after */ -/* completing this code. Set the s1zero flag in r12 if S1 is zero. */ - -S1noinf: - bb1 s1size,r9,S1noinfd /* work with double precision operand */ -S1noinfs: - or r10,r0,r5 /* load high word into r10 */ - clr r10,r10,1<sign> /* clear the sign bit */ - extu r11,r6,3<29> /* extract lower 3 bits of mantissa */ - or r10,r10,r11 /* or these 3 bits with high word */ - bcnd ne0,r10,operation /* do not set zero flag */ - jmp.n r1 /* since this operand was not */ - /* infinity, S2 must have been, */ - /* so return */ - set r12,r12,1<s1zero> /* set zeroflag */ -S1noinfd: - clr r10,r5,1<sign> /* clear the sign bit */ - or r10,r6,r10 /* or high and low word */ - bcnd ne0,r10,operation /* do not set zero flag */ - jmp.n r1 /* since this operand was not */ - /* infinity, S2 must have been, */ - /* so return */ - set r12,r12,1<s1zero> /* set zeroflag */ - - -/* Check S2 for zero. If it is zero, then set the s2zero flag in r12. */ - -S2noinf: - bb1 s2size,r9,S2noinfd /* work with double precision operand */ -S2noinfs: - or r10,r0,r7 /* load high word into r10 */ - clr r10,r10,1<sign> /* clear the sign bit */ - extu r11,r8,3<29> /* extract lower 3 bits of mantissa */ - or r10,r10,r11 /* or these 3 bits with high word */ - bcnd ne0,r10,operation /* do not set zero flag */ - jmp.n r1 /* since this operand was not */ - /* infinity, S1 must have been, */ - /* so return */ - set r12,r12,1<s2zero> /* set zeroflag */ -S2noinfd: - clr r10,r7,1<sign> /* clear the sign bit */ - or r10,r8,r10 /* or high and low word */ - bcnd ne0,r10,operation /* do not set zero flag */ - set r12,r12,1<s2zero> /* set zeroflag */ - /* since this operand was not */ - /* infinity, S1 must have been, */ - /* so return */ -operation: - jmp r1 - -ASENTRY(Xfp_imprecise) -/* input: r3 is the exception frame */ - or r29, r3, r0 /* r29 is now the E.F. */ - subu r31, r31, 40 - st r1, r31, 32 - st r29, r31, 36 - - ld r2 , r29, EF_FPSR * 4 - ld r3 , r29, EF_FPCR * 4 - ld r4 , r29, EF_FPECR * 4 - ld r10, r29, EF_FPRH * 4 - ld r11, r29, EF_FPRL * 4 - ld r12, r29, EF_FPIT * 4 - -/* Load into r1 the return address for the exception handlers. Looking */ -/* at FPECR, branch to the appropriate exception handler. */ - - or.u r1,r0,hi16(fpui_wrapup)/* load return address of functions */ - or r1,r1,lo16(fpui_wrapup) - - bb0 2,r4,2f /* branch to FPunderflow if bit set */ - br _ASM_LABEL(FPunderflow) -2: - bb0 1,r4,3f /* branch to FPoverflow if bit set */ - br _ASM_LABEL(FPoverflow) -3: - /* XXX handle inexact!!! */ -#ifdef HANDLER - br _handler /* branch to handler since bit will */ - /* be set for inexact */ -#endif - -fpui_wrapup: - tb1 0,r0,0 /* make sure all floating point operations */ - /* have finished */ - ldcr r4, cr1 /* load the PSR */ -#if 0 - set r4, r4, 1<PSR_FPU_DISABLE_BIT> -#endif - set r4, r4, 1<PSR_INTERRUPT_DISABLE_BIT> - stcr r4, cr1 - ld r1, r31, 32 - ld r29,r31, 36 - addu r31, r31, 40 - - fstcr r2, FPSR /* write revised value of FPSR */ - fstcr r3, FPCR /* write revised value of FPCR */ - - /* write back the results */ - extu r2, r12, 5<0> - addu r3, r29, EF_R0*4 - bb0 destsize, r12, Iwritesingle - st r10, r3 [r2] - addu r2, r2, 1 - clr r2, r2, 27<5> -Iwritesingle: - st r11, r3 [r2] - jmp r1 diff --git a/sys/arch/luna88k/luna88k/process.S b/sys/arch/luna88k/luna88k/process.S deleted file mode 100644 index 5ffa2bf65e1..00000000000 --- a/sys/arch/luna88k/luna88k/process.S +++ /dev/null @@ -1,332 +0,0 @@ -/* $OpenBSD: process.S,v 1.1 2004/04/21 15:24:13 aoyama Exp $ */ -/* - * Copyright (c) 1996 Nivas Madhur - * 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 Nivas Madhur. - * 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 "assym.h" -#include <machine/asm.h> -#include <machine/psl.h> -#include <machine/intr.h> - - data - align 4 -ASLOCAL(swchanpanic) - string "switch wchan %x\0" - align 4 -ASLOCAL(swsrunpanic) - string "switch SRUN %x\0" -#ifdef DEBUG - align 4 -ASLOCAL(boguspsr) - string "Invalid PSR in idle loop 0x%x\n\0" -#endif - - text - align 8 -ASLOCAL(Lswchanpanic) - or.u r2, r0, hi16(_ASM_LABEL(swchanpanic)) - or r2, r2, lo16(_ASM_LABEL(swchanpanic)) - bsr.n _C_LABEL(panic) - or r3, r0, r9 - -ASLOCAL(Lswsrunpanic) - or.u r2, r0, hi16(_ASM_LABEL(swsrunpanic)) - or r2, r2, lo16(_ASM_LABEL(swsrunpanic)) - bsr.n _C_LABEL(panic) - or r3, r0, r9 - -/* - * 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. - * The ipl is high enough to prevent the memory from being reallocated. - * switch_exit(proc * p) - */ - -ENTRY(switch_exit) - /* - * Change pcb to idle u. area, i.e., set r31 to top of stack - * and set curpcb to point to _idle_u. r2 contains proc *p. - */ - or.u r30, r0, hi16(_C_LABEL(idle_u)) - or r30, r30,lo16(_C_LABEL(idle_u)) - addu r31, r30, USIZE /* now on idle_u stack */ - or.u r10, r0, hi16(_C_LABEL(curpcb)) - st r30, r10,lo16(_C_LABEL(curpcb)) /* curpcb = &idle_u */ - or.u r10, r0, hi16(_C_LABEL(curproc)) - st r0, r10, lo16(_C_LABEL(curproc)) /* curproc = NULL */ - - /* Schedule the vmspace and stack to be freed. */ - bsr.n _C_LABEL(exit2) - subu r31, r31, 48 /* allocate stack */ - addu r31, r31, 48 /* restore stack */ - bsr _C_LABEL(cpu_switch) /* goto final switch */ - -/* - * cpu_switch() - * XXX - Arg 1 is a proc pointer (curproc) but this doesn't use it. - * XXX - how about using stack for saving spl and last proc? - * XXX rewrite this whole mess in C nivas - */ -ENTRY(cpu_switch) - - /* - * Save state of previous process in its pcb. - */ - or.u r2, r0, hi16(_C_LABEL(curpcb)) - ld r2, r2, lo16(_C_LABEL(curpcb)) - st r1, r2, PCB_PC /* save return address */ - bsr _ASM_LABEL(__savectx) - /* note that we don't need to recover r1 at this point */ - - or.u r11, r0, hi16(_C_LABEL(curproc)) - ld r2, r11, lo16(_C_LABEL(curproc)) - bcnd eq0, r2, 1f - - bsr.n _C_LABEL(pmap_deactivate) - subu r31, r31,48 - addu r31, r31,48 - or.u r11, r0, hi16(_C_LABEL(curproc)) - -1: - st r0, r11, lo16(_C_LABEL(curproc)) /* curproc = NULL */ - -ASLOCAL(Lidleloop) - - /* - * Find the highest-priority queue that isn't empty, - * then take the first proc from that queue. - */ - - or.u r7, r0, hi16(_C_LABEL(whichqs)) - ld r7, r7, lo16(_C_LABEL(whichqs)) - - bcnd ne0, r7, _ASM_LABEL(Ldoneloop) - -ASLOCAL(Lloopchk) /* if whichqs is zero, keep checking */ - bsr.n _C_LABEL(setipl) /* unmask all ints... */ - or r2, r0, IPL_NONE - - ldcr r2, PSR - bb0 PSR_INTERRUPT_DISABLE_BIT, r2, 1f -#ifdef DEBUG - or r3, r2, r0 - or.u r2, r0, hi16(_ASM_LABEL(boguspsr)) - bsr.n _C_LABEL(printf) - or r2, r2, lo16(_ASM_LABEL(boguspsr)) - ldcr r2, PSR -#endif - clr r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT> /* ...and enable them */ - stcr r2, PSR - FLUSH_PIPELINE -1: - br _ASM_LABEL(Lidleloop) - -ASLOCAL(Ldoneloop) - - bsr.n _C_LABEL(setipl) /* disable ints */ - or r2, r0, IPL_HIGH - - or.u r7, r0, hi16(_C_LABEL(whichqs)) /* reload whichqs */ - ld r7, r7, lo16(_C_LABEL(whichqs)) - - bcnd eq0, r7, _ASM_LABEL(Lloopchk) /* keep spinning for whichqs to be != 0 */ - - xor r6, r6, r6 /* set r6 to 0 */ -1: bb1 0, r7, 2f /* if rightmost bit set, done */ - extu r7, r7, 0<1> /* else, right shift whichqs, */ - br.n 1b /* increment r6, and repeat */ - addu r6, r6, 1 -2: - or.u r7, r0, hi16(_qs) - or r7, r7, lo16(_qs) - - /* - * Need to make - * p->p_forw->p_back = p->p_back and - * p->p_back->p_forw = p->p_forw where - * p is q->p_forw. - * Remember that q->p_forw == p and p->p_back == q. - */ - - lda.d r8, r7[r6] /* r8 = &qs[ff1(whichqs)] */ - ld r9, r8, P_FORW /* r8 is q, r9 is p */ - - ld r12, r9, P_FORW /* r12 = p->p_forw */ - st r8, r12, P_BACK /* p->p_forw->p_back = q (p->p_back) */ - st r12, r8, P_FORW /* q->p_forw = p->p_forw */ - lda.d r8, r7[r6] /* reload r8 with qs[ff1(whichqs)] */ - ld r12, r8, P_FORW /* q->p_forw */ - cmp r12, r12, r8 /* q == q->p_forw; anyone left on queue? */ - bb1 ne, r12, 3f /* yes, skip clearing bit in whichqs */ - - or r12, r0, 1 /* r12 is 1 now */ -1: bcnd eq0, r6, 2f - mak r12, r12, 0<1> /* shift left by 1 */ - br.n 1b - subu r6, r6, 1 /* keep doing this while r6 != 0 */ -2: - /* - * NOTE: we could have just used "mak r12, r12, r6" instead of the - * loop above. But that will break if NQS is made > 32. I can use - * preprocessor to do the right thing, but that means I have to - * include sys/proc.h in this file. XXX nivas - */ - or.u r7, r0, hi16(_C_LABEL(whichqs)) - ld r8, r7, lo16(_C_LABEL(whichqs)) - and.c r8, r8, r12 /* whichqs &= ~the bit */ - st r8, r7, lo16(_C_LABEL(whichqs)) -3: - ld r2, r9, P_WCHAN - bcnd ne0, r2, _ASM_LABEL(Lswchanpanic) - ld.b r2, r9, P_STAT - cmp r2, r2, SRUN - bb1 ne, r2, _ASM_LABEL(Lswsrunpanic) - - or.u r11, r0, hi16(_C_LABEL(want_resched)) - st r0, r11, lo16(_C_LABEL(want_resched)) /* clear want_resched */ - - or.u r11, r0, hi16(_C_LABEL(curproc)) - st r9, r11,lo16(_C_LABEL(curproc)) /* curproc = p */ - - /* r9 is curproc */ - st r0, r9, P_BACK /* p->p_back = 0 */ - ld r3, r9, P_ADDR - or.u r10, r0, hi16(_C_LABEL(curpcb)) - st r3, r10, lo16(_C_LABEL(curpcb)) /* curpcb = p->p_addr */ - - /* pmap_activate() the process' pmap */ - or r2, r0, r9 /* r2 = p */ - or r14, r0, r9 /* save p in r14 */ - bsr.n _C_LABEL(pmap_activate) - subu r31, r31,48 - addu r31, r31,48 - or r9, r0, r14 /* restore p saved in r14 */ - - or.u r31, r0, hi16(_ASM_LABEL(intstack_end)) - or r31,r31, lo16(_ASM_LABEL(intstack_end)) - subu r31, r31,48 - bsr.n _C_LABEL(load_u_area) - or r2, r0, r9 - addu r31, r31,48 - - or.u r10, r0, hi16(_C_LABEL(curpcb)) - ld r10, r10, lo16(_C_LABEL(curpcb)) - /* XXX Is this correct/necessary? */ - st r10, r14, P_ADDR /* p->p_addr = curpcb; restore p_addr */ - - /* restore from the current context */ - ld r2, r10, PCB_FCR62 - ld r3, r10, PCB_FCR63 - fstcr r2, fcr62 - fstcr r3, fcr63 - ld r1, r10, PCB_PC - ld r14,r10, PCB_R14 - ld r15,r10, PCB_R15 - ld r16,r10, PCB_R16 - ld r17,r10, PCB_R17 - ld r18,r10, PCB_R18 - ld r19,r10, PCB_R19 - ld r20,r10, PCB_R20 - ld r21,r10, PCB_R21 - ld r22,r10, PCB_R22 - ld r23,r10, PCB_R23 - ld r24,r10, PCB_R24 - ld r25,r10, PCB_R25 - ld r26,r10, PCB_R26 - ld r27,r10, PCB_R27 - ld r28,r10, PCB_R28 - ld r29,r10, PCB_R29 - ld r30,r10, PCB_R30 /* restore frame pointer & stack */ - ld r31,r10, PCB_SP - -/* XXX - * Should we postpone restoring stack till after ipl is restored? - * The stack access could fault - */ - subu r31,r31,48 - st r1, r31,36 /* save r1 on stack */ - bsr.n _C_LABEL(setipl) - ld r2, r10, PCB_IPL /* restore interrupt mask */ - ld r1, r31,36 /* restore r1 from stack */ - addu r31,r31,48 - jmp.n r1 - or r2, r0, 1 /* return 1 (for alternate returns) */ - -/* - * savectx(pcb) - * Update pcb, saving current processor state. - */ -ENTRY(savectx) - /* - * Save preserved general register set. - */ - st r1, r2, PCB_PC /* save return address */ -ASENTRY(__savectx) - st r14, r2, PCB_R14 - st r15, r2, PCB_R15 - st r16, r2, PCB_R16 - st r17, r2, PCB_R17 - st r18, r2, PCB_R18 - st r19, r2, PCB_R19 - st r20, r2, PCB_R20 - st r21, r2, PCB_R21 - st r22, r2, PCB_R22 - st r23, r2, PCB_R23 - st r24, r2, PCB_R24 - st r25, r2, PCB_R25 - st r26, r2, PCB_R26 - st r27, r2, PCB_R27 - st r28, r2, PCB_R28 - st r29, r2, PCB_R29 - st r30, r2, PCB_R30 /* save frame pointer & stack pointer */ - st r31, r2, PCB_SP - - /* - * Get the current spl. - * We need to save r1 on the stack because we don't know if we were - * called as savectx or __savectx. - */ - subu r31, r31, 40 /* allocate stack for r1 and args */ - st r1, r31, 32 - bsr.n _C_LABEL(getipl) /* get the current interrupt mask */ - or r14, r0, r2 - st r2, r14, PCB_IPL /* save interrupt mask */ - ld r1, r31, 32 /* recover return address */ - addu r31, r31, 40 /* put stack pointer back */ - - /* - * Save FP state. - */ - fldcr r2, fcr62 - fldcr r3, fcr63 - st r2, r14, PCB_FCR62 - jmp.n r1 - st r3, r14, PCB_FCR63 diff --git a/sys/arch/luna88k/luna88k/process_machdep.c b/sys/arch/luna88k/luna88k/process_machdep.c deleted file mode 100644 index 27bf49b45ed..00000000000 --- a/sys/arch/luna88k/luna88k/process_machdep.c +++ /dev/null @@ -1,149 +0,0 @@ -/* $OpenBSD: process_machdep.c,v 1.1 2004/04/21 15:24:14 aoyama Exp $ */ - -/* - * 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. 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 - */ - -/* - * 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 (<machine/reg.h>). - * 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 <sys/param.h> -#include <sys/systm.h> -#include <sys/time.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/user.h> -#include <sys/vnode.h> -#include <machine/psl.h> -#include <machine/reg.h> -#include <machine/trap.h> -#if 0 -#include <machine/frame.h> -#endif -#include <sys/ptrace.h> - -int -process_read_regs(p, regs) - struct proc *p; - struct reg *regs; -{ - bcopy((caddr_t)USER_REGS(p), (caddr_t)regs, sizeof(struct reg)); - return (0); -} - -int -process_read_fpregs(p, regs) - struct proc *p; - struct fpreg *regs; -{ -#if 0 - extern struct fpstate initfpstate; - struct fpstate *statep = &initfpstate; - - /* NOTE: struct fpreg == struct fpstate */ - if (p->p_md.md_fpstate) - statep = p->p_md.md_fpstate; - bcopy(statep, regs, sizeof(struct fpreg)); -#endif - return 0; -} - -#ifdef PTRACE - -int -process_write_regs(p, regs) - struct proc *p; - struct reg *regs; -{ - bcopy((caddr_t)regs, (caddr_t)USER_REGS(p), sizeof(struct reg)); - return (0); -} - -int -process_sstep(p, sstep) - struct proc *p; - int sstep; -{ - if (sstep) - cpu_singlestep(p); - return (0); -} - -int -process_set_pc(p, addr) - struct proc *p; - caddr_t addr; -{ - struct reg *regs; - - regs = USER_REGS(p); - regs->sxip = (u_int)addr; - regs->snip = (u_int)addr + 4; - return (0); -} - -int -process_write_fpregs(p, regs) - struct proc *p; - struct fpreg *regs; -{ -#if 0 - if (p->p_md.md_fpstate == NULL) - return EINVAL; - - bcopy(regs, p->p_md.md_fpstate, sizeof(struct fpreg)); -#endif - return 0; -} - -#endif /* PTRACE */ diff --git a/sys/arch/luna88k/luna88k/vectors_88100.S b/sys/arch/luna88k/luna88k/vectors_88100.S deleted file mode 100644 index e9e5a66734e..00000000000 --- a/sys/arch/luna88k/luna88k/vectors_88100.S +++ /dev/null @@ -1,89 +0,0 @@ -/* $OpenBSD: vectors_88100.S,v 1.1 2004/04/21 15:24:14 aoyama Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1991, 1992 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -#include <machine/asm.h> - -#define UNDEFINED16 \ - word UNKNOWN_HANDLER; word UNKNOWN_HANDLER; \ - word UNKNOWN_HANDLER; word UNKNOWN_HANDLER; \ - word UNKNOWN_HANDLER; word UNKNOWN_HANDLER; \ - word UNKNOWN_HANDLER; word UNKNOWN_HANDLER; \ - word UNKNOWN_HANDLER; word UNKNOWN_HANDLER; \ - word UNKNOWN_HANDLER; word UNKNOWN_HANDLER; \ - word UNKNOWN_HANDLER; word UNKNOWN_HANDLER; \ - word UNKNOWN_HANDLER; word UNKNOWN_HANDLER; - - data - .align 4096 /* VBR points to page aligned list */ -GLOBAL(vector_list) - VECTOR(reset_handler) /* 00 */ - VECTOR(interrupt_handler) /* 01 */ - VECTOR(instruction_access_handler) /* 02 */ - VECTOR(data_exception_handler) /* 03 */ - VECTOR(misaligned_handler) /* 04 */ - VECTOR(unimplemented_handler) /* 05 */ - VECTOR(privilege_handler) /* 06 */ - VECTOR(bounds_handler) /* 07 */ - VECTOR(divide_handler) /* 08 */ - VECTOR(overflow_handler) /* 09 */ - VECTOR(error_handler) /* 0a */ - word UNKNOWN_HANDLER /* 0b */ - word UNKNOWN_HANDLER /* 0c */ - word UNKNOWN_HANDLER /* 0d */ - word UNKNOWN_HANDLER /* 0e */ - word UNKNOWN_HANDLER /* 0f */ - UNDEFINED16 /* 1x */ - UNDEFINED16 /* 2x */ - UNDEFINED16 /* 3x */ - UNDEFINED16 /* 4x */ - UNDEFINED16 /* 5x */ - UNDEFINED16 /* 6x */ - word UNKNOWN_HANDLER /* 70 */ - word UNKNOWN_HANDLER /* 71 */ - VECTOR(fp_precise_handler) /* 72 */ - VECTOR(fp_imprecise_handler) /* 73 */ - VECTOR(unimplemented_handler) /* 74 */ - word UNKNOWN_HANDLER /* 75 */ - VECTOR(unimplemented_handler) /* 76 */ - word UNKNOWN_HANDLER /* 77 */ - VECTOR(unimplemented_handler) /* 78 */ - word UNKNOWN_HANDLER /* 79 */ - VECTOR(unimplemented_handler) /* 7a */ - word UNKNOWN_HANDLER /* 7b */ - VECTOR(unimplemented_handler) /* 7c */ - word UNKNOWN_HANDLER /* 7d */ - VECTOR(unimplemented_handler) /* 7e */ - word UNKNOWN_HANDLER /* 7f */ - VECTOR(syscall_handler) /* 80 */ - VECTOR(syscall_handler) /* 81 */ - VECTOR(break) /* 82 */ - VECTOR(trace) /* 83 */ - VECTOR(entry) /* 84 */ -GLOBAL(vector_list_end) - word END_OF_VECTOR_LIST - diff --git a/sys/arch/m88k/conf/files.m88k b/sys/arch/m88k/conf/files.m88k index 93b8183e615..b6e9706cf15 100644 --- a/sys/arch/m88k/conf/files.m88k +++ b/sys/arch/m88k/conf/files.m88k @@ -1 +1,12 @@ -# $OpenBSD: files.m88k,v 1.1 2004/04/26 12:34:05 miod Exp $ +# $OpenBSD: files.m88k,v 1.2 2004/04/29 14:33:27 miod Exp $ + +file arch/m88k/m88k/cmmu.c +file arch/m88k/m88k/m88100_fp.S m88100 +file arch/m88k/m88k/m88110_fp.S m88110 +file arch/m88k/m88k/m88110_mmu.S m88110 +file arch/m88k/m88k/process.S +file arch/m88k/m88k/process_machdep.c +file arch/m88k/m88k/subr.S +file arch/m88k/m88k/trap.c +file arch/m88k/m88k/vectors_88100.S m88100 +file arch/m88k/m88k/vectors_88110.S m88110 diff --git a/sys/arch/mvme88k/mvme88k/cmmu.c b/sys/arch/m88k/m88k/cmmu.c index 6a2f26cef66..b82898ca979 100644 --- a/sys/arch/mvme88k/mvme88k/cmmu.c +++ b/sys/arch/m88k/m88k/cmmu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmmu.c,v 1.27 2004/01/20 14:35:54 miod Exp $ */ +/* $OpenBSD: cmmu.c,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur diff --git a/sys/arch/mvme88k/mvme88k/genassym.cf b/sys/arch/m88k/m88k/genassym.cf index efb3f5e8a50..9c7329013c3 100644 --- a/sys/arch/mvme88k/mvme88k/genassym.cf +++ b/sys/arch/m88k/m88k/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.10 2004/01/12 07:46:17 miod Exp $ +# $OpenBSD: genassym.cf,v 1.1 2004/04/29 14:33:27 miod Exp $ # # Copyright (c) 1982, 1990 The Regents of the University of California. # All rights reserved. @@ -28,7 +28,7 @@ # SUCH DAMAGE. # # @(#)genassym.c 7.8 (Berkeley) 5/7/91 -# $Id: genassym.cf,v 1.10 2004/01/12 07:46:17 miod Exp $ +# $Id: genassym.cf,v 1.1 2004/04/29 14:33:27 miod Exp $ # include <sys/param.h> diff --git a/sys/arch/mvme88k/mvme88k/m88100_fp.S b/sys/arch/m88k/m88k/m88100_fp.S index c1b11ca7947..5d32f10887c 100644 --- a/sys/arch/mvme88k/mvme88k/m88100_fp.S +++ b/sys/arch/m88k/m88k/m88100_fp.S @@ -1,4 +1,4 @@ -/* $OpenBSD: m88100_fp.S,v 1.21 2004/01/16 00:13:43 miod Exp $ */ +/* $OpenBSD: m88100_fp.S,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1991 Carnegie Mellon University diff --git a/sys/arch/mvme88k/mvme88k/m88110_fp.S b/sys/arch/m88k/m88k/m88110_fp.S index 91ed4c2f44d..254a14894aa 100644 --- a/sys/arch/mvme88k/mvme88k/m88110_fp.S +++ b/sys/arch/m88k/m88k/m88110_fp.S @@ -1,4 +1,4 @@ -/* $OpenBSD: m88110_fp.S,v 1.11 2003/08/12 19:33:27 miod Exp $ */ +/* $OpenBSD: m88110_fp.S,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * All rights reserved. diff --git a/sys/arch/mvme88k/mvme88k/m88110_mmu.S b/sys/arch/m88k/m88k/m88110_mmu.S index ab5b6cf90f6..1daff42ed48 100644 --- a/sys/arch/mvme88k/mvme88k/m88110_mmu.S +++ b/sys/arch/m88k/m88k/m88110_mmu.S @@ -1,4 +1,4 @@ -# $OpenBSD: m88110_mmu.S,v 1.9 2003/08/20 20:33:47 miod Exp $ +# $OpenBSD: m88110_mmu.S,v 1.1 2004/04/29 14:33:27 miod Exp $ /* * Copyright (c) 2000 Steve Murphree, Jr. * All rights reserved. diff --git a/sys/arch/mvme88k/mvme88k/process.S b/sys/arch/m88k/m88k/process.S index 76984a44e08..9c460e544da 100644 --- a/sys/arch/mvme88k/mvme88k/process.S +++ b/sys/arch/m88k/m88k/process.S @@ -1,4 +1,4 @@ -/* $OpenBSD: process.S,v 1.29 2004/01/17 22:35:41 miod Exp $ */ +/* $OpenBSD: process.S,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Copyright (c) 1996 Nivas Madhur * All rights reserved. diff --git a/sys/arch/mvme88k/mvme88k/process_machdep.c b/sys/arch/m88k/m88k/process_machdep.c index 1230bc39692..41071bf4c07 100644 --- a/sys/arch/mvme88k/mvme88k/process_machdep.c +++ b/sys/arch/m88k/m88k/process_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: process_machdep.c,v 1.12 2004/01/12 21:33:15 miod Exp $ */ +/* $OpenBSD: process_machdep.c,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Copyright (c) 1993 The Regents of the University of California. diff --git a/sys/arch/mvme88k/mvme88k/locore_asm_routines.S b/sys/arch/m88k/m88k/subr.S index 33ba3f9376c..bafc847981d 100644 --- a/sys/arch/mvme88k/mvme88k/locore_asm_routines.S +++ b/sys/arch/m88k/m88k/subr.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore_asm_routines.S,v 1.28 2004/01/23 17:26:06 miod Exp $ */ +/* $OpenBSD: subr.S,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1993-1992 Carnegie Mellon University diff --git a/sys/arch/luna88k/luna88k/trap.c b/sys/arch/m88k/m88k/trap.c index d7bee6ad47b..1bd4e5b6fc2 100644 --- a/sys/arch/luna88k/luna88k/trap.c +++ b/sys/arch/m88k/m88k/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.1 2004/04/21 15:24:14 aoyama Exp $ */ +/* $OpenBSD: trap.c,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur diff --git a/sys/arch/mvme88k/mvme88k/vectors_88100.S b/sys/arch/m88k/m88k/vectors_88100.S index d12e9fb7c0b..e3a77568f2e 100644 --- a/sys/arch/mvme88k/mvme88k/vectors_88100.S +++ b/sys/arch/m88k/m88k/vectors_88100.S @@ -1,4 +1,4 @@ -/* $OpenBSD: vectors_88100.S,v 1.1 2003/01/14 03:20:16 miod Exp $ */ +/* $OpenBSD: vectors_88100.S,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1991, 1992 Carnegie Mellon University diff --git a/sys/arch/mvme88k/mvme88k/vectors_88110.S b/sys/arch/m88k/m88k/vectors_88110.S index ae07c247238..f0c70865f12 100644 --- a/sys/arch/mvme88k/mvme88k/vectors_88110.S +++ b/sys/arch/m88k/m88k/vectors_88110.S @@ -1,4 +1,4 @@ -/* $OpenBSD: vectors_88110.S,v 1.1 2003/01/14 03:20:16 miod Exp $ */ +/* $OpenBSD: vectors_88110.S,v 1.1 2004/04/29 14:33:27 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1991, 1992 Carnegie Mellon University diff --git a/sys/arch/mvme88k/conf/GENERIC b/sys/arch/mvme88k/conf/GENERIC index d1939c3e060..0ec3af450cf 100644 --- a/sys/arch/mvme88k/conf/GENERIC +++ b/sys/arch/mvme88k/conf/GENERIC @@ -1,15 +1,18 @@ -# $OpenBSD: GENERIC,v 1.41 2004/04/26 12:34:05 miod Exp $ +# $OpenBSD: GENERIC,v 1.42 2004/04/29 14:33:27 miod Exp $ machine mvme88k m88k include "../../../conf/GENERIC" -option MVME187 # support for 187 -option MVME188 # support for 188 -option MVME197 # support for 197 +# Processor type +option M88100 +option M88110 + +option MVME187 # support for 187 (requires M88100) +option MVME188 # support for 188 (requires M88100) +option MVME197 # support for 197 (requires M88110) + option "NCPUS=1" # number of CPUs supported (max 4) -option BUGMAP # use the Bug ROM VME mappings -#option DEBUG # print debugging statements # Define this if your processor has the xxx.usr bug (mask C82N) option ERRATA__XXX_USR diff --git a/sys/arch/mvme88k/conf/M187 b/sys/arch/mvme88k/conf/M187 index f16c6f61910..037f444695a 100644 --- a/sys/arch/mvme88k/conf/M187 +++ b/sys/arch/mvme88k/conf/M187 @@ -1,13 +1,13 @@ -# $OpenBSD: M187,v 1.29 2004/04/26 12:34:05 miod Exp $ +# $OpenBSD: M187,v 1.30 2004/04/29 14:33:27 miod Exp $ machine mvme88k m88k include "../../../conf/GENERIC" -option MVME187 # support for 187 -option BUGMAP # use Bug Rom VME Mappings -#option DEBUG # print debugging statements -#option EH_DEBUG # debugging code for exception handlers +# Processor type +option M88100 + +option MVME187 # support for 187 (requires M88100) # Define this if your processor has the xxx.usr bug (mask C82N) option ERRATA__XXX_USR diff --git a/sys/arch/mvme88k/conf/M188 b/sys/arch/mvme88k/conf/M188 index 1fef0a26aaf..9ebc241e5e9 100644 --- a/sys/arch/mvme88k/conf/M188 +++ b/sys/arch/mvme88k/conf/M188 @@ -1,14 +1,16 @@ -# $OpenBSD: M188,v 1.22 2004/04/26 12:34:05 miod Exp $ +# $OpenBSD: M188,v 1.23 2004/04/29 14:33:27 miod Exp $ machine mvme88k m88k include "../../../conf/GENERIC" -option MVME188 # support for 188 +# Processor type +option M88100 +option M88110 + +option MVME188 # support for 188 (requires M88100) + option "NCPUS=1" # Number of cpus supported (max 4) -option BUGMAP # use Bug Rom VME Mappings -#option DEBUG # print debugging statements -#option EH_DEBUG # debugging code for exception handlers # Define this if your processor has the xxx.usr bug (mask C82N) option ERRATA__XXX_USR diff --git a/sys/arch/mvme88k/conf/M197 b/sys/arch/mvme88k/conf/M197 index 3b9fe1b6952..ae4f9f8ee71 100644 --- a/sys/arch/mvme88k/conf/M197 +++ b/sys/arch/mvme88k/conf/M197 @@ -1,17 +1,15 @@ -# $OpenBSD: M197,v 1.23 2004/04/26 12:34:05 miod Exp $ +# $OpenBSD: M197,v 1.24 2004/04/29 14:33:27 miod Exp $ machine mvme88k m88k include "../../../conf/GENERIC" -option MVME197 # support for 197 -option "NCPUS=1" # Number of cpus supported (max 4) -option BUGMAP # use Bug Rom VME Mappings -#option DEBUG # print debugging statements -#option EH_DEBUG # debugging code for exception handlers +# Processor type +option M88110 + +option MVME197 # support for 197 (requires M88110) -# Define this if your processor has the xxx.usr bug (mask C82N) -option ERRATA__XXX_USR +option "NCPUS=1" # Number of cpus supported (max 4) maxusers 64 diff --git a/sys/arch/mvme88k/conf/Makefile.mvme88k b/sys/arch/mvme88k/conf/Makefile.mvme88k index f292482a6b6..080c03dd8fe 100644 --- a/sys/arch/mvme88k/conf/Makefile.mvme88k +++ b/sys/arch/mvme88k/conf/Makefile.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.mvme88k,v 1.32 2004/04/05 19:17:25 miod Exp $ +# $OpenBSD: Makefile.mvme88k,v 1.33 2004/04/29 14:33:27 miod Exp $ # # Makefile for OpenBSD # @@ -32,6 +32,7 @@ STRIP?= strip S!= cd ../../../..; pwd .endif MVME88K= $S/arch/mvme88k +M88K= $S/arch/m88k INCLUDES= -nostdinc -I. -I$S/arch -I$S CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dmvme88k -Dm88k @@ -54,14 +55,7 @@ HOSTED_CFLAGS?= ${CFLAGS} ### CPU configuration -.if (${IDENT:M-DMVME187} != "" || ${IDENT:M-DMVME188} != "") -CPPFLAGS+= -DM88100 -.endif -.if (${IDENT:M-DMVME197} != "") -CPPFLAGS+= -DM88110 -.endif - -# syntaxic sugar for 187, which do not exist with multiple processors +# syntaxic sugar for 187, which does not exist with multiple processors .if (${IDENT:M-DMVME187} != "" && ${IDENT:M-DNCPUS} == "") CPPFLAGS+= -DNCPUS=1 .endif @@ -129,9 +123,9 @@ LINKFLAGS+= -x %LOAD -assym.h: $S/kern/genassym.sh ${MVME88K}/mvme88k/genassym.cf Makefile +assym.h: $S/kern/genassym.sh ${M88K}/m88k/genassym.cf Makefile sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} \ - ${PARAM} < ${MVME88K}/mvme88k/genassym.cf > assym.h.tmp && \ + ${PARAM} < ${M88K}/m88k/genassym.cf > assym.h.tmp && \ mv -f assym.h.tmp assym.h param.c: $S/conf/param.c diff --git a/sys/arch/mvme88k/conf/RAMDISK b/sys/arch/mvme88k/conf/RAMDISK index 29eb6dfab54..7fa300ed1dd 100644 --- a/sys/arch/mvme88k/conf/RAMDISK +++ b/sys/arch/mvme88k/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.22 2004/04/26 12:34:05 miod Exp $ +# $OpenBSD: RAMDISK,v 1.23 2004/04/29 14:33:27 miod Exp $ machine mvme88k m88k @@ -6,12 +6,15 @@ machine mvme88k m88k option MINIROOTSIZE=4096 option RAMDISK_HOOKS -option MVME187 # support for 187 -option MVME188 # support for 188 -option MVME197 # support for 197 +# Processor type +option M88100 +option M88110 + +option MVME187 # support for 187 (requires M88100) +option MVME188 # support for 188 (requires M88100) +option MVME197 # support for 197 (requires M88110) option "NCPUS=1" # number of CPUs supported (max 4) -option BUGMAP # use the Bug ROM VME mappings # Define this if your processor has the xxx.usr bug (mask C82N) option ERRATA__XXX_USR diff --git a/sys/arch/mvme88k/conf/files.mvme88k b/sys/arch/mvme88k/conf/files.mvme88k index 723cb448f29..00c51acde68 100644 --- a/sys/arch/mvme88k/conf/files.mvme88k +++ b/sys/arch/mvme88k/conf/files.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.mvme88k,v 1.26 2004/04/24 19:51:44 miod Exp $ +# $OpenBSD: files.mvme88k,v 1.27 2004/04/29 14:33:27 miod Exp $ # maxpartitions 16 @@ -77,26 +77,16 @@ file netns/ns_cksum.c ns file arch/mvme88k/mvme88k/autoconf.c file arch/mvme88k/mvme88k/conf.c -file arch/mvme88k/mvme88k/cmmu.c -file arch/mvme88k/mvme88k/m8820x.c mvme187 | mvme188 -file arch/mvme88k/mvme88k/m88110.c mvme197 +file arch/mvme88k/mvme88k/m8820x.c m88100 +file arch/mvme88k/mvme88k/m88110.c m88110 file arch/mvme88k/mvme88k/disksubr.c file arch/mvme88k/mvme88k/dkbad.c file arch/mvme88k/mvme88k/eh.S -file arch/mvme88k/mvme88k/locore_asm_routines.S file arch/mvme88k/mvme88k/locore_c_routines.c -file arch/mvme88k/mvme88k/m88100_fp.S mvme187 | mvme188 -file arch/mvme88k/mvme88k/m88110_fp.S mvme197 -file arch/mvme88k/mvme88k/m88110_mmu.S mvme197 file arch/mvme88k/mvme88k/machdep.c file arch/mvme88k/mvme88k/mem.c file arch/mvme88k/mvme88k/pmap.c file arch/mvme88k/mvme88k/pmap_table.c -file arch/mvme88k/mvme88k/process.S -file arch/mvme88k/mvme88k/process_machdep.c -file arch/mvme88k/mvme88k/trap.c -file arch/mvme88k/mvme88k/vectors_88100.S mvme187 | mvme188 -file arch/mvme88k/mvme88k/vectors_88110.S mvme197 file arch/mvme88k/mvme88k/vm_machdep.c file arch/mvme88k/ddb/db_disasm.c ddb file arch/mvme88k/ddb/db_interface.c ddb diff --git a/sys/arch/mvme88k/mvme88k/trap.c b/sys/arch/mvme88k/mvme88k/trap.c deleted file mode 100644 index e1d6f95faf0..00000000000 --- a/sys/arch/mvme88k/mvme88k/trap.c +++ /dev/null @@ -1,1797 +0,0 @@ -/* $OpenBSD: trap.c,v 1.72 2004/01/29 21:39:05 deraadt Exp $ */ -/* - * Copyright (c) 1998 Steve Murphree, Jr. - * Copyright (c) 1996 Nivas Madhur - * 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 Nivas Madhur. - * 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. - * - */ -/* - * Mach Operating System - * Copyright (c) 1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/user.h> -#include <sys/syscall.h> -#include <sys/systm.h> -#include <sys/ktrace.h> - -#include "systrace.h" -#include <dev/systrace.h> - -#include <uvm/uvm_extern.h> - -#include <machine/asm_macro.h> /* enable/disable interrupts */ -#include <machine/cpu.h> -#include <machine/locore.h> -#ifdef M88100 -#include <machine/m88100.h> /* DMT_xxx */ -#include <machine/m8820x.h> /* CMMU_PFSR_xxx */ -#endif -#ifdef M88110 -#include <machine/m88110.h> -#endif -#include <machine/pcb.h> /* FIP_E, etc. */ -#include <machine/psl.h> /* FIP_E, etc. */ -#include <machine/trap.h> - -#include <machine/db_machdep.h> -#ifdef DDB -#include <ddb/db_output.h> /* db_printf() */ -#endif /* DDB */ -#define SSBREAKPOINT (0xF000D1F8U) /* Single Step Breakpoint */ - -#ifdef DDB -#define DEBUG_MSG(x) db_printf x -#else -#define DEBUG_MSG(x) -#endif /* DDB */ - -#define USERMODE(PSR) (((PSR) & PSR_MODE) == 0) -#define SYSTEMMODE(PSR) (((PSR) & PSR_MODE) != 0) - -/* sigh */ -extern int procfs_domem(struct proc *, struct proc *, void *, struct uio *); - -__dead void panictrap(int, struct trapframe *); -__dead void error_fatal(struct trapframe *); - -extern void regdump(struct trapframe *f); - -const char *trap_type[] = { - "Reset", - "Interrupt Exception", - "Instruction Access", - "Data Access Exception", - "Misaligned Access", - "Unimplemented Opcode", - "Privilege Violation" - "Bounds Check Violation", - "Illegal Integer Divide", - "Integer Overflow", - "Error Exception", - "Non-Maskable Exception", -}; -const int trap_types = sizeof trap_type / sizeof trap_type[0]; - -const char *pbus_exception_type[] = { - "Success (No Fault)", - "unknown 1", - "unknown 2", - "Bus Error", - "Segment Fault", - "Page Fault", - "Supervisor Violation", - "Write Violation", -}; - -static inline void -userret(struct proc *p, struct trapframe *frame, u_quad_t oticks) -{ - int sig; - - /* take pending signals */ - while ((sig = CURSIG(p)) != 0) - postsig(sig); - p->p_priority = p->p_usrpri; - - if (want_resched) { - /* - * We're being preempted. - */ - preempt(NULL); - while ((sig = CURSIG(p)) != 0) - postsig(sig); - } - - /* - * If profiling, charge recent system time to the trapped pc. - */ - if (p->p_flag & P_PROFIL) { - extern int psratio; - - addupc_task(p, frame->tf_sxip & XIP_ADDR, - (int)(p->p_sticks - oticks) * psratio); - } - curpriority = p->p_priority; -} - -__dead void -panictrap(int type, struct trapframe *frame) -{ -#ifdef DDB - static int panicing = 0; - - if (panicing++ == 0) { - switch (cputyp) { -#ifdef M88100 - case CPU_88100: - if (type == 2) { - /* instruction exception */ - db_printf("\nInstr access fault (%s) v = %x, " - "frame %p\n", - pbus_exception_type[ - CMMU_PFSR_FAULT(frame->tf_ipfsr)], - frame->tf_sxip & XIP_ADDR, frame); - } else if (type == 3) { - /* data access exception */ - db_printf("\nData access fault (%s) v = %x, " - "frame %p\n", - pbus_exception_type[ - CMMU_PFSR_FAULT(frame->tf_dpfsr)], - frame->tf_sxip & XIP_ADDR, frame); - } else - db_printf("\nTrap type %d, v = %x, frame %p\n", - type, frame->tf_sxip & XIP_ADDR, frame); - break; -#endif -#ifdef M88110 - case CPU_88110: - db_printf("\nTrap type %d, v = %x, frame %p\n", - type, frame->tf_exip, frame); - break; -#endif - } - regdump(frame); - } -#endif - if ((u_int)type < trap_types) - panic(trap_type[type]); - else - panic("trap %d", type); - /*NOTREACHED*/ -} - -#ifdef M88100 -void -m88100_trap(unsigned type, struct trapframe *frame) -{ - struct proc *p; - u_quad_t sticks = 0; - struct vm_map *map; - vaddr_t va; - vm_prot_t ftype; - int fault_type, pbus_type; - u_long fault_code; - unsigned nss, fault_addr; - struct vmspace *vm; - union sigval sv; - int result; -#ifdef DDB - int s; -#endif - int sig = 0; - - extern struct vm_map *kernel_map; - extern caddr_t guarded_access_start; - extern caddr_t guarded_access_end; - extern caddr_t guarded_access_bad; - - uvmexp.traps++; - if ((p = curproc) == NULL) - p = &proc0; - - if (USERMODE(frame->tf_epsr)) { - sticks = p->p_sticks; - type += T_USER; - p->p_md.md_tf = frame; /* for ptrace/signals */ - } - fault_type = 0; - fault_code = 0; - fault_addr = frame->tf_sxip & XIP_ADDR; - - switch (type) { - default: - panictrap(frame->tf_vector, frame); - break; - /*NOTREACHED*/ - -#if defined(DDB) - case T_KDB_BREAK: - s = splhigh(); - db_enable_interrupt(); - ddb_break_trap(T_KDB_BREAK, (db_regs_t*)frame); - db_disable_interrupt(); - splx(s); - return; - case T_KDB_ENTRY: - s = splhigh(); - db_enable_interrupt(); - ddb_entry_trap(T_KDB_ENTRY, (db_regs_t*)frame); - db_disable_interrupt(); - splx(s); - return; -#endif /* DDB */ - case T_ILLFLT: - DEBUG_MSG(("Unimplemented opcode!\n")); - panictrap(frame->tf_vector, frame); - break; - case T_INT: - case T_INT+T_USER: - /* This function pointer is set in machdep.c - It calls m188_ext_int or sbc_ext_int depending - on the value of brdtyp - smurph */ - (*md.interrupt_func)(T_INT, frame); - return; - - case T_MISALGNFLT: - DEBUG_MSG(("kernel misaligned " - "access exception @ 0x%08x\n", frame->tf_sxip)); - panictrap(frame->tf_vector, frame); - break; - - case T_INSTFLT: - /* kernel mode instruction access fault. - * Should never, never happen for a non-paged kernel. - */ -#ifdef TRAPDEBUG - pbus_type = CMMU_PFSR_FAULT(frame->tf_ipfsr); - printf("Kernel Instruction fault #%d (%s) v = 0x%x, frame 0x%x cpu %d\n", - pbus_type, pbus_exception_type[pbus_type], - fault_addr, frame, frame->tf_cpu); -#endif - panictrap(frame->tf_vector, frame); - break; - - case T_DATAFLT: - /* kernel mode data fault */ - - /* data fault on the user address? */ - if ((frame->tf_dmt0 & DMT_DAS) == 0) { - type = T_DATAFLT + T_USER; - goto user_fault; - } - - fault_addr = frame->tf_dma0; - if (frame->tf_dmt0 & (DMT_WRITE|DMT_LOCKBAR)) { - ftype = VM_PROT_READ|VM_PROT_WRITE; - fault_code = VM_PROT_WRITE; - } else { - ftype = VM_PROT_READ; - fault_code = VM_PROT_READ; - } - - va = trunc_page((vaddr_t)fault_addr); - if (va == 0) { - panic("trap: bad kernel access at %x", fault_addr); - } - - vm = p->p_vmspace; - map = kernel_map; - - pbus_type = CMMU_PFSR_FAULT(frame->tf_dpfsr); -#ifdef TRAPDEBUG - printf("Kernel Data access fault #%d (%s) v = 0x%x, frame 0x%x cpu %d\n", - pbus_type, pbus_exception_type[pbus_type], - fault_addr, frame, frame->tf_cpu); -#endif - - switch (pbus_type) { - case CMMU_PFSR_BERROR: - /* - * If it is a guarded access, bus error is OK. - */ - if ((frame->tf_sxip & XIP_ADDR) >= - (unsigned)&guarded_access_start && - (frame->tf_sxip & XIP_ADDR) <= - (unsigned)&guarded_access_end) { - frame->tf_snip = - ((unsigned)&guarded_access_bad ) | NIP_V; - frame->tf_sfip = - ((unsigned)&guarded_access_bad + 4) | FIP_V; - frame->tf_sxip = 0; - /* We sort of resolved the fault ourselves - * because we know where it came from - * [guarded_access()]. But we must still think - * about the other possible transactions in - * dmt1 & dmt2. Mark dmt0 so that - * data_access_emulation skips it. XXX smurph - */ - frame->tf_dmt0 |= DMT_SKIP; - data_access_emulation((unsigned *)frame); - frame->tf_dpfsr = 0; - frame->tf_dmt0 = 0; - return; - } - break; - case CMMU_PFSR_SUCCESS: - /* - * The fault was resolved. Call data_access_emulation - * to drain the data unit pipe line and reset dmt0 - * so that trap won't get called again. - */ - data_access_emulation((unsigned *)frame); - frame->tf_dpfsr = 0; - frame->tf_dmt0 = 0; - return; - case CMMU_PFSR_SFAULT: - case CMMU_PFSR_PFAULT: - result = uvm_fault(map, va, VM_FAULT_INVALID, ftype); - if (result == 0) { - /* - * We could resolve the fault. Call - * data_access_emulation to drain the data - * unit pipe line and reset dmt0 so that trap - * won't get called again. - */ - data_access_emulation((unsigned *)frame); - frame->tf_dpfsr = 0; - frame->tf_dmt0 = 0; - return; - } - break; - } -#ifdef TRAPDEBUG - printf("PBUS Fault %d (%s) va = 0x%x\n", pbus_type, - pbus_exception_type[pbus_type], va); -#endif - panictrap(frame->tf_vector, frame); - /* NOTREACHED */ - case T_INSTFLT+T_USER: - /* User mode instruction access fault */ - /* FALLTHROUGH */ - case T_DATAFLT+T_USER: -user_fault: - if (type == T_INSTFLT + T_USER) { - pbus_type = CMMU_PFSR_FAULT(frame->tf_ipfsr); -#ifdef TRAPDEBUG - printf("User Instruction fault #%d (%s) v = 0x%x, frame 0x%x cpu %d\n", - pbus_type, pbus_exception_type[pbus_type], - fault_addr, frame, frame->tf_cpu); -#endif - } else { - fault_addr = frame->tf_dma0; - pbus_type = CMMU_PFSR_FAULT(frame->tf_dpfsr); -#ifdef TRAPDEBUG - printf("User Data access fault #%d (%s) v = 0x%x, frame 0x%x cpu %d\n", - pbus_type, pbus_exception_type[pbus_type], - fault_addr, frame, frame->tf_cpu); -#endif - } - - if (frame->tf_dmt0 & (DMT_WRITE | DMT_LOCKBAR)) { - ftype = VM_PROT_READ | VM_PROT_WRITE; - fault_code = VM_PROT_WRITE; - } else { - ftype = VM_PROT_READ; - fault_code = VM_PROT_READ; - } - - va = trunc_page((vaddr_t)fault_addr); - - vm = p->p_vmspace; - map = &vm->vm_map; - - /* Call uvm_fault() to resolve non-bus error faults */ - switch (pbus_type) { - case CMMU_PFSR_SUCCESS: - result = 0; - break; - case CMMU_PFSR_BERROR: - result = EACCES; - break; - default: - result = uvm_fault(map, va, VM_FAULT_INVALID, ftype); - if (result == EACCES) - result = EFAULT; - break; - } - - if ((caddr_t)va >= vm->vm_maxsaddr) { - if (result == 0) { - nss = btoc(USRSTACK - va);/* XXX check this */ - if (nss > vm->vm_ssize) - vm->vm_ssize = nss; - } - } - - /* - * This could be a fault caused in copyin*() - * while accessing user space. - */ - if (result != 0 && p->p_addr->u_pcb.pcb_onfault != NULL) { - frame->tf_snip = p->p_addr->u_pcb.pcb_onfault | NIP_V; - frame->tf_sfip = (p->p_addr->u_pcb.pcb_onfault + 4) | FIP_V; - frame->tf_sxip = 0; - /* - * Continue as if the fault had been resolved, but - * do not try to complete the faulting access. - */ - frame->tf_dmt0 |= DMT_SKIP; - result = 0; - } - - if (result == 0) { - if (type == T_DATAFLT+T_USER) { - /* - * We could resolve the fault. Call - * data_access_emulation to drain the data unit - * pipe line and reset dmt0 so that trap won't - * get called again. - */ - data_access_emulation((unsigned *)frame); - frame->tf_dpfsr = 0; - frame->tf_dmt0 = 0; - } else { - /* - * back up SXIP, SNIP, - * clearing the Error bit - */ - frame->tf_sfip = frame->tf_snip & ~FIP_E; - frame->tf_snip = frame->tf_sxip & ~NIP_E; - frame->tf_ipfsr = 0; - } - } else { - sig = result == EACCES ? SIGBUS : SIGSEGV; - fault_type = result == EACCES ? - BUS_ADRERR : SEGV_MAPERR; - } - break; - case T_MISALGNFLT+T_USER: - sig = SIGBUS; - fault_type = BUS_ADRALN; - break; - case T_PRIVINFLT+T_USER: - case T_ILLFLT+T_USER: -#ifndef DDB - case T_KDB_BREAK: - case T_KDB_ENTRY: -#endif - case T_KDB_BREAK+T_USER: - case T_KDB_ENTRY+T_USER: - case T_KDB_TRACE: - case T_KDB_TRACE+T_USER: - sig = SIGILL; - break; - case T_BNDFLT+T_USER: - sig = SIGFPE; - break; - case T_ZERODIV+T_USER: - sig = SIGFPE; - fault_type = FPE_INTDIV; - break; - case T_OVFFLT+T_USER: - sig = SIGFPE; - fault_type = FPE_INTOVF; - break; - case T_FPEPFLT+T_USER: - case T_FPEIFLT+T_USER: - sig = SIGFPE; - break; - case T_SIGSYS+T_USER: - sig = SIGSYS; - break; - case T_SIGTRAP+T_USER: - sig = SIGTRAP; - fault_type = TRAP_TRACE; - break; - case T_STEPBPT+T_USER: - /* - * This trap is used by the kernel to support single-step - * debugging (although any user could generate this trap - * which should probably be handled differently). When a - * process is continued by a debugger with the PT_STEP - * function of ptrace (single step), the kernel inserts - * one or two breakpoints in the user process so that only - * one instruction (or two in the case of a delayed branch) - * is executed. When this breakpoint is hit, we get the - * T_STEPBPT trap. - */ - { - unsigned va; - unsigned instr; - struct uio uio; - struct iovec iov; - unsigned pc = PC_REGS(&frame->tf_regs); - - /* read break instruction */ - copyin((caddr_t)pc, &instr, sizeof(unsigned)); -#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 - /* check and see if we got here by accident */ - if ((p->p_md.md_ss_addr != pc && - p->p_md.md_ss_taken_addr != pc) || - instr != SSBREAKPOINT) { - sig = SIGTRAP; - fault_type = TRAP_TRACE; - break; - } - /* restore original instruction and clear BP */ - instr = p->p_md.md_ss_instr; - va = p->p_md.md_ss_addr; - if (va != 0) { - iov.iov_base = (caddr_t)&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; - procfs_domem(p, p, NULL, &uio); - } - - /* branch taken instruction */ - instr = p->p_md.md_ss_taken_instr; - va = p->p_md.md_ss_taken_addr; - if (instr != 0) { - iov.iov_base = (caddr_t)&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; - procfs_domem(p, p, NULL, &uio); - } -#if 1 - frame->tf_sfip = frame->tf_snip; /* set up next FIP */ - frame->tf_snip = pc; /* set up next NIP */ - frame->tf_snip |= 2; /* set valid bit */ -#endif - p->p_md.md_ss_addr = 0; - p->p_md.md_ss_instr = 0; - p->p_md.md_ss_taken_addr = 0; - p->p_md.md_ss_taken_instr = 0; - sig = SIGTRAP; - fault_type = TRAP_BRKPT; - } - break; - - case T_USERBPT+T_USER: - /* - * This trap is meant to be used by debuggers to implement - * breakpoint debugging. When we get this trap, we just - * return a signal which gets caught by the debugger. - */ - frame->tf_sfip = frame->tf_snip; /* set up the next FIP */ - frame->tf_snip = frame->tf_sxip; /* set up the next NIP */ - sig = SIGTRAP; - fault_type = TRAP_BRKPT; - break; - - case T_ASTFLT+T_USER: - uvmexp.softs++; - want_ast = 0; - if (p->p_flag & P_OWEUPC) { - p->p_flag &= ~P_OWEUPC; - ADDUPROF(p); - } - break; - } - - /* - * If trap from supervisor mode, just return - */ - if (type < T_USER) - return; - - if (sig) { - sv.sival_int = fault_addr; - trapsignal(p, sig, fault_code, fault_type, sv); - /* - * don't want multiple faults - we are going to - * deliver signal. - */ - frame->tf_dmt0 = 0; - frame->tf_ipfsr = frame->tf_dpfsr = 0; - } - - userret(p, frame, sticks); -} -#endif /* m88100 */ - -#ifdef M88110 -void -m88110_trap(unsigned type, struct trapframe *frame) -{ - struct proc *p; - u_quad_t sticks = 0; - struct vm_map *map; - vaddr_t va; - vm_prot_t ftype; - int fault_type; - u_long fault_code; - unsigned nss, fault_addr; - struct vmspace *vm; - union sigval sv; - int result; -#ifdef DDB - int s; /* IPL */ -#endif - int sig = 0; - pt_entry_t *pte; - - extern struct vm_map *kernel_map; - extern unsigned guarded_access_start; - extern unsigned guarded_access_end; - extern unsigned guarded_access_bad; - extern pt_entry_t *pmap_pte(pmap_t, vaddr_t); - - uvmexp.traps++; - if ((p = curproc) == NULL) - p = &proc0; - - if (USERMODE(frame->tf_epsr)) { - sticks = p->p_sticks; - type += T_USER; - p->p_md.md_tf = frame; /* for ptrace/signals */ - } - fault_type = 0; - fault_code = 0; - fault_addr = frame->tf_exip & XIP_ADDR; - - switch (type) { - default: - panictrap(frame->tf_vector, frame); - break; - /*NOTREACHED*/ - - case T_197_READ+T_USER: - case T_197_READ: - DEBUG_MSG(("DMMU read miss: Hardware Table Searches should be enabled!\n")); - panictrap(frame->tf_vector, frame); - break; - /*NOTREACHED*/ - case T_197_WRITE+T_USER: - case T_197_WRITE: - DEBUG_MSG(("DMMU write miss: Hardware Table Searches should be enabled!\n")); - panictrap(frame->tf_vector, frame); - break; - /*NOTREACHED*/ - case T_197_INST+T_USER: - case T_197_INST: - DEBUG_MSG(("IMMU miss: Hardware Table Searches should be enabled!\n")); - panictrap(frame->tf_vector, frame); - break; - /*NOTREACHED*/ -#ifdef DDB - case T_KDB_TRACE: - s = splhigh(); - db_enable_interrupt(); - ddb_break_trap(T_KDB_TRACE, (db_regs_t*)frame); - db_disable_interrupt(); - splx(s); - return; - case T_KDB_BREAK: - s = splhigh(); - db_enable_interrupt(); - ddb_break_trap(T_KDB_BREAK, (db_regs_t*)frame); - db_disable_interrupt(); - splx(s); - return; - case T_KDB_ENTRY: - s = splhigh(); - db_enable_interrupt(); - ddb_entry_trap(T_KDB_ENTRY, (db_regs_t*)frame); - db_disable_interrupt(); - /* skip one instruction */ - if (frame->tf_exip & 1) - frame->tf_exip = frame->tf_enip; - else - frame->tf_exip += 4; - frame->tf_enip = 0; - splx(s); - return; -#if 0 - case T_ILLFLT: - s = splhigh(); - db_enable_interrupt(); - ddb_error_trap(type == T_ILLFLT ? "unimplemented opcode" : - "error fault", (db_regs_t*)frame); - db_disable_interrupt(); - splx(s); - return; -#endif /* 0 */ -#endif /* DDB */ - case T_ILLFLT: - DEBUG_MSG(("Unimplemented opcode!\n")); - panictrap(frame->tf_vector, frame); - break; - case T_NON_MASK: - case T_NON_MASK+T_USER: - /* This function pointer is set in machdep.c - It calls m197_ext_int - smurph */ - (*md.interrupt_func)(T_NON_MASK, frame); - return; - case T_INT: - case T_INT+T_USER: - (*md.interrupt_func)(T_INT, frame); - return; - case T_MISALGNFLT: - DEBUG_MSG(("kernel mode misaligned " - "access exception @ 0x%08x\n", frame->tf_exip)); - panictrap(frame->tf_vector, frame); - break; - /*NOTREACHED*/ - - case T_INSTFLT: - /* kernel mode instruction access fault. - * Should never, never happen for a non-paged kernel. - */ -#ifdef TRAPDEBUG - printf("Kernel Instruction fault exip %x isr %x ilar %x\n", - frame->tf_exip, frame->tf_isr, frame->tf_ilar); -#endif - panictrap(frame->tf_vector, frame); - break; - /*NOTREACHED*/ - - case T_DATAFLT: - /* kernel mode data fault */ - - /* data fault on the user address? */ - if ((frame->tf_dsr & CMMU_DSR_SU) == 0) { - type = T_DATAFLT + T_USER; - goto m88110_user_fault; - } - -#ifdef TRAPDEBUG - printf("Kernel Data access fault exip %x dsr %x dlar %x\n", - frame->tf_exip, frame->tf_dsr, frame->tf_dlar); -#endif - - fault_addr = frame->tf_dlar; - if (frame->tf_dsr & CMMU_DSR_RW) { - ftype = VM_PROT_READ; - fault_code = VM_PROT_READ; - } else { - ftype = VM_PROT_READ|VM_PROT_WRITE; - fault_code = VM_PROT_WRITE; - } - - va = trunc_page((vaddr_t)fault_addr); - if (va == 0) { - panic("trap: bad kernel access at %x", fault_addr); - } - - vm = p->p_vmspace; - map = kernel_map; - - if (frame->tf_dsr & CMMU_DSR_BE) { - /* - * If it is a guarded access, bus error is OK. - */ - if ((frame->tf_exip & XIP_ADDR) >= - (unsigned)&guarded_access_start && - (frame->tf_exip & XIP_ADDR) <= - (unsigned)&guarded_access_end) { - frame->tf_exip = (unsigned)&guarded_access_bad; - frame->tf_enip = 0; - return; - } - } - if (frame->tf_dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) { - frame->tf_dsr &= ~CMMU_DSR_WE; /* undefined */ - /* - * On a segment or a page fault, call uvm_fault() to - * resolve the fault. - */ - result = uvm_fault(map, va, VM_FAULT_INVALID, ftype); - if (result == 0) - return; - } - if (frame->tf_dsr & CMMU_DSR_WE) { /* write fault */ - /* - * This could be a write protection fault or an - * exception to set the used and modified bits - * in the pte. Basically, if we got a write error, - * then we already have a pte entry that faulted - * in from a previous seg fault or page fault. - * Get the pte and check the status of the - * modified and valid bits to determine if this - * indeed a real write fault. XXX smurph - */ - pte = pmap_pte(map->pmap, va); - if (pte == PT_ENTRY_NULL) - panic("NULL pte on write fault??"); - if (!(*pte & PG_M) && !(*pte & PG_RO)) { - /* Set modified bit and try the write again. */ -#ifdef TRAPDEBUG - printf("Corrected kernel write fault, map %x pte %x\n", - map->pmap, *pte); -#endif - *pte |= PG_M; - return; -#if 1 /* shouldn't happen */ - } else { - /* must be a real wp fault */ -#ifdef TRAPDEBUG - printf("Uncorrected kernel write fault, map %x pte %x\n", - map->pmap, *pte); -#endif - result = uvm_fault(map, va, VM_FAULT_INVALID, ftype); - if (result == 0) - return; -#endif - } - } - panictrap(frame->tf_vector, frame); - /* NOTREACHED */ - case T_INSTFLT+T_USER: - /* User mode instruction access fault */ - /* FALLTHROUGH */ - case T_DATAFLT+T_USER: -m88110_user_fault: - if (type == T_INSTFLT+T_USER) { - ftype = VM_PROT_READ; - fault_code = VM_PROT_READ; -#ifdef TRAPDEBUG - printf("User Instruction fault exip %x isr %x ilar %x\n", - frame->tf_exip, frame->tf_isr, frame->tf_ilar); -#endif - } else { - fault_addr = frame->tf_dlar; - if (frame->tf_dsr & CMMU_DSR_RW) { - ftype = VM_PROT_READ; - fault_code = VM_PROT_READ; - } else { - ftype = VM_PROT_READ|VM_PROT_WRITE; - fault_code = VM_PROT_WRITE; - } -#ifdef TRAPDEBUG - printf("User Data access fault exip %x dsr %x dlar %x\n", - frame->tf_exip, frame->tf_dsr, frame->tf_dlar); -#endif - } - - va = trunc_page((vaddr_t)fault_addr); - - vm = p->p_vmspace; - map = &vm->vm_map; - - /* - * Call uvm_fault() to resolve non-bus error faults - * whenever possible. - */ - if (type == T_DATAFLT+T_USER) { - /* data faults */ - if (frame->tf_dsr & CMMU_DSR_BE) { - /* bus error */ - result = EACCES; - } else - if (frame->tf_dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) { - /* segment or page fault */ - result = uvm_fault(map, va, VM_FAULT_INVALID, ftype); - if (result == EACCES) - result = EFAULT; - } else - if (frame->tf_dsr & (CMMU_DSR_CP | CMMU_DSR_WA)) { - /* copyback or write allocate error */ - result = 0; - } else - if (frame->tf_dsr & CMMU_DSR_WE) { - /* write fault */ - /* This could be a write protection fault or an - * exception to set the used and modified bits - * in the pte. Basically, if we got a write - * error, then we already have a pte entry that - * faulted in from a previous seg fault or page - * fault. - * Get the pte and check the status of the - * modified and valid bits to determine if this - * indeed a real write fault. XXX smurph - */ - pte = pmap_pte(vm_map_pmap(map), va); -#ifdef DEBUG - if (pte == PT_ENTRY_NULL) - panic("NULL pte on write fault??"); -#endif - if (!(*pte & PG_M) && !(*pte & PG_RO)) { - /* - * Set modified bit and try the - * write again. - */ -#ifdef TRAPDEBUG - printf("Corrected userland write fault, map %x pte %x\n", - map->pmap, *pte); -#endif - *pte |= PG_M; - /* - * invalidate ATCs to force - * table search - */ - set_dcmd(CMMU_DCMD_INV_UATC); - return; - } else { - /* must be a real wp fault */ -#ifdef TRAPDEBUG - printf("Uncorrected userland write fault, map %x pte %x\n", - map->pmap, *pte); -#endif - result = uvm_fault(map, va, VM_FAULT_INVALID, ftype); - if (result == EACCES) - result = EFAULT; - } - } else { -#ifdef TRAPDEBUG - printf("Unexpected Data access fault dsr %x\n", - frame->tf_dsr); -#endif - panictrap(frame->tf_vector, frame); - } - } else { - /* instruction faults */ - if (frame->tf_isr & - (CMMU_ISR_BE | CMMU_ISR_SP | CMMU_ISR_TBE)) { - /* bus error, supervisor protection */ - result = EACCES; - } else - if (frame->tf_isr & (CMMU_ISR_SI | CMMU_ISR_PI)) { - /* segment or page fault */ - result = uvm_fault(map, va, VM_FAULT_INVALID, ftype); - if (result == EACCES) - result = EFAULT; - } else { -#ifdef TRAPDEBUG - printf("Unexpected Instruction fault isr %x\n", - frame->tf_isr); -#endif - panictrap(frame->tf_vector, frame); - } - } - - if ((caddr_t)va >= vm->vm_maxsaddr) { - if (result == 0) { - nss = btoc(USRSTACK - va);/* XXX check this */ - if (nss > vm->vm_ssize) - vm->vm_ssize = nss; - } - } - - /* - * This could be a fault caused in copyin*() - * while accessing user space. - */ - if (result != 0 && p->p_addr->u_pcb.pcb_onfault != NULL) { - frame->tf_exip = p->p_addr->u_pcb.pcb_onfault; - frame->tf_enip = 0; - frame->tf_dsr = frame->tf_isr = 0; - /* - * Continue as if the fault had been resolved. - */ - result = 0; - } - - if (result != 0) { - sig = result == EACCES ? SIGBUS : SIGSEGV; - fault_type = result == EACCES ? - BUS_ADRERR : SEGV_MAPERR; - } - break; - case T_MISALGNFLT+T_USER: - sig = SIGBUS; - fault_type = BUS_ADRALN; - break; - case T_PRIVINFLT+T_USER: - case T_ILLFLT+T_USER: -#ifndef DDB - case T_KDB_BREAK: - case T_KDB_ENTRY: - case T_KDB_TRACE: -#endif - case T_KDB_BREAK+T_USER: - case T_KDB_ENTRY+T_USER: - case T_KDB_TRACE+T_USER: - sig = SIGILL; - break; - case T_BNDFLT+T_USER: - sig = SIGFPE; - break; - case T_ZERODIV+T_USER: - sig = SIGFPE; - fault_type = FPE_INTDIV; - break; - case T_OVFFLT+T_USER: - sig = SIGFPE; - fault_type = FPE_INTOVF; - break; - case T_FPEPFLT+T_USER: - case T_FPEIFLT+T_USER: - sig = SIGFPE; - break; - case T_SIGSYS+T_USER: - sig = SIGSYS; - break; - case T_SIGTRAP+T_USER: - sig = SIGTRAP; - fault_type = TRAP_TRACE; - break; - case T_STEPBPT+T_USER: - /* - * This trap is used by the kernel to support single-step - * debugging (although any user could generate this trap - * which should probably be handled differently). When a - * process is continued by a debugger with the PT_STEP - * function of ptrace (single step), the kernel inserts - * one or two breakpoints in the user process so that only - * one instruction (or two in the case of a delayed branch) - * is executed. When this breakpoint is hit, we get the - * T_STEPBPT trap. - */ - { - unsigned instr; - struct uio uio; - struct iovec iov; - unsigned pc = PC_REGS(&frame->tf_regs); - - /* read break instruction */ - copyin((caddr_t)pc, &instr, sizeof(unsigned)); -#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 - /* check and see if we got here by accident */ -#ifdef notyet - if (p->p_md.md_ss_addr != pc || instr != SSBREAKPOINT) { - sig = SIGTRAP; - fault_type = TRAP_TRACE; - break; - } -#endif - /* restore original instruction and clear BP */ - /*sig = suiword((caddr_t)pc, p->p_md.md_ss_instr);*/ - instr = p->p_md.md_ss_instr; - if (instr != 0) { - iov.iov_base = (caddr_t)&instr; - iov.iov_len = sizeof(int); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)pc; - uio.uio_resid = sizeof(int); - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_WRITE; - uio.uio_procp = curproc; - } - - p->p_md.md_ss_addr = 0; - sig = SIGTRAP; - fault_type = TRAP_BRKPT; - break; - } - case T_USERBPT+T_USER: - /* - * This trap is meant to be used by debuggers to implement - * breakpoint debugging. When we get this trap, we just - * return a signal which gets caught by the debugger. - */ - sig = SIGTRAP; - fault_type = TRAP_BRKPT; - break; - - case T_ASTFLT+T_USER: - uvmexp.softs++; - want_ast = 0; - if (p->p_flag & P_OWEUPC) { - p->p_flag &= ~P_OWEUPC; - ADDUPROF(p); - } - break; - } - - /* - * If trap from supervisor mode, just return - */ - if (type < T_USER) - return; - - if (sig) { - sv.sival_int = fault_addr; - trapsignal(p, sig, fault_code, fault_type, sv); - /* - * don't want multiple faults - we are going to - * deliver signal. - */ - frame->tf_dsr = frame->tf_isr = 0; - } - - userret(p, frame, sticks); -} -#endif /* MVME197 */ - -__dead void -error_fatal(struct trapframe *frame) -{ -#ifdef DDB - switch (frame->tf_vector) { - case 0: - db_printf("\n[RESET EXCEPTION (Really Bad News[tm]) frame %8p]\n", frame); - db_printf("This is usually caused by a branch to a NULL function pointer.\n"); - db_printf("e.g. jump to address 0. Use the debugger trace command to track it down.\n"); - break; - default: - db_printf("\n[ERROR EXCEPTION (Bad News[tm]) frame %p]\n", frame); - db_printf("This is usually an exception within an exception. The trap\n"); - db_printf("frame shadow registers you are about to see are invalid.\n"); - db_printf("(read totally useless) But R1 to R31 might be interesting.\n"); - break; - } - regdump((struct trapframe*)frame); -#endif /* DDB */ - panic("unrecoverable exception %d", frame->tf_vector); -} - -#ifdef M88100 -void -m88100_syscall(register_t code, struct trapframe *tf) -{ - int i, nsys, nap; - struct sysent *callp; - struct proc *p; - int error; - register_t args[11], rval[2], *ap; - u_quad_t sticks; -#ifdef DIAGNOSTIC - extern struct pcb *curpcb; -#endif - - uvmexp.syscalls++; - - p = curproc; - - callp = p->p_emul->e_sysent; - nsys = p->p_emul->e_nsysent; - -#ifdef DIAGNOSTIC - if (USERMODE(tf->tf_epsr) == 0) - panic("syscall"); - if (curpcb != &p->p_addr->u_pcb) - panic("syscall curpcb/ppcb"); - if (tf != (struct trapframe *)&curpcb->user_state) - panic("syscall trapframe"); -#endif - - sticks = p->p_sticks; - p->p_md.md_tf = tf; - - /* - * For 88k, all the arguments are passed in the registers (r2-r12) - * For syscall (and __syscall), r2 (and r3) has the actual code. - * __syscall takes a quad syscall number, so that other - * arguments are at their natural alignments. - */ - ap = &tf->tf_r[2]; - nap = 11; /* r2-r12 */ - - switch (code) { - case SYS_syscall: - code = *ap++; - nap--; - break; - case SYS___syscall: - if (callp != sysent) - break; - code = ap[_QUAD_LOWWORD]; - ap += 2; - nap -= 2; - break; - } - - /* Callp currently points to syscall, which returns ENOSYS. */ - if (code < 0 || code >= nsys) - callp += p->p_emul->e_nosys; - else { - callp += code; - i = callp->sy_argsize / sizeof(register_t); - if (i > nap) - panic("syscall nargs"); - /* - * just copy them; syscall stub made sure all the - * args are moved from user stack to registers. - */ - bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t)); - } - -#ifdef SYSCALL_DEBUG - scdebug_call(p, code, args); -#endif -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p, code, callp->sy_argsize, args); -#endif - rval[0] = 0; - rval[1] = 0; -#if NSYSTRACE > 0 - if (ISSET(p->p_flag, P_SYSTRACE)) - error = systrace_redirect(code, p, args, rval); - else -#endif - error = (*callp->sy_call)(p, args, rval); - /* - * system call will look like: - * ld r10, r31, 32; r10,r11,r12 might be garbage. - * ld r11, r31, 36 - * ld r12, r31, 40 - * or r13, r0, <code> - * tb0 0, r0, <128> <- sxip - * br err <- snip - * jmp r1 <- sfip - * err: or.u r3, r0, hi16(errno) - * st r2, r3, lo16(errno) - * subu r2, r0, 1 - * jmp r1 - * - * So, when we take syscall trap, sxip/snip/sfip will be as - * shown above. - * Given this, - * 1. If the system call returned 0, need to skip nip. - * nip = fip, fip += 4 - * (doesn't matter what fip + 4 will be but we will never - * execute this since jmp r1 at nip will change the execution flow.) - * 2. If the system call returned an errno > 0, plug the value - * in r2, and leave nip and fip unchanged. This will have us - * executing "br err" on return to user space. - * 3. If the system call code returned ERESTART, - * we need to rexecute the trap instruction. Back up the pipe - * line. - * fip = nip, nip = xip - * 4. If the system call returned EJUSTRETURN, don't need to adjust - * any pointers. - */ - - switch (error) { - case 0: - /* - * If fork succeeded and we are the child, our stack - * has moved and the pointer tf is no longer valid, - * and p is wrong. Compute the new trapframe pointer. - * (The trap frame invariably resides at the - * tippity-top of the u. area.) - */ - p = curproc; - tf = (struct trapframe *)USER_REGS(p); - tf->tf_r[2] = rval[0]; - tf->tf_r[3] = rval[1]; - tf->tf_epsr &= ~PSR_C; - tf->tf_snip = tf->tf_sfip & ~NIP_E; - tf->tf_sfip = tf->tf_snip + 4; - break; - case ERESTART: - /* - * If (error == ERESTART), back up the pipe line. This - * will end up reexecuting the trap. - */ - tf->tf_epsr &= ~PSR_C; - tf->tf_sfip = tf->tf_snip & ~FIP_E; - tf->tf_snip = tf->tf_sxip & ~NIP_E; - break; - case EJUSTRETURN: - /* if (error == EJUSTRETURN), leave the ip's alone */ - tf->tf_epsr &= ~PSR_C; - break; - default: - /* error != ERESTART && error != EJUSTRETURN*/ - if (p->p_emul->e_errno) - error = p->p_emul->e_errno[error]; - tf->tf_r[2] = error; - tf->tf_epsr |= PSR_C; /* fail */ - tf->tf_snip = tf->tf_snip & ~NIP_E; - tf->tf_sfip = tf->tf_sfip & ~FIP_E; - break; - } -#ifdef SYSCALL_DEBUG - scdebug_ret(p, code, error, rval); -#endif - userret(p, tf, sticks); -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p, code, error, rval[0]); -#endif -} -#endif /* M88100 */ - -#ifdef M88110 -/* Instruction pointers operate differently on mc88110 */ -void -m88110_syscall(register_t code, struct trapframe *tf) -{ - int i, nsys, nap; - struct sysent *callp; - struct proc *p; - int error; - register_t args[11], rval[2], *ap; - u_quad_t sticks; -#ifdef DIAGNOSTIC - extern struct pcb *curpcb; -#endif - - uvmexp.syscalls++; - - p = curproc; - - callp = p->p_emul->e_sysent; - nsys = p->p_emul->e_nsysent; - -#ifdef DIAGNOSTIC - if (USERMODE(tf->tf_epsr) == 0) - panic("syscall"); - if (curpcb != &p->p_addr->u_pcb) - panic("syscall curpcb/ppcb"); - if (tf != (struct trapframe *)&curpcb->user_state) - panic("syscall trapframe"); -#endif - - sticks = p->p_sticks; - p->p_md.md_tf = tf; - - /* - * For 88k, all the arguments are passed in the registers (r2-r12) - * For syscall (and __syscall), r2 (and r3) has the actual code. - * __syscall takes a quad syscall number, so that other - * arguments are at their natural alignments. - */ - ap = &tf->tf_r[2]; - nap = 11; /* r2-r12 */ - - switch (code) { - case SYS_syscall: - code = *ap++; - nap--; - break; - case SYS___syscall: - if (callp != sysent) - break; - code = ap[_QUAD_LOWWORD]; - ap += 2; - nap -= 2; - break; - } - - /* Callp currently points to syscall, which returns ENOSYS. */ - if (code < 0 || code >= nsys) - callp += p->p_emul->e_nosys; - else { - callp += code; - i = callp->sy_argsize / sizeof(register_t); - if (i > nap) - panic("syscall nargs"); - /* - * just copy them; syscall stub made sure all the - * args are moved from user stack to registers. - */ - bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t)); - } -#ifdef SYSCALL_DEBUG - scdebug_call(p, code, args); -#endif -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p, code, callp->sy_argsize, args); -#endif - rval[0] = 0; - rval[1] = 0; -#if NSYSTRACE > 0 - if (ISSET(p->p_flag, P_SYSTRACE)) - error = systrace_redirect(code, p, args, rval); - else -#endif - error = (*callp->sy_call)(p, args, rval); - /* - * system call will look like: - * ld r10, r31, 32; r10,r11,r12 might be garbage. - * ld r11, r31, 36 - * ld r12, r31, 40 - * or r13, r0, <code> - * tb0 0, r0, <128> <- exip - * br err <- enip - * jmp r1 - * err: or.u r3, r0, hi16(errno) - * st r2, r3, lo16(errno) - * subu r2, r0, 1 - * jmp r1 - * - * So, when we take syscall trap, exip/enip will be as - * shown above. - * Given this, - * 1. If the system call returned 0, need to jmp r1. - * exip += 8 - * 2. If the system call returned an errno > 0, increment - * exip += 4 and plug the value in r2. This will have us - * executing "br err" on return to user space. - * 3. If the system call code returned ERESTART, - * we need to rexecute the trap instruction. leave exip as is. - * 4. If the system call returned EJUSTRETURN, just return. - * exip += 4 - */ - - switch (error) { - case 0: - /* - * If fork succeeded and we are the child, our stack - * has moved and the pointer tf is no longer valid, - * and p is wrong. Compute the new trapframe pointer. - * (The trap frame invariably resides at the - * tippity-top of the u. area.) - */ - p = curproc; - tf = (struct trapframe *)USER_REGS(p); - tf->tf_r[2] = rval[0]; - tf->tf_r[3] = rval[1]; - tf->tf_epsr &= ~PSR_C; - /* skip two instructions */ - if (tf->tf_exip & 1) - tf->tf_exip = tf->tf_enip + 4; - else - tf->tf_exip += 4 + 4; - tf->tf_enip = 0; - break; - case ERESTART: - /* - * Reexecute the trap. - * exip is already at the trap instruction, so - * there is nothing to do. - */ - tf->tf_epsr &= ~PSR_C; - break; - case EJUSTRETURN: - tf->tf_epsr &= ~PSR_C; - /* skip one instruction */ - if (tf->tf_exip & 1) - tf->tf_exip = tf->tf_enip; - else - tf->tf_exip += 4; - tf->tf_enip = 0; - break; - default: - if (p->p_emul->e_errno) - error = p->p_emul->e_errno[error]; - tf->tf_r[2] = error; - tf->tf_epsr |= PSR_C; /* fail */ - /* skip one instruction */ - if (tf->tf_exip & 1) - tf->tf_exip = tf->tf_enip; - else - tf->tf_exip += 4; - tf->tf_enip = 0; - break; - } - -#ifdef SYSCALL_DEBUG - scdebug_ret(p, code, error, rval); -#endif - userret(p, tf, sticks); -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p, code, error, rval[0]); -#endif -} -#endif /* MVME197 */ - -/* - * Set up return-value registers as fork() libc stub expects, - * and do normal return-to-user-mode stuff. - */ -void -child_return(arg) - void *arg; -{ - struct proc *p = arg; - struct trapframe *tf; - - tf = (struct trapframe *)USER_REGS(p); - tf->tf_r[2] = 0; - tf->tf_r[3] = 0; - tf->tf_epsr &= ~PSR_C; - if (cputyp != CPU_88110) { - tf->tf_snip = tf->tf_sfip & XIP_ADDR; - tf->tf_sfip = tf->tf_snip + 4; - } else { - /* skip two instructions */ - if (tf->tf_exip & 1) - tf->tf_exip = tf->tf_enip + 4; - else - tf->tf_exip += 4 + 4; - tf->tf_enip = 0; - } - - userret(p, tf, p->p_sticks); -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p, SYS_fork, 0, 0); -#endif -} - -#ifdef PTRACE - -/* - * User Single Step Debugging Support - */ - -#include <sys/ptrace.h> - -unsigned ss_get_value(struct proc *, unsigned, int); -int ss_put_value(struct proc *, unsigned, unsigned, int); -unsigned ss_branch_taken(unsigned, unsigned, - unsigned (*func)(unsigned int, struct reg *), struct reg *); -unsigned int ss_getreg_val(unsigned int, struct reg *); -int ss_inst_branch(unsigned); -int ss_inst_delayed(unsigned); -unsigned ss_next_instr_address(struct proc *, unsigned, unsigned); - -unsigned -ss_get_value(struct proc *p, unsigned addr, int size) -{ - struct uio uio; - struct iovec iov; - unsigned value; - - iov.iov_base = (caddr_t)&value; - iov.iov_len = size; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)addr; - uio.uio_resid = size; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_procp = curproc; - procfs_domem(curproc, p, NULL, &uio); - return value; -} - -int -ss_put_value(struct proc *p, unsigned addr, unsigned value, int size) -{ - struct uio uio; - struct iovec iov; - - iov.iov_base = (caddr_t)&value; - iov.iov_len = size; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)addr; - uio.uio_resid = size; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_WRITE; - uio.uio_procp = curproc; - return procfs_domem(curproc, p, NULL, &uio); -} - -/* - * ss_branch_taken(instruction, program counter, func, func_data) - * - * instruction will be a control flow instruction location at address pc. - * Branch taken is supposed to return the address to which the instruction - * would jump if the branch is taken. Func can be used to get the current - * register values when invoked with a register number and func_data as - * arguments. - * - * If the instruction is not a control flow instruction, panic. - */ -unsigned -ss_branch_taken(unsigned inst, unsigned pc, - unsigned (*func)(unsigned int, struct reg *), struct reg *func_data) -{ - /* check if br/bsr */ - if ((inst & 0xf0000000) == 0xc0000000) { - /* signed 26 bit pc relative displacement, shift left two bits */ - inst = (inst & 0x03ffffff) << 2; - /* check if sign extension is needed */ - if (inst & 0x08000000) - inst |= 0xf0000000; - return (pc + inst); - } - - /* check if bb0/bb1/bcnd case */ - switch (inst & 0xf8000000) { - case 0xd0000000: /* bb0 */ - case 0xd8000000: /* bb1 */ - case 0xe8000000: /* bcnd */ - /* signed 16 bit pc relative displacement, shift left two bits */ - inst = (inst & 0x0000ffff) << 2; - /* check if sign extension is needed */ - if (inst & 0x00020000) - inst |= 0xfffc0000; - return (pc + inst); - } - - /* check jmp/jsr case */ - /* check bits 5-31, skipping 10 & 11 */ - if ((inst & 0xfffff3e0) == 0xf400c000) - return (*func)(inst & 0x1f, func_data); /* the register value */ - - /* can't happen */ - return (0); -} - -/* - * ss_getreg_val - handed a register number and an exception frame. - * Returns the value of the register in the specified - * frame. Only makes sense for general registers. - */ -unsigned int -ss_getreg_val(unsigned int regno, struct reg *regs) -{ - return (regno == 0 ? 0 : regs->r[regno]); -} - -int -ss_inst_branch(unsigned ins) -{ - /* check high five bits */ - - switch (ins >> (32 - 5)) { - case 0x18: /* br */ - case 0x1a: /* bb0 */ - case 0x1b: /* bb1 */ - case 0x1d: /* bcnd */ - return TRUE; - break; - case 0x1e: /* could be jmp */ - if ((ins & 0xfffffbe0) == 0xf400c000) - return TRUE; - } - - return FALSE; -} - -/* ss_inst_delayed - this instruction is followed by a delay slot. Could be - br.n, bsr.n bb0.n, bb1.n, bcnd.n or jmp.n or jsr.n */ - -int -ss_inst_delayed(unsigned ins) -{ - /* check the br, bsr, bb0, bb1, bcnd cases */ - switch ((ins & 0xfc000000) >> (32 - 6)) { - case 0x31: /* br */ - case 0x33: /* bsr */ - case 0x35: /* bb0 */ - case 0x37: /* bb1 */ - case 0x3b: /* bcnd */ - return TRUE; - } - - /* check the jmp, jsr cases */ - /* mask out bits 0-4, bit 11 */ - return ((ins & 0xfffff7e0) == 0xf400c400) ? TRUE : FALSE; -} - -unsigned -ss_next_instr_address(struct proc *p, unsigned pc, unsigned delay_slot) -{ - if (delay_slot == 0) - return (pc + 4); - else { - if (ss_inst_delayed(ss_get_value(p, pc, sizeof(int)))) - return (pc + 4); - else - return pc; - } -} - -int -cpu_singlestep(p) - struct proc *p; -{ - struct reg *sstf = USER_REGS(p); - unsigned pc, brpc; - int bpinstr = SSBREAKPOINT; - unsigned curinstr; - - pc = PC_REGS(sstf); - /* - * User was stopped at pc, e.g. the instruction - * at pc was not executed. - * Fetch what's at the current location. - */ - curinstr = ss_get_value(p, pc, sizeof(int)); - - /* compute next address after current location */ - if (curinstr != 0) { - if (ss_inst_branch(curinstr) || - inst_call(curinstr) || inst_return(curinstr)) { - brpc = ss_branch_taken(curinstr, pc, ss_getreg_val, sstf); - if (brpc != pc) { /* self-branches are hopeless */ - p->p_md.md_ss_taken_addr = brpc; - p->p_md.md_ss_taken_instr = - ss_get_value(p, brpc, sizeof(int)); - /* Store breakpoint instruction at the - "next" location now. */ - if (ss_put_value(p, brpc, bpinstr, - sizeof(int)) != 0) - return (EFAULT); - } - } - pc = ss_next_instr_address(p, pc, 0); - } else { - pc = PC_REGS(sstf) + 4; - } - - if (p->p_md.md_ss_addr != NULL) { - return (EFAULT); - } - - p->p_md.md_ss_addr = pc; - - /* Fetch what's at the "next" location. */ - p->p_md.md_ss_instr = ss_get_value(p, pc, sizeof(int)); - - /* Store breakpoint instruction at the "next" location now. */ - if (ss_put_value(p, pc, bpinstr, sizeof(int)) != 0) - return (EFAULT); - - return (0); -} - -#endif /* PTRACE */ - -#ifdef DIAGNOSTIC -void -splassert_check(int wantipl, const char *func) -{ - int oldipl; - - /* - * This will raise the spl if too low, - * in a feeble attempt to reduce further damage. - */ - oldipl = raiseipl(wantipl); - - if (oldipl < wantipl) { - splassert_fail(wantipl, oldipl, func); - } -} -#endif |