summaryrefslogtreecommitdiff
path: root/sys/arch/luna88k
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-04-29 14:33:28 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-04-29 14:33:28 +0000
commit1fa78801a9defc09408f6ce5b7d52e7779fa0db2 (patch)
tree4c27b16dbb451c90c2f0389c2f192283d76e8b77 /sys/arch/luna88k
parenta500642091db73be0684e3a3946c4c97396c840e (diff)
Continue factorizing m88k common code, this time files in <arch>/<arch>
which were copied verbatim from mvme88k to luna88k. This requires backing out syntactic sugar in mvme88k kernel configuration files which would deduct the required processor types from the board models, as the common code only depends upon the M88100 and M88110 defines.
Diffstat (limited to 'sys/arch/luna88k')
-rw-r--r--sys/arch/luna88k/conf/GENERIC5
-rw-r--r--sys/arch/luna88k/conf/Makefile.luna88k11
-rw-r--r--sys/arch/luna88k/conf/RAMDISK5
-rw-r--r--sys/arch/luna88k/conf/files.luna88k9
-rw-r--r--sys/arch/luna88k/luna88k/cmmu.c78
-rw-r--r--sys/arch/luna88k/luna88k/genassym.cf144
-rw-r--r--sys/arch/luna88k/luna88k/locore_asm_routines.S1621
-rw-r--r--sys/arch/luna88k/luna88k/m88100_fp.S2516
-rw-r--r--sys/arch/luna88k/luna88k/process.S332
-rw-r--r--sys/arch/luna88k/luna88k/process_machdep.c149
-rw-r--r--sys/arch/luna88k/luna88k/trap.c1797
-rw-r--r--sys/arch/luna88k/luna88k/vectors_88100.S89
12 files changed, 13 insertions, 6743 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/trap.c b/sys/arch/luna88k/luna88k/trap.c
deleted file mode 100644
index d7bee6ad47b..00000000000
--- a/sys/arch/luna88k/luna88k/trap.c
+++ /dev/null
@@ -1,1797 +0,0 @@
-/* $OpenBSD: trap.c,v 1.1 2004/04/21 15:24:14 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) 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
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
-