Cleanup after import. This also seems to bring up the current version.
authorrahnds <rahnds@openbsd.org>
Mon, 3 Mar 1997 20:20:27 +0000 (20:20 +0000)
committerrahnds <rahnds@openbsd.org>
Mon, 3 Mar 1997 20:20:27 +0000 (20:20 +0000)
125 files changed:
sys/arch/mvme88k/conf/GENERIC [new file with mode: 0644]
sys/arch/mvme88k/conf/MYBOX [new file with mode: 0644]
sys/arch/mvme88k/ddb/db_disasm.c [new file with mode: 0644]
sys/arch/mvme88k/ddb/db_interface.c [new file with mode: 0644]
sys/arch/mvme88k/ddb/db_sstep.c [new file with mode: 0644]
sys/arch/mvme88k/ddb/db_trace.c [new file with mode: 0644]
sys/arch/mvme88k/dev/bugtty.c [new file with mode: 0644]
sys/arch/mvme88k/dev/clock.c [new file with mode: 0644]
sys/arch/mvme88k/dev/pcc2.c [new file with mode: 0644]
sys/arch/mvme88k/dev/pcctwo.c [new file with mode: 0644]
sys/arch/mvme88k/include/ansi.h [new file with mode: 0644]
sys/arch/mvme88k/include/asm.h [new file with mode: 0644]
sys/arch/mvme88k/include/asm_macro.h [new file with mode: 0644]
sys/arch/mvme88k/include/assert.h [new file with mode: 0644]
sys/arch/mvme88k/include/assym.s [new file with mode: 0644]
sys/arch/mvme88k/include/autoconf.h [new file with mode: 0644]
sys/arch/mvme88k/include/board.h [new file with mode: 0644]
sys/arch/mvme88k/include/bug.h [new file with mode: 0644]
sys/arch/mvme88k/include/bugio.h [new file with mode: 0644]
sys/arch/mvme88k/include/cdefs.h [new file with mode: 0644]
sys/arch/mvme88k/include/cpu.h [new file with mode: 0644]
sys/arch/mvme88k/include/cpus.h [new file with mode: 0644]
sys/arch/mvme88k/include/db_machdep.h [new file with mode: 0644]
sys/arch/mvme88k/include/disklabel.h [new file with mode: 0644]
sys/arch/mvme88k/include/endian.h [new file with mode: 0644]
sys/arch/mvme88k/include/exception_vectors.h [new file with mode: 0644]
sys/arch/mvme88k/include/exec.h [new file with mode: 0644]
sys/arch/mvme88k/include/limits.h [new file with mode: 0644]
sys/arch/mvme88k/include/locore.h [new file with mode: 0644]
sys/arch/mvme88k/include/m88100.h [new file with mode: 0644]
sys/arch/mvme88k/include/m882xx.h [new file with mode: 0644]
sys/arch/mvme88k/include/mmu.h [new file with mode: 0644]
sys/arch/mvme88k/include/param.h [new file with mode: 0644]
sys/arch/mvme88k/include/pcb.h [new file with mode: 0644]
sys/arch/mvme88k/include/pcctworeg.h [new file with mode: 0644]
sys/arch/mvme88k/include/pmap.h [new file with mode: 0644]
sys/arch/mvme88k/include/pmap_table.h [new file with mode: 0644]
sys/arch/mvme88k/include/proc.h [new file with mode: 0644]
sys/arch/mvme88k/include/profile.h [new file with mode: 0644]
sys/arch/mvme88k/include/psl.h [new file with mode: 0644]
sys/arch/mvme88k/include/ptrace.h [new file with mode: 0644]
sys/arch/mvme88k/include/reg.h [new file with mode: 0644]
sys/arch/mvme88k/include/setjmp.h [new file with mode: 0644]
sys/arch/mvme88k/include/signal.h [new file with mode: 0644]
sys/arch/mvme88k/include/stdarg.h [new file with mode: 0644]
sys/arch/mvme88k/include/trap.h [new file with mode: 0644]
sys/arch/mvme88k/include/types.h [new file with mode: 0644]
sys/arch/mvme88k/include/va-m88k.h [new file with mode: 0644]
sys/arch/mvme88k/include/varargs.h [new file with mode: 0644]
sys/arch/mvme88k/include/vid.h [new file with mode: 0644]
sys/arch/mvme88k/include/vmparam.h [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/TODO [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/autoconf.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/cmmu.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/conf.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/eh.S [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/genassym.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/locore.S [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/locore_asm_routines.S [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/locore_c_routines.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/m88100_fp.S [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/machdep.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/pmap.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/process.S [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/process_machdep.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/swapgeneric.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/syscall.stub [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/timerreg.h [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/trap.c [new file with mode: 0644]
sys/arch/mvme88k/mvme88k/vm_machdep.c [new file with mode: 0644]
sys/arch/mvme88k/stand/Makefile [new file with mode: 0644]
sys/arch/mvme88k/stand/boot/Makefile [new file with mode: 0644]
sys/arch/mvme88k/stand/boot/main.c [new file with mode: 0644]
sys/arch/mvme88k/stand/boot/obj.m88k/boot [deleted file]
sys/arch/mvme88k/stand/boot/wrtvid.c [new file with mode: 0644]
sys/arch/mvme88k/stand/bootsd/bootsd [deleted file]
sys/arch/mvme88k/stand/bootsd/bootsd.bin [deleted file]
sys/arch/mvme88k/stand/bootsd/bootsd.bug [deleted file]
sys/arch/mvme88k/stand/bootsd/sdboot [deleted file]
sys/arch/mvme88k/stand/bootst/bak.c [deleted file]
sys/arch/mvme88k/stand/bootst/bootst [deleted file]
sys/arch/mvme88k/stand/bootst/bootst.bug [deleted file]
sys/arch/mvme88k/stand/bootst/stboot [deleted file]
sys/arch/mvme88k/stand/bugcrt/Makefile [new file with mode: 0644]
sys/arch/mvme88k/stand/bugexec/Makefile [new file with mode: 0644]
sys/arch/mvme88k/stand/bugexec/hello.c [new file with mode: 0644]
sys/arch/mvme88k/stand/bugexec/wrtos.c [new file with mode: 0644]
sys/arch/mvme88k/stand/include/bug.h [new file with mode: 0644]
sys/arch/mvme88k/stand/include/bugio.h [new file with mode: 0644]
sys/arch/mvme88k/stand/kerncrt/Makefile [new file with mode: 0644]
sys/arch/mvme88k/stand/kerncrt/kerncrt.c [new file with mode: 0644]
sys/arch/mvme88k/stand/libbug/Makefile [new file with mode: 0644]
sys/arch/mvme88k/stand/libbug/bugio.c [new file with mode: 0644]
sys/arch/mvme88k/stand/libbug/log1 [deleted file]
sys/arch/mvme88k/stand/libbug/log2 [deleted file]
sys/arch/mvme88k/stand/libsa/log1 [deleted file]
sys/arch/mvme88k/stand/libsa/log2 [deleted file]
sys/arch/mvme88k/stand/netboot/netboot [deleted file]
sys/arch/mvme88k/stand/netboot/netboot.bin [deleted file]
sys/arch/mvme88k/stand/obj.m88k/boot [deleted file]
sys/arch/mvme88k/stand/obj.m88k/boot.1 [deleted file]
sys/arch/mvme88k/stand/obj.m88k/boot.2 [deleted file]
sys/arch/mvme88k/stand/openbsd/bootsd/bootsd [deleted file]
sys/arch/mvme88k/stand/openbsd/bootsd/bootsd.bin [deleted file]
sys/arch/mvme88k/stand/openbsd/bootsd/bootsd.bug [deleted file]
sys/arch/mvme88k/stand/openbsd/bootsd/sdboot [deleted file]
sys/arch/mvme88k/stand/openbsd/bootst/bootst [deleted file]
sys/arch/mvme88k/stand/openbsd/bootst/bootst.bug [deleted file]
sys/arch/mvme88k/stand/openbsd/bootst/stboot [deleted file]
sys/arch/mvme88k/stand/openbsd/libbug/log1 [deleted file]
sys/arch/mvme88k/stand/openbsd/libbug/log2 [deleted file]
sys/arch/mvme88k/stand/openbsd/libsa/log1 [deleted file]
sys/arch/mvme88k/stand/openbsd/libsa/log2 [deleted file]
sys/arch/mvme88k/stand/openbsd/netboot/netboot [deleted file]
sys/arch/mvme88k/stand/openbsd/netboot/netboot.bin [deleted file]
sys/arch/mvme88k/stand/openbsd/sboot/rboot [deleted file]
sys/arch/mvme88k/stand/openbsd/sboot/rboot.tmp [deleted file]
sys/arch/mvme88k/stand/openbsd/sboot/sboot [deleted file]
sys/arch/mvme88k/stand/openbsd/sboot/sboot.tmp [deleted file]
sys/arch/mvme88k/stand/openbsd/sboot/srec [deleted file]
sys/arch/mvme88k/stand/openbsd/wrtvid/wrtvid [deleted file]
sys/arch/mvme88k/stand/prtvid/chklabel [deleted file]
sys/arch/mvme88k/stand/prtvid/prtvid [deleted file]
sys/arch/mvme88k/stand/wrtvid/Makefile,v [deleted file]
sys/arch/mvme88k/stand/wrtvid/wrtvid [deleted file]

diff --git a/sys/arch/mvme88k/conf/GENERIC b/sys/arch/mvme88k/conf/GENERIC
new file mode 100644 (file)
index 0000000..959af67
--- /dev/null
@@ -0,0 +1,100 @@
+#
+# This configuration file contains all possible options
+#
+
+machine m88k
+
+options                TIMEZONE=300, DST=1
+
+#
+# processors this kernel should support
+#
+options                "M88000"        # support for 88K
+options                MVME187         # support for 187
+
+options                SWAPPAGER       # Pager for processes (Required)
+options                VNODEPAGER      # Pager for vnodes (Required)
+options                DEVPAGER        # Pager for devices (Required)
+
+#
+# Networking options
+#
+
+#
+# File system related options
+#
+#options               QUOTA           # Disk quotas for local disks
+#options               NFSSERVER       # Network File System server side code
+#options               NFSCLIENT       # Network File System client side code
+
+#
+# File systems
+#
+options                FFS             # Berkeley fast file system
+options                MFS             # Memory based filesystem
+options                FIFO            # FIFO operations on vnodes (Recommended)
+
+#
+# Compatability options for various existing systems
+#
+#options               "COMPAT_43"     # 4.3 BSD compatible system calls
+#options               "TCP_COMPAT_42" # Use 4.2 BSD style TCP
+#options               "COMPAT_NOMID"  # allow nonvalid machine id executables
+
+#
+# Support for System V IPC facilities.
+#
+
+#
+# Support for various kernel options
+#
+options                GENERIC         # Mini-root boot support
+options                DIAGNOSTIC      # Add additional error checking code
+options                "NKMEMCLUSTERS=256"     # Size of kernel malloc area
+
+#
+# Misc. debuging options
+#
+options                PANICWAIT       # Require keystroke to dump/reboot
+options                DEBUG           # Add debugging statements
+options                DDB             # Kernel debugger
+options                SYSCALL_DEBUG   # debug all syscalls.
+
+#
+# devices
+#
+mainbus0 at root
+# mainbus devices
+#sram0 at mainbus0 addr 0xffe00000
+vme0   at mainbus0 addr 0xfff40000
+pcctwo0 at mainbus0 addr 0xfff42000
+# pcctwo devices
+clock0 at pcctwo0 addr 0xfff42000 ipl 5
+nvram0 at pcctwo0 addr 0xfffc0000 size 0x10000
+#ie0   at pcctwo0 addr 0xfff46000 ipl 1 size
+#siop0 at pcctwo0 addr 0xfff47000 ipl 2 #size
+cl0    at pcctwo0 addr 0xfff45000 ipl 3 size 0x512
+#lptwo0        at pcctwo0 addr 0xfff45000 ipl 1 size
+#mcecc0        at pcctwo0 addr 0xfff43000
+#mcecc1        at pcctwo0 addr 0xfff43100
+#memc0 at pcctwo0 addr 0xfff43000
+#memc1 at pcctwo0 addr 0xfff43100
+
+#bugtty0 at mainbus0
+
+#vme0 devices
+vmes0  at vme0
+vmel0  at vme0
+
+#scsibus* at siop?
+#
+#sd*   at scsibus? target ? lun ?
+#st*   at scsibus? target ? lun ?
+#cd*   at scsibus? target ? lun ?
+
+#pseudo-device sl                      # slip
+#pseudo-device ppp                     # ppp
+pseudo-device  pty 16                  # pseudo terminals
+pseudo-device  loop                    # network loopback
+
+config netbsd swap on generic
diff --git a/sys/arch/mvme88k/conf/MYBOX b/sys/arch/mvme88k/conf/MYBOX
new file mode 100644 (file)
index 0000000..1876913
--- /dev/null
@@ -0,0 +1,73 @@
+#      $Id: MYBOX,v 1.4 1997/03/03 20:20:30 rahnds Exp $
+
+include "std.mvme88k"
+
+maxusers       8
+options                TIMEZONE=300, DST=1
+options                BYTE_MSF
+options                SWAPPAGER, VNODEPAGER, DEVPAGER
+#options               INET
+options                FFS, MFS, FDESC
+#options               "COMPAT_42", "COMPAT_43"
+options                GENERIC, KTRACE, DIAGNOSTIC, "NKMEMCLUSTERS=256"
+#options               PANICWAIT, DEBUG, DDB
+options                PANICWAIT, DEBUG, DDB
+
+#options       "CD9660", PORTAL, MSDOSFS, PROCFS, NULLFS, FIFO, KERNFS
+#options       NFSSERVER, NFSCLIENT
+#options       SYSVSHM, SYSVMSG, SYSVSEM       
+#options       SYSCALL_DEBUG, SCSIDEBUG, KGDB
+
+mainbus0       at root
+
+pcctwo0 at mainbus0 addr 0xfff00000
+clock0 at pcctwo0 ipl 5
+#nvram0        at pcctwo0 offset 0xc0000
+#ie0   at pcctwo0 offset 0x46000 ipl 1
+#siop0 at pcctwo0 offset 0x47000 ipl 2
+#cl0   at pcctwo0 offset 0x45000 ipl 4
+vme0   at pcctwo0 offset 0x40000
+#lptwo0        at pcctwo0 ipl 1
+#mcecc0        at pcctwo0 offset 0x43000
+#mcecc1        at pcctwo0 offset 0x43100
+#memc0 at pcctwo0 offset 0x43000
+#memc1 at pcctwo0 offset 0x43100
+#sram0 at mainbus0 addr 0xffe00000
+
+bugtty0                at mainbus0             # bug tty
+
+# scsi stuff, all possible
+#m187scsi0     at mainbus0
+#bugscsi0      at mainbus0
+#bugscsi0      at pcc0
+
+#scsibus0      at m187scsi0
+#scsibus0      at bugscsi0
+#scsibus0      at scsi0
+#
+# compat.
+#
+#sd0   at scsibus? target 0 lun 0
+#sd1   at scsibus? target 1 lun 0
+#sd2   at scsibus? target 2 lun 0
+#sd3   at scsibus? target 3 lun 0
+#sd4   at scsibus? target 4 lun 0
+#sd5   at scsibus? target 5 lun 0
+#sd6   at scsibus? target 6 lun 0
+
+#
+# This is nicer however many amiga setups expect sd units to refer to
+# scsi target numbers.  If this is not the case, you can remove the 
+# specific sdx lines above and each hard drive from low target to high
+# will configure to the next available sd unit number
+
+#sd*   at scsibus? target ? lun ?      # scsi disks
+#st*   at scsibus? target ? lun ?      # scsi tapes
+#cd*   at scsibus? target ? lun ?      # scsi cd's
+
+#pseudo-device sl                      # slip
+#pseudo-device ppp                     # ppp
+#pseudo-device pty 16                  # pseudo terminals
+#pseudo-device loop                    # network loopback
+#
+config netbsd swap on generic
diff --git a/sys/arch/mvme88k/ddb/db_disasm.c b/sys/arch/mvme88k/ddb/db_disasm.c
new file mode 100644 (file)
index 0000000..81cf53a
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * 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.
+ */
+
+/*
+ * m88k disassembler for use in ddb
+ */
+
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>                /* DB_STGY_PROC, db_printsym() */
+#include <ddb/db_access.h>     /* db_get_value() */
+#include <ddb/db_output.h>     /* db_printf() */
+
+static char *instwidth[4] = {
+       ".d", "  ", ".h", ".b"
+};
+
+static char *condname[6] = {
+       "gt0 ", "eq0 ", "ge0 ", "lt0 ", "ne0 ", "le0 "
+};  
+
+static char *ctrlreg[64] = {
+       "cr0(PID)   ",
+       "cr1(PSR)   ",
+       "cr2(EPSR)  ",
+       "cr3(SSBR)  ",
+       "cr4(SXIP)  ",
+       "cr5(SNIP)  ",
+       "cr6(SFIP)  ",
+       "cr7(VBR)   ",
+       "cr8(DMT0)  ",
+       "cr9(DMD0)  ",
+       "cr10(DMA0) ",
+       "cr11(DMT1) ",
+       "cr12(DMD1) ",
+       "cr13(DMA1) ",
+       "cr14(DMT2) ",
+       "cr15(DMD2) ",
+       "cr16(DMA2) ",
+       "cr17(SR0)  ",
+       "cr18(SR1)  ",
+       "cr19(SR2)  ",
+       "cr20(SR3)  ",
+       "fcr0(FPECR)",
+       "fcr1(FPHS1)",
+       "fcr2(FPLS1)",
+       "fcr3(FPHS2)",
+       "fcr4(FPLS2)",
+       "fcr5(FPPT) ",
+       "fcr6(FPRH) ",
+       "fcr7(FPRL) ",
+       "fcr8(FPIT) ",
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       "fcr62(FPSR)",
+       "fcr63(FPCR)"
+};
+
+#define printval(x)  if (x<0) db_printf ("-0x%X", -x); else db_printf("0x%X",x)
+
+/* Handlers immediate integer arithmetic instructions */      
+static void
+oimmed(long inst, char  *opcode, long iadr)
+{
+  register int Linst = inst & 0177777;
+  register int Hinst = inst >> 16;
+  register int H6inst = Hinst >> 10;
+  register int rs1 = Hinst & 037;
+  register int rd = ( Hinst >> 5 ) & 037;
+
+  if (( H6inst > 017 ) && ( H6inst < 030 ) && ( H6inst & 01) == 1 ) 
+    db_printf("\t%s.u",opcode);
+  else {
+    db_printf("\t%s",opcode);
+    db_printf("  ");
+  }
+  db_printf("\t\tr%-3d,r%-3d,", rd, rs1);
+  printval(Linst);
+}
+
+
+/* Handles instructions dealing with control registers */
+static void
+ctrlregs(long inst, char *opcode, long iadr)
+{
+  register int L6inst = (inst >> 11) & 037;
+  register int creg = (inst >> 5) & 077;
+  register int rd = (inst >> 21) & 037;
+  register int rs1 = (inst >> 16) & 037;
+  
+  db_printf("\t%s",opcode);
+  
+  if ( L6inst == 010 || L6inst == 011 )
+    db_printf("\t\tr%-3d,%s", rd, ctrlreg[creg]);
+  else if ( L6inst == 020 || L6inst == 021 )
+    db_printf("\t\tr%-3d,%s", rs1, ctrlreg[creg]);
+  else
+    db_printf("\t\tr%-3d,r%-3d,%s", rd, rs1, ctrlreg[creg]);
+}
+
+
+static void
+printsod(int t)
+{
+  if ( t == 0 ) 
+    db_printf("s");
+  else
+    db_printf("d");
+}
+
+/* Handles floating point instructions */
+static void
+sindou(int inst, char *opcode, long iadr)
+{
+  register int rs2 = inst & 037;
+  register int td = ( inst >> 5 ) & 03;
+  register int t2 = ( inst >> 7 ) & 03;
+  register int t1 = ( inst >> 9 ) & 03;
+  register int rs1 = ( inst >> 16 ) & 037;
+  register int rd = ( inst >> 21 ) & 037;
+  register int checkbits  = ( inst >> 11 ) & 037;
+  
+  db_printf("\t%s.",opcode);
+  printsod(td);
+  if (( checkbits > 010 && checkbits < 014 ) || ( checkbits == 04 )) {
+    printsod(t2);
+    db_printf(" ");
+    if ( checkbits == 012 || checkbits == 013 )
+      db_printf("\t\tr%-3d,r%-3d", rd, rs2);
+    else
+      db_printf("\t\tr%-3d,r%-3d", rd, rs2);
+  }
+  else{
+    printsod(t1);printsod(t2);
+    db_printf("\t\tr%-3d,r%-3d,r%-3d", rd, rs1, rs2);
+  }
+}
+
+
+static void
+jump(long inst, char *opcode, long iadr)
+{
+  register int rs2 = inst & 037;
+  register int Nbit = ( inst >> 10 ) & 01;
+  
+  db_printf("\t%s",opcode);
+  if ( Nbit == 1 )
+    db_printf(".n");
+  else
+    db_printf("  ");
+  db_printf("\t\tr%-3d",rs2);
+}
+
+
+/* Handles ff1, ff0, tbnd and rte instructions */ 
+static void
+instset(long inst, char *opcode, long iadr)
+{
+  register int rs2 = inst & 037;
+  register int rs1 = ( inst >> 16 ) & 037;
+  register int rd = ( inst >> 21 ) & 037;
+  register int checkbits = ( inst >> 10 ) & 077;
+  register int H6inst = ( inst >> 26 ) & 077;
+  
+  db_printf("\t%s",opcode);
+  if ( H6inst == 076 ) {
+    db_printf("\t\tr%-3d,",rs1);
+    printval(inst & 0177777);
+  }
+  else if (( checkbits == 072 ) || ( checkbits == 073 ))
+    db_printf("\t\tr%-3d,r%-3d", rd, rs2);
+  else if ( checkbits == 076 )
+    db_printf("\t\tr%-3d,r%-3d",rs1,rs2);
+}
+
+static void
+symofset(int  disp, int  bit, int iadr)
+{
+  long addr;
+
+  if ( disp & (1 << (bit-1)) ) {
+    /* negative value */
+    addr = iadr + ((disp << 2) | (~0 << bit));
+  }
+  else {
+    addr = iadr + (disp << 2);
+  }
+  db_printsym(addr,DB_STGY_PROC);
+  return;
+}
+
+static void
+obranch(int inst, char *opcode, long iadr)
+{
+  int cond = ( inst >> 26 ) & 01;
+  int disp = inst &0377777777;
+  
+  if ( cond == 0 ) {
+    db_printf("\t%s\t\t",opcode);
+    symofset(disp, 26, iadr);
+  }
+  else {
+    db_printf("\t%s.n\t\t",opcode);
+    symofset(disp, 26, iadr);
+  }
+}
+
+
+/* Handles branch on conditions instructions */
+static void
+brcond(int inst, char *opcode, long iadr)
+{
+  int cond = ( inst >> 26 ) & 1;
+  int match = ( inst >> 21 ) & 037;
+  int rs = ( inst >> 16 ) & 037;
+  int disp = ( inst & 0177777 );
+  
+  if ( cond == 0 )
+    db_printf("\t%s\t\t", opcode); 
+  else
+    db_printf("\t%s.n\t\t", opcode);
+  if ( ( ( inst >> 27 ) & 03 ) == 1 )
+    switch (match) {
+    case 1 : db_printf("%s,", condname[0]); break;
+    case 2 : db_printf("%s,", condname[1]); break;
+    case 3 : db_printf("%s,", condname[2]); break;
+    case 12: db_printf("%s,", condname[3]); break;
+    case 13: db_printf("%s,", condname[4]); break;
+    case 14: db_printf("%s,", condname[5]); break;
+    default: printval(match); 
+      db_printf(",");
+    }
+  else {
+    printval(match);
+    db_printf(",");
+  }
+
+  db_printf("r%-3d,", rs);
+  symofset(disp,16, iadr);
+}
+
+
+static void
+otrap(int inst, char *opcode, long iadr)
+{
+  int vecno = inst & 0777;
+  int match = ( inst >> 21 ) & 037;
+  int rs = ( inst >> 16 ) & 037;
+  
+  db_printf("\t%s\t",opcode);
+  if ( ( ( inst >> 12 ) & 017 ) == 0xe )
+    switch (match) {
+    case 1 : db_printf("%s,", condname[0]);break;
+    case 2 : db_printf("%s,", condname[1]);break;
+    case 3 : db_printf("%s,", condname[2]);break;
+    case 12: db_printf("%s,", condname[3]);break;
+    case 13: db_printf("%s,", condname[4]);break;
+    case 14: db_printf("%s,", condname[5]);break;
+    default: printval(match);
+      db_printf(",");
+    }
+  else {
+    printval(match);
+    db_printf(",");
+  }
+  db_printf("\tr%-3d,", rs);
+  printval(vecno);
+}
+
+
+/* Handles 10 bit immediate bit field operations */
+static void
+obit(int inst, char *opcode, long iadr)
+{
+  int rs = ( inst >> 16 ) & 037;
+  int rd = ( inst >> 21 ) & 037;
+  int width = ( inst >> 5 ) & 037;
+  int offset = ( inst & 037 );  
+  
+  db_printf("\t%s\t\tr%-3d,r%-3d,", opcode, rd, rs); 
+  if ( ( ( inst >> 10 ) & 077 ) == 052 ) {
+    db_printf("<"); 
+    printval(offset); 
+    db_printf(">"); 
+  }
+  else
+    {
+      printval(width);
+      db_printf("<");
+      printval(offset);
+      db_printf(">");
+    }
+}
+
+
+/* Handles triadic mode bit field instructions */
+static void
+bitman(int inst, char *opcode, long iadr)
+{
+  
+  int rs1 = ( inst >> 16 ) & 037;
+  int rd  = ( inst >> 21 ) & 037;
+  int rs2 = inst & 037;
+  
+  db_printf("\t%s\t\tr%-3d,r%-3d,r%-3d", opcode, rd, rs1, rs2);
+}
+
+
+/* Handles immediate load/store/exchange instructions */
+static void
+immem(int inst, char *opcode, long iadr)
+{
+  register int immed  = inst & 0xFFFF;
+  register int rd     = (inst >> 21) & 037;
+  register int rs     = (inst >> 16) & 037;
+  register int st_lda = (inst >> 28) & 03;
+  register int aryno  = (inst >> 26) & 03;
+  char c = ' ';
+  
+  if (!st_lda) {
+    if ((aryno == 0) || (aryno == 01))
+      opcode = "xmem";
+    else
+      opcode = "ld";
+    if (aryno == 0)
+      aryno = 03;
+    if (!(aryno == 01))
+      c = 'u';
+  }
+  else
+    if (st_lda == 01)
+      opcode = "ld";
+  
+  db_printf("\t%s%s%c\t\tr%-3d,r%-3d,", opcode, instwidth[aryno], 
+           c, rd, rs);
+  printval(immed);
+}
+
+
+/* Handles triadic mode load/store/exchange instructions */
+static void
+nimmem(int inst, char *opcode, long iadr)
+{
+  register int scaled  = (inst >> 9) & 01;
+  register int rd      = (inst >> 21) & 037;
+  register int rs1     = (inst >> 16) & 037;
+  register int rs2     = inst & 037;
+  register int st_lda  = (inst >> 12) & 03;
+  register int aryno   = (inst >> 10) & 03;
+  register int user_bit = 0;
+  int signed_fg  = 1;
+  char *user           = "    ";
+  char c = ' ';
+  
+  if (!st_lda) {
+    if ((aryno == 0) || (aryno == 01))
+      opcode = "xmem";
+    else
+      opcode = "ld";
+    if (aryno == 0)
+      aryno = 03;
+    if (!(aryno == 01))        {
+      c = 'u';
+      signed_fg = 0;
+    }
+  }
+  else
+    if (st_lda == 01)
+      opcode = "ld";
+  
+  if (!(st_lda == 03)) {
+    user_bit = (inst >> 8) & 01;
+    if (user_bit)
+      user = ".usr";
+  }
+  
+  if (user_bit && signed_fg && (aryno == 01)) {
+    if (st_lda)
+      db_printf("\t%s%s\tr%-3d,r%-3d", opcode,
+               user, rd, rs1);
+    else
+      db_printf("\t%s%s\tr%-3d,r%-3d", opcode,
+               user, rd, rs1);
+  }    
+  else 
+    if (user_bit && signed_fg)
+      db_printf("\t%s%s%s\tr%-3d,r%-3d", opcode, 
+               instwidth[aryno], user, rd, rs1);
+    else
+      db_printf("\t%s%s%c%s\tr%-3d,r%-3d", opcode, 
+               instwidth[aryno], c, user, rd, rs1);
+  
+  if (scaled)
+    db_printf("[r%-3d]", rs2);
+  else
+    db_printf(",r%-3d", rs2);
+}
+
+
+/* Handles triadic mode logical instructions */
+static void
+lognim(int inst, char *opcode, long iadr)
+{
+  register int rd   = (inst >> 21) & 037;
+  register int rs1  = (inst >> 16) & 037;
+  register int rs2  = inst & 037;
+  register int complemt = (inst >> 10) & 01;
+  char *c = "  ";
+  
+  if (complemt)
+    c = ".c";
+  
+  db_printf("\t%s%s\t\tr%-3d,r%-3d,r%-3d", opcode, c, rd, rs1, rs2);
+}
+
+
+/* Handles triadic mode arithmetic instructions */
+static void
+onimmed(int inst, char *opcode, long iadr)
+{
+  register int rd   = (inst >> 21) & 037;
+  register int rs1  = (inst >> 16) & 037;
+  register int rs2  = inst & 037;
+  register int carry = (inst >> 8) & 03;
+  register int nochar = (inst >> 10) & 07;
+  register int nodecode = (inst >> 11) & 01;
+  char *tab, *c ;
+  
+  if (nochar > 02)
+    tab = "\t\t";
+  else
+    tab = "\t";
+  
+  if (!nodecode) {
+    if (carry == 01)
+      c = ".co ";
+    else
+      if (carry == 02)
+       c = ".ci ";
+      else
+       if (carry == 03)
+         c = ".cio";
+       else
+         c = "    ";
+  }
+  else
+    c = "    ";
+  
+  db_printf("\t%s%s%sr%-3d,r%-3d,r%-3d", opcode, c,
+           tab, rd, rs1, rs2);
+}
+
+static struct opdesc {
+    unsigned mask, match;
+    void (*opfun) ();
+    char *farg;
+} opdecode[] = {
+
+    /* ORDER IS IMPORTANT BELOW */
+
+    {  0xF0000000U, 0x00000000U, immem, 0,             },
+    {  0xF0000000U, 0x10000000U, immem, 0,             },
+    {  0xF0000000U, 0x20000000U, immem, "st"           },
+    {  0xF0000000U, 0x30000000U, immem, "lda"          },
+
+    {  0xF8000000U, 0x40000000U, oimmed, "and"         },
+    {  0xF8000000U, 0x48000000U, oimmed, "mask"        },
+    {  0xF8000000U, 0x50000000U, oimmed, "xor"         },
+    {  0xF8000000U, 0x58000000U, oimmed, "or"          },
+    {  0xFC000000U, 0x60000000U, oimmed, "addu"        },
+    {  0xFC000000U, 0x64000000U, oimmed, "subu"        },
+    {  0xFC000000U, 0x68000000U, oimmed, "divu"        },
+    {  0xFC000000U, 0x6C000000U, oimmed, "mul"         },
+    {  0xFC000000U, 0x70000000U, oimmed, "add"         },
+    {  0xFC000000U, 0x74000000U, oimmed, "sub"         },
+    {  0xFC000000U, 0x78000000U, oimmed, "div"         },
+    {  0xFC000000U, 0x7C000000U, oimmed, "cmp"         },
+
+    {  0xFC00F800U, 0x80004000U, ctrlregs, "ldcr"      },
+    {  0xFC00F800U, 0x80004800U, ctrlregs, "fldcr"     },
+    {  0xFC00F800U, 0x80008000U, ctrlregs, "stcr"      },
+    {  0xFC00F800U, 0x80008800U, ctrlregs, "fstcr"     },
+    {  0xFC00F800U, 0x8000C000U, ctrlregs, "xcr"       },
+    {  0xFC00F800U, 0x8000C800U, ctrlregs, "fxcr"      },
+
+    {  0xFC00F800U, 0x84000000U, sindou, "fmul"        },
+    {  0xFC1FFF80U, 0x84002000U, sindou, "flt"         },
+    {  0xFC00F800U, 0x84002800U, sindou, "fadd"        },
+    {  0xFC00F800U, 0x84003000U, sindou, "fsub"        },
+    {  0xFC00F860U, 0x84003800U, sindou, "fcmp"        },
+    {  0xFC1FFE60U, 0x84004800U, sindou, "int"         },
+    {  0xFC1FFE60U, 0x84005000U, sindou, "nint"        },
+    {  0xFC1FFE60U, 0x84005800U, sindou, "trnc"        },
+    {  0xFC00F800U, 0x84007000U, sindou, "fdiv"        },
+
+    {  0xF8000000U, 0xC0000000U, obranch, "br"         },
+    {  0xF8000000U, 0xC8000000U, obranch, "bsr"        },
+
+    {  0xF8000000U, 0xD0000000U, brcond, "bb0"         },
+    {  0xF8000000U, 0xD8000000U, brcond, "bb1"         },
+    {  0xF8000000U, 0xE8000000U, brcond, "bcnd"        },
+
+    {  0xFC00FC00U, 0xF0008000U, obit, "clr"           },
+    {  0xFC00FC00U, 0xF0008800U, obit, "set"           },
+    {  0xFC00FC00U, 0xF0009000U, obit, "ext"           },
+    {  0xFC00FC00U, 0xF0009800U, obit, "extu"          },
+    {  0xFC00FC00U, 0xF000A000U, obit, "mak"           },
+    {  0xFC00FC00U, 0xF000A800U, obit, "rot"           },
+
+    {  0xFC00FE00U, 0xF000D000U, otrap, "tb0"          },
+    {  0xFC00FE00U, 0xF000D800U, otrap, "tb1"          },
+    {  0xFC00FE00U, 0xF000E800U, otrap, "tcnd"         },
+
+    {  0xFC00F2E0U, 0xF4000000U, nimmem, 0,            },
+    {  0xFC00F2E0U, 0xF4000200U, nimmem, 0,            },
+    {  0xFC00F2E0U, 0xF4001000U, nimmem, 0,            },
+    {  0xFC00F2E0U, 0xF4001200U, nimmem, 0,            },
+    {  0xFC00F2E0U, 0xF4002000U, nimmem, "st"          },
+    {  0xFC00F2E0U, 0xF4002200U, nimmem, "st"          },
+    {  0xFC00F2E0U, 0xF4003000U, nimmem, "lda"         },
+    {  0xFC00F2E0U, 0xF4003200U, nimmem, "lda"         },
+
+    {  0xFC00FBE0U, 0xF4004000U, lognim, "and"         },
+    {  0xFC00FBE0U, 0xF4005000U, lognim, "xor"         },
+    {  0xFC00FBE0U, 0xF4005800U, lognim, "or"          },
+
+    {  0xFC00FCE0U, 0xF4006000U, onimmed, "addu"       },
+    {  0xFC00FCE0U, 0xF4006400U, onimmed, "subu"       },
+    {  0xFC00FCE0U, 0xF4006800U, onimmed, "divu"       },
+    {  0xFC00FCE0U, 0xF4006C00U, onimmed, "mul"        },
+    {  0xFC00FCE0U, 0xF4007000U, onimmed, "add"        },
+    {  0xFC00FCE0U, 0xF4007400U, onimmed, "sub"        },
+    {  0xFC00FCE0U, 0xF4007800U, onimmed, "div"        },
+    {  0xFC00FCE0U, 0xF4007C00U, onimmed, "cmp"        },
+    {  0xFC00FFE0U, 0xF4008000U, bitman, "clr"         },
+    {  0xFC00FFE0U, 0xF4008800U, bitman, "set"         },
+    {  0xFC00FFE0U, 0xF4009000U, bitman, "ext"         },
+    {  0xFC00FFE0U, 0xF4009800U, bitman, "extu"        },
+    {  0xFC00FFE0U, 0xF400A000U, bitman, "mak"         },
+    {  0xFC00FFE0U, 0xF400A800U, bitman, "rot"         },
+
+    {  0xFC00FBE0U, 0xF400C000U, jump, "jmp"           },
+    {  0xFC00FBE0U, 0xF400C800U, jump, "jsr"           },
+
+    {  0xFC00FFE0U, 0xF400E800U, instset, "ff1"        },
+    {  0xFC00FFE0U, 0xF400EC00U, instset, "ff0"        },
+    {  0xFC00FFE0U, 0xF400F800U, instset, "tbnd"       },
+    {  0xFC00FFE0U, 0xF400FC00U, instset, "rte"        },
+    {  0xFC000000U, 0xF8000000U, instset, "tbnd"       },
+    {  0,0,0,0 }
+};
+
+static char *badop = "\t???";
+
+int
+m88k_print_instruction(unsigned iadr, long inst)
+{
+  register struct opdesc *p;
+  
+  /* this messes up "orb" instructions ever so slightly, */
+  /* but keeps us in sync between routines... */
+  if (inst == 0) {
+    db_printf ("\t.word 0");
+  }
+  else 
+    {
+      for (p = opdecode; p->mask; p++)
+       if ((inst & p->mask) == p->match) {
+         (*p->opfun) (inst, p->farg, iadr);
+         break;
+       }
+      if (!p->mask)
+       db_printf (badop);
+    }
+
+  return iadr+4;
+}
+
+db_addr_t
+db_disasm(db_addr_t loc, boolean_t altfmt)
+{
+  m88k_print_instruction(loc, db_get_value(loc, 4, FALSE));
+  db_printf ("\n");
+  return loc+4;
+}
diff --git a/sys/arch/mvme88k/ddb/db_interface.c b/sys/arch/mvme88k/ddb/db_interface.c
new file mode 100644 (file)
index 0000000..7717367
--- /dev/null
@@ -0,0 +1,848 @@
+/*
+ * 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.
+ */
+
+/*
+ * m88k interface to ddb debugger
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/systm.h> /* just for boothowto --eichin */
+
+#include <vm/vm.h>
+
+#include <machine/m882xx.h>             /* CMMU defs                   */
+#include <machine/trap.h>               /* current_thread()            */
+#include <machine/db_machdep.h>                 /* local ddb stuff             */
+#include <machine/bug.h>                /* bug routines                */
+#include <machine/mmu.h>
+
+#include <ddb/db_command.h>
+#include <ddb/db_sym.h>
+
+extern label_t *db_recover;
+extern unsigned int db_maxoff;
+
+int    db_active = 0;
+int    db_noisy = 0;
+int    quiet_db_read_bytes = 0;
+
+/*
+ * Received keyboard interrupt sequence.
+ */
+kdb_kintr(regs)
+        register struct m88100_saved_state *regs;
+{
+        if (db_active == 0 && (boothowto & RB_KDB)) {
+                printf("\n\nkernel: keyboard interrupt\n");
+                m88k_db_trap(-1, regs);
+        }
+}
+
+/************************/
+/* PRINTING *************/
+/************************/
+
+static void
+m88k_db_str(char *str)
+{
+    db_printf(str);
+}
+
+static void
+m88k_db_str1(char *str, int arg1)
+{
+    db_printf(str, arg1);
+}
+
+static void
+m88k_db_str2(char *str, int arg1, int arg2)
+{
+    db_printf(str, arg1, arg2);
+}
+
+/************************/
+/* DB_REGISTERS ****/
+/************************/
+
+/*
+ *
+ * If you really feel like understanding the following procedure and
+ * macros, see pages 6-22 to 6-30 (Section 6.7.3) of
+ *
+ * MC881000 RISC Microprocessor User's Manual Second Edition
+ * (Motorola Order: MC88100UM/AD REV 1)
+ *
+ * and ERRATA-5 (6-23, 6-24, 6-24) of
+ *
+ * Errata to MC88100 User's Manual Second Edition MC88100UM/AD Rev 1
+ * (Oct 2, 1990)
+ * (Motorola Order: MC88100UMAD/AD)
+ *
+ */
+
+/* macros for decoding dmt registers */
+
+#define XMEM(x)  ((x) & (1<<12))
+#define XMEM_MODE(x) ((((x)>>2 & 0xf) == 0xf) ? "" : ".bu")
+#define MODE(x) ((x)>>2 & 0xf)
+#define DOUB(x) ((x) & (1<<13))
+#define SIGN(x) ((x) & (1<<6))
+#define DAS(x) (((x) & (1<<14)) ? "" : ".usr")
+#define REG(x) (((x)>>7) & 0x1f)
+#define STORE(x) ((x) & 0x2)
+
+/*
+ * return 1 if the printing of the next stage should be surpressed
+ */
+static int
+m88k_dmx_print(unsigned t, unsigned d, unsigned a, unsigned no)
+{
+    static unsigned addr_mod[16] = { 0, 3, 2, 2, 1, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0};
+    static char *mode[16]  = { "?", ".b", ".b", ".h", ".b", "?", "?", "?",
+                             ".b", ".h", "?" , "?" , "?" , "?", "?", ""};
+    static unsigned mask[16] = { 0,           0xff,        0xff00,     0xffff,
+                                0xff0000,    0,           0,          0,
+                                0xff000000U, 0xffff0000U, 0,          0,
+                                0,           0,           0,    0xffffffffU};
+    static unsigned shift[16] = { 0,  0, 8, 0, 16, 0, 0, 0,
+                                24, 16, 0, 0,  0, 0, 0, 0};
+    int reg = REG(t);
+
+    if (XMEM(t))
+    {
+       db_printf("xmem%s%s r%d(0x%x) <-> mem(0x%x),",
+           XMEM_MODE(t), DAS(t), reg,
+           (((t)>>2 & 0xf) == 0xf) ? d : (d & 0xff), a );
+       return 1;
+    }
+    else
+    {
+       if (MODE(t) == 0xf)
+       {
+           /* full or double word */
+           if (STORE(t))
+               if (DOUB(t) && no == 2)
+                   db_printf("st.d%s -> mem(0x%x) (** restart sxip **)",
+                       DAS(t), a);
+               else
+                   db_printf("st%s (0x%x) -> mem(0x%x)", DAS(t), d, a);
+           else /* load */
+               if (DOUB(t) && no == 2)
+                   db_printf("ld.d%s r%d <- mem(0x%x), r%d <- mem(0x%x)",
+                       DAS(t), reg, a, reg+1, a+4);
+               else
+                   db_printf("ld%s r%d <- mem(0x%x)",  DAS(t), reg, a);
+       }
+       else
+       {
+           /* fractional word - check if load or store */
+           a += addr_mod[MODE(t)];
+           if (STORE(t))
+               db_printf("st%s%s (0x%x) -> mem(0x%x)", mode[MODE(t)], DAS(t),
+               (d & mask[MODE(t)]) >> shift[MODE(t)], a);
+           else
+               db_printf("ld%s%s%s r%d <- mem(0x%x)",
+               mode[MODE(t)], SIGN(t) ? "" : "u", DAS(t), reg, a);
+       }
+    }
+    return 0;
+}
+
+static void
+m88k_db_print_frame(db_expr_t addr, int have_addr, int count, char *modif)
+{
+    struct m88100_saved_state *s = (struct m88100_saved_state *)addr;
+    char *name;
+    db_expr_t offset;
+    int surpress1 = 0, surpress2 = 0;
+    int c, force = 0, help = 0;
+
+    if (!have_addr) {
+       db_printf("requires address of frame\n");
+       help = 1;
+    }
+
+    while (modif && *modif) {
+       switch (c = *modif++, c) {
+       case 'f': force = 1; break;
+       case 'h': help = 1; break;
+        default:
+           db_printf("unknown modifier [%c]\n", c);
+           help = 1;
+           break;
+       }
+    }
+
+    if (help) {
+       db_printf("usage: mach frame/[f] ADDRESS\n");
+       db_printf("  /f force printing of insane frames.\n");
+       return;
+    }
+
+    if (badwordaddr((vm_offset_t)s) ||
+       badwordaddr((vm_offset_t)(&((db_regs_t*)s)->mode))) {
+           db_printf("frame at 0x%08x is unreadable\n", s);
+           return;
+    }
+
+    if (!frame_is_sane(s))  /* see db_trace.c */
+    {
+       db_printf("frame seems insane (");
+
+       if (force)
+           db_printf("forging ahead anyway...)\n");
+       else {
+           db_printf("use /f to force)\n");
+           return;
+       }
+    }
+
+#define R(i) s->r[i]
+#define IPMASK(x) ((x) &  ~(3))
+    db_printf("R00-05: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(0),R(1),R(2),R(3),R(4),R(5));
+    db_printf("R06-11: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(6),R(7),R(8),R(9),R(10),R(11));
+    db_printf("R12-17: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(12),R(13),R(14),R(15),R(16),R(17));
+    db_printf("R18-23: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(18),R(19),R(20),R(21),R(22),R(23));
+    db_printf("R24-29: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(24),R(25),R(26),R(27),R(28),R(29));
+    db_printf("R30-31: 0x%08x  0x%08x\n",R(30),R(31));
+
+    db_printf("sxip: 0x%08x ",s->sxip & ~3);
+    db_find_xtrn_sym_and_offset((db_addr_t) IPMASK(s->sxip),&name,&offset);
+    if (name!= 0 && (unsigned)offset <= db_maxoff)
+       db_printf("%s+0x%08x",name,(unsigned)offset);
+    db_printf("\n");
+    if (s->snip != s->sxip+4)
+    {
+       db_printf("snip: 0x%08x ",s->snip);
+       db_find_xtrn_sym_and_offset((db_addr_t) IPMASK(s->snip),&name,&offset);
+       if (name!= 0 && (unsigned)offset <= db_maxoff)
+           db_printf("%s+0x%08x",name,(unsigned)offset);
+       db_printf("\n");
+    }
+    if (s->sfip != s->snip+4)
+    {
+       db_printf("sfip: 0x%08x ",s->sfip);
+       db_find_xtrn_sym_and_offset((db_addr_t) IPMASK(s->sfip),&name,&offset);
+       if (name!= 0 && (unsigned)offset <= db_maxoff)
+           db_printf("%s+0x%08x",name,(unsigned)offset);
+       db_printf("\n");
+    }
+
+    db_printf("vector: 0x%02x                    interrupt mask: 0x%08x\n",
+       s->vector, s->mask);
+    db_printf("epsr: 0x%08x                current process: 0x%x\n",
+       s->epsr, curproc);
+
+    /*
+     * If the vector indicates trap, instead of an exception or
+     * interrupt, skip the check of dmt and fp regs.
+     *
+     * Interrupt and exceptions are vectored at 0-10 and 114-127.
+     */
+
+    if (!(s->vector <= 10 || (114 <= s->vector && s->vector <= 127)))
+    {
+       db_printf("\n\n");
+       return;
+    }
+
+    if (s->vector == /*data*/3 || s->dmt0 & 1)
+    {
+       db_printf("dmt,d,a0: 0x%08x  0x%08x  0x%08x ",s->dmt0,s->dmd0,s->dma0);
+       db_find_xtrn_sym_and_offset((db_addr_t) s->dma0,&name,&offset);
+       if (name!= 0 && (unsigned)offset <= db_maxoff)
+           db_printf("%s+0x%08x",name,(unsigned)offset);
+       db_printf("\n          ");
+       surpress1 = m88k_dmx_print(s->dmt0|0x01, s->dmd0, s->dma0, 0);
+       db_printf("\n");
+
+       if ((s->dmt1 & 1) && (!surpress1))
+       {
+           db_printf("dmt,d,a1: 0x%08x  0x%08x  0x%08x ",s->dmt1, s->dmd1,s->dma1);
+           db_find_xtrn_sym_and_offset((db_addr_t) s->dma1,&name,&offset);
+           if (name!= 0 && (unsigned)offset <= db_maxoff)
+               db_printf("%s+0x%08x",name,(unsigned)offset);
+           db_printf("\n          ");
+           surpress2 = m88k_dmx_print(s->dmt1, s->dmd1, s->dma1, 1);
+           db_printf("\n");
+
+           if ((s->dmt2 & 1) && (!surpress2))
+           {
+               db_printf("dmt,d,a2: 0x%08x  0x%08x  0x%08x ",s->dmt2, s->dmd2,s->dma2);
+               db_find_xtrn_sym_and_offset((db_addr_t) s->dma2,&name,&offset);
+               if (name!= 0 && (unsigned)offset <= db_maxoff)
+                   db_printf("%s+0x%08x",name,(unsigned)offset);
+               db_printf("\n          ");
+               (void) m88k_dmx_print(s->dmt2, s->dmd2, s->dma2, 2);
+               db_printf("\n");
+           }
+       }
+    }
+
+    if (s->fpecr & 255) /* floating point error occured */
+    {
+       db_printf("fpecr: 0x%08x fpsr: 0x%08x fpcr: 0x%08x\n",
+           s->fpecr,s->fpsr,s->fpcr);
+       db_printf("fcr1-4: 0x%08x  0x%08x  0x%08x  0x%08x\n",
+           s->fphs1, s->fpls1, s->fphs2, s->fpls2);
+       db_printf("fcr5-8: 0x%08x  0x%08x  0x%08x  0x%08x\n",
+           s->fppt,  s->fprh,  s->fprl,  s->fpit);
+    }
+    db_printf("\n\n");
+}
+
+static void
+m88k_db_registers(db_expr_t addr, int have_addr, int count, char *modif)
+{
+    if (modif && *modif) {
+       db_printf("usage: mach regs\n");
+       return;
+    }
+
+    m88k_db_print_frame((db_expr_t)DDB_REGS, TRUE,0,0);
+    return;
+}
+
+/************************/
+/* PAUSE ****************/
+/************************/
+
+/*
+ * pause for 2*ticks many cycles
+ */
+static void
+m88k_db_pause(unsigned volatile ticks)
+{
+    while (ticks)
+       ticks -= 1;
+    return;
+}
+
+/*
+ *  m88k_db_trap - field a TRACE or BPT trap
+ */
+
+m88k_db_trap(
+    int type,
+    register struct m88100_saved_state *regs)
+{
+
+    int i;
+
+#if 0
+    if ((i = db_spl()) != 7)
+       m88k_db_str1("WARNING: spl is not high in m88k_db_trap (spl=%x)\n", i);
+#endif /* 0 */
+
+    if (db_are_interrupts_disabled())
+       m88k_db_str("WARNING: entered debugger with interrupts disabled\n");
+
+    switch(type) {
+    
+    case T_KDB_BREAK:
+    case T_KDB_TRACE:
+    case T_KDB_ENTRY:
+       break;
+    case -1:
+       break;
+    default:
+       kdbprinttrap(type, 0);
+       if (db_recover != 0) {
+               db_error("Caught exception in ddb.\n");
+               /*NOTREACHED*/
+       }
+    }
+    
+    ddb_regs = *regs;
+    
+    db_active++;
+    cnpollc(TRUE);
+    db_trap(type, 0);
+    cnpollc(FALSE);
+    db_active--;
+
+    *regs = ddb_regs;
+
+#if 0
+    (void) spl7();
+#endif
+    return(1);
+}
+
+extern char *trap_type[];
+extern int trap_types;
+
+/*
+ * Print trap reason.
+ */
+kdbprinttrap(type, code)
+       int     type, code;
+{
+       printf("kernel: ");
+       if (type >= trap_types || type < 0)
+               printf("type %d", type);
+       else
+               printf("%s", trap_type[type]);
+       printf(" trap\n");
+}
+
+void
+Debugger(void)
+{
+    asm (ENTRY_ASM); /* entry trap */
+    /* ends up at ddb_entry_trap below */
+}
+
+/* gimmeabreak - drop execute the ENTRY trap */
+void
+gimmeabreak(void)
+{
+    asm (ENTRY_ASM); /* entry trap */
+    /* ends up at ddb_entry_trap below */
+}
+
+/* fielded a non maskable interrupt */
+int
+ddb_nmi_trap(int level, db_regs_t *eframe)
+{
+    NOISY(m88k_db_str("kernel: nmi interrupt\n");)
+    m88k_db_trap(T_KDB_ENTRY, eframe);
+
+    return 0;
+}
+
+/*
+ * When the below routine is entered interrupts should be on
+ * but spl should be high
+ *
+ * The following routine is for breakpoint and watchpoint entry.
+ */
+
+/* breakpoint/watchpoint entry */
+int
+ddb_break_trap(int type, db_regs_t *eframe)
+{
+    m88k_db_trap(type, eframe);
+
+    if (type == T_KDB_BREAK) {
+       /* back up an instruction and retry the instruction at the
+          breakpoint address */
+       eframe->sfip = eframe->snip;
+       eframe->snip = eframe->sxip;
+    }
+
+    return 0;
+}
+
+/* enter at splhigh */
+int
+ddb_entry_trap(int level, db_regs_t *eframe)
+{
+    m88k_db_trap(T_KDB_ENTRY, eframe);
+
+    return 0;
+}
+
+/*
+ * When the below routine is entered interrupts should be on
+ * but spl should be high
+ */
+/* error trap - unreturnable */
+void
+ddb_error_trap(char *error, db_regs_t *eframe)
+{
+
+    m88k_db_str1("KERNEL:  terminal error [%s]\n",(int)error);
+    m88k_db_str ("KERNEL:  Exiting debugger will cause abort to rom\n");
+    m88k_db_str1("at 0x%x ", eframe->sxip & ~3);
+    m88k_db_str2("dmt0 0x%x dma0 0x%x", eframe->dmt0, eframe->dma0);
+    m88k_db_pause(1000000);
+    m88k_db_trap(T_KDB_BREAK, eframe);
+}
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+void
+db_read_bytes(addr, size, data)
+       vm_offset_t     addr;
+       register int    size;
+       register char   *data;
+{
+    register char      *src;
+
+    src = (char *)addr;
+
+    while(--size >= 0) {
+       *data++ = *src++;
+    }
+}
+
+/*
+ * Write bytes to kernel address space for debugger.
+ * This should make a text page writable to be able
+ * to plant a break point (right now text is mapped with
+ * write access in pmap_bootstrap()). XXX nivas
+ */
+void
+db_write_bytes(char *addr, int size, char *data)
+{
+
+    register char      *dst;
+    int i = size;
+    vm_offset_t physaddr;
+    pte_template_t     *pte;
+
+    dst = (char *)addr;
+       
+    while(--size >= 0) {
+#if 0
+       db_printf("byte %x\n", *data);
+#endif /* 0 */
+       *dst++ = *data++;    
+    }
+    physaddr = pmap_extract(kernel_pmap, (vm_offset_t)addr);
+    cmmu_flush_cache(physaddr, i); 
+}
+
+/* to print a character to the console */
+void
+db_putc(int c)
+{
+    bugoutchr(c & 0xff);
+}
+
+/* to peek at the console; returns -1 if no character is there */
+int
+db_getc(void)
+{
+    if (buginstat())
+       return (buginchr());
+    else
+       return -1;
+}
+
+/* display where all the cpus are stopped at */
+static void
+m88k_db_where(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+    struct m88100_saved_state *s;
+    char *name;
+    int *offset;
+    int i;
+    int l;
+
+    s = DDB_REGS;
+
+    l = m88k_pc(s); /* clear low bits */
+
+    db_find_xtrn_sym_and_offset((db_addr_t) l,&name, (db_expr_t*)&offset);
+    if (name && (unsigned)offset <= db_maxoff)
+       db_printf("stopped at 0x%x  (%s+0x%x)\n",
+           l, name, offset);
+    else
+       db_printf("stopped at 0x%x\n", l);
+}
+
+/*
+ * Walk back a stack, looking for exception frames.
+ * These frames are recognized by the routine frame_is_sane. Frames
+ * only start with zero, so we only call frame_is_sane if the
+ * current address contains zero.
+ *
+ * If addr is given, it is assumed to an address on the stack to be
+ * searched. Otherwise, r31 of the current cpu is used.
+ */
+static void
+m88k_db_frame_search(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+#if 1
+    db_printf("sorry, frame search currently disabled.\n");
+#else
+    if (have_addr)
+       addr &= ~3; /* round to word */
+    else
+       addr = (DDB_REGS -> r[31]);
+
+    /* walk back up stack until 8k boundry, looking for 0 */
+    while (addr & ((8*1024)-1))
+    {
+       int i;
+       db_read_bytes(addr, 4, &i);
+       if (i == 0 && frame_is_sane(i))
+           db_printf("frame found at 0x%x\n", i);
+       addr += 4;
+    }
+
+    db_printf("(Walked back until 0x%x)\n",addr);
+#endif
+}
+
+/* flush icache */
+static void
+m88k_db_iflush(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+    addr = 0;
+    cmmu_remote_set(addr, CMMU_SCR, 0, CMMU_FLUSH_CACHE_CBI_ALL);
+}
+
+/* flush dcache */
+
+static void
+m88k_db_dflush(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+    addr = 0;
+
+    cmmu_remote_set(addr, CMMU_SCR, 1, CMMU_FLUSH_CACHE_CBI_ALL);
+}
+
+/* probe my cache */
+static void
+m88k_db_peek(db_expr_t addr, int have_addr, int count, char *modif)
+{
+    int pa12;
+    int valmask;
+
+    pa12 = addr & ~((1<<12) -1);
+
+    /* probe dcache */
+    cmmu_remote_set(0, CMMU_SAR, 1, addr);
+
+    valmask = cmmu_remote_get(0, CMMU_CSSP, 1);
+    db_printf("dcache valmask 0x%x\n", (unsigned)valmask);
+    db_printf("dcache tag ports 0x%x 0x%x 0x%x 0x%x\n",
+    (unsigned)cmmu_remote_get(0, CMMU_CTP0, 1),
+    (unsigned)cmmu_remote_get(0, CMMU_CTP1, 1),
+    (unsigned)cmmu_remote_get(0, CMMU_CTP2, 1),
+    (unsigned)cmmu_remote_get(0, CMMU_CTP3, 1));
+
+    /* probe icache */
+    cmmu_remote_set(0, CMMU_SAR, 0, addr);
+
+    valmask = cmmu_remote_get(0, CMMU_CSSP, 0);
+    db_printf("icache valmask 0x%x\n", (unsigned)valmask);
+    db_printf("icache tag ports 0x%x 0x%x 0x%x 0x%x\n",
+    (unsigned)cmmu_remote_get(0, CMMU_CTP0, 0),
+    (unsigned)cmmu_remote_get(0, CMMU_CTP1, 0),
+    (unsigned)cmmu_remote_get(0, CMMU_CTP2, 0),
+    (unsigned)cmmu_remote_get(0, CMMU_CTP3, 0));
+
+}
+
+
+/*
+ * control how much info the debugger prints about itself
+ */
+static void
+m88k_db_noise(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+    if (!have_addr)
+    {
+       /* if off make noisy; if noisy or very noisy turn off */
+       if (db_noisy)
+       {
+           db_printf("changing debugger status from %s to quiet\n",
+               db_noisy == 1 ? "noisy" :
+               db_noisy == 2 ? "very noisy" : "violent");
+           db_noisy = 0;
+       }
+       else
+       {
+           db_printf("changing debugger status from quiet to noisy\n");
+           db_noisy = 1;
+       }
+    }
+    else
+       if (addr < 0 || addr > 3)
+           db_printf("invalid noise level to m88k_db_noisy; should be 0, 1, 2, or 3\n");
+       else
+       {
+           db_noisy = addr;
+           db_printf("debugger noise level set to %s\n",
+               db_noisy == 0 ? "quiet" :
+               (db_noisy == 1 ? "noisy" :
+               db_noisy==2 ? "very noisy" : "violent"));
+       }
+}
+
+/*
+ * See how a virtual address translates.
+ * Must have an address.
+ */
+static void
+m88k_db_translate(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+#if 0
+    char c;
+    int verbose_flag = 0;
+    int supervisor_flag = 1;
+    int wanthelp = 0;
+
+    if (!have_addr)
+       wanthelp = 1;
+    else {
+        while (c = *modif++, c != 0) {
+           switch (c) {
+            default:
+               db_printf("bad modifier [%c]\n", c); 
+               wanthelp = 1;
+               break;
+            case 'h':
+               wanthelp = 1;
+               break;
+            case 'v':
+               verbose_flag++;
+               break;
+            case 's':
+               supervisor_flag = 1;
+               break;
+            case 'u':
+               supervisor_flag = 0;
+               break;
+           }
+       }
+    }
+    if (wanthelp) {
+       db_printf("usage: translate[/vvsu] address\n");
+       db_printf("flags: v - be verbose (vv - be very verbose)\n");
+       db_printf("       s - use cmmu's supervisor area pointer (default)\n");
+       db_printf("       u - use cmmu's user area pointer\n");
+       return;
+    }
+
+    cmmu_show_translation(addr, supervisor_flag, verbose_flag);
+#endif /* 0 */
+}
+
+void cpu_interrupt_to_db(int cpu_no)
+{}
+
+
+/************************/
+/* COMMAND TABLE / INIT */
+/************************/
+
+static struct db_command m88k_cache_cmds[] =
+{
+    { "iflush",    m88k_db_iflush, 0, 0},
+    { "dflush",    m88k_db_dflush, 0, 0},
+    { "peek",      m88k_db_peek, 0, 0},
+    { (char *) 0,}
+};
+
+struct db_command db_machine_cmds[] =
+{
+    {"cache",          0,                      0, m88k_cache_cmds},
+    {"frame",          m88k_db_print_frame,    0, 0},
+    {"noise",          m88k_db_noise,          0, 0},
+    {"regs",           m88k_db_registers,      0, 0},
+    {"searchframe",    m88k_db_frame_search,   0, 0},
+    {"translate",      m88k_db_translate,      0, 0},
+    {"where",          m88k_db_where,          0, 0},
+    {(char  *) 0,}
+};
+
+/*
+ * Called from "m88k/m1x7_init.c"
+ */
+void
+kdb_init(void)
+{
+#ifdef DB_MACHINE_COMMANDS
+    db_machine_commands_install(db_machine_cmds);
+#endif
+    ddb_init();
+
+    db_printf("ddb enabled\n");
+}
+
+/*
+ * Attempt to figure out the UX name of the task.
+ * This is kludgy at best... we can't even be sure the task is a UX task...
+ */
+#define TOP_OF_USER_STACK USRSTACK
+#define MAX_DISTANCE_TO_LOOK (1024 * 10)
+
+#define DB_TASK_NAME_LEN 50
+
+char
+*db_task_name()
+{
+    static unsigned buffer[(DB_TASK_NAME_LEN + 5)/sizeof(unsigned)];
+    unsigned ptr = (vm_offset_t)(TOP_OF_USER_STACK - 4);
+    unsigned limit = ptr - MAX_DISTANCE_TO_LOOK;
+    unsigned word;
+    int i;
+
+    /* skip zeros at the end */
+    while (ptr > limit &&
+          (i = db_trace_get_val((vm_offset_t)ptr, &word))
+          && (word == 0))
+    {
+       ptr -= 4; /* continue looking for a non-null word */
+    }
+
+    if (ptr <= limit) {
+       db_printf("bad name at line %d\n", __LINE__);
+       return "<couldn't find 1>";
+    } else if (i != 1) {
+       return "<nostack>";
+    }
+
+    /* skip looking for null before all the text */
+    while (ptr > limit
+       &&(i = db_trace_get_val(ptr, &word))
+       && (word != 0))
+    {
+       ptr -= 4; /* continue looking for a null word */
+    }
+    
+    if (ptr <= limit) {
+       db_printf("bad name at line %d\n", __LINE__);
+       return "<couldn't find 2>";
+    } else if (i != 1) {
+       db_printf("bad name read of %x "
+                 "at line %d\n", ptr, __LINE__);
+       return "<bad read 2>";
+    }
+
+    ptr += 4; /* go back to the non-null word after this one */
+
+    for (i = 0; i < sizeof(buffer); i++, ptr+=4) {
+       buffer[i] = 0; /* just in case it's not read */
+       db_trace_get_val((vm_offset_t)ptr, &buffer[i]);
+    }
+    return (char*)buffer;
+}
diff --git a/sys/arch/mvme88k/ddb/db_sstep.c b/sys/arch/mvme88k/ddb/db_sstep.c
new file mode 100644 (file)
index 0000000..db4115b
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * 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 <machine/db_machdep.h>
+#include <ddb/db_access.h>     /* db_get_value() */
+
+/*
+ * Support routines for software single step.
+ *
+ * Author: Daniel Stodolsky (danner@cs.cmu.edu)
+ *
+ */
+
+/* is the instruction a branch or jump instruction (br, bb0, bb1, bcnd, jmp)
+   but not a function call (bsr or jsr) */
+
+boolean_t
+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 & 0xfffffbe0U) == 0xf400c000U)
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
+/* inst_load(ins) - returns the number of words the instruction loads. byte,
+   half and word count as 1; double word as 2 */
+
+unsigned
+inst_load(unsigned ins)
+{
+  /* look at the top six bits, for starters */
+
+  switch (ins >> (32-6))
+    {
+    case 0x0: /* xmem byte imm */
+    case 0x1: /* xmem word imm */
+
+    case 0x2: /* unsigned half-word load imm */
+    case 0x3: /* unsigned byte load imm */
+    case 0x5: /* signed word load imm */
+    case 0x6: /* signed half-word load imm */
+    case 0x7: /* signed byte load imm */
+      return 1;
+
+    case 0x4: /* signed double word load imm */
+      return 2;
+
+    case 0x3d: /* load/store/xmem scaled/unscaled instruction */
+      if ((ins & 0xf400c0e0U) == 0xf4000000U) /* is load/xmem */
+       switch ((ins & 0x0000fce0)>>5)  /* look at bits 15-5, but mask bits 8-9 */
+         {
+         case 0x0: /* xmem byte */
+         case 0x1: /* xmem word */
+         case 0x2: /* unsigned half word */
+         case 0x3: /* unsigned byte load */
+         case 0x5: /* signed word load */
+         case 0x6: /* signed half-word load */
+         case 0x7: /* signed byte load */
+           return 1;
+
+         case 0x4: /* signed double word load */
+           return 2;
+         } /* end switch load/xmem  */
+      break;
+    } /* end switch 32-6 */
+
+  return 0;
+}
+
+/* inst_store - like inst_load, except for store instructions. */
+
+unsigned
+inst_store(unsigned ins)
+{
+  /* decode top 6 bits again */
+  switch (ins >> (32-6))
+    {
+    case 0x0: /* xmem byte imm */
+    case 0x1: /* xmem word imm */
+    case 0x9: /* store word imm */
+    case 0xa: /* store half-word imm */
+    case 0xb: /* store byte imm */
+      return 1;
+
+    case 0x8: /* store double word */
+      return 2;
+    case 0x3d: /* load/store/xmem scaled/unscaled instruction */
+      /* check bits 15,14,12,7,6,5 are all 0 */
+      if ((ins & 0x0000d0e0U) == 0)
+       switch ((ins & 0x00003c00U) >> 10 ) /* decode bits 10-13 */
+         {
+         case 0x0: /* xmem byte imm */
+         case 0x1: /* xmem word imm */
+         case 0x9: /* store word */
+         case 0xa: /* store half-word */
+         case 0xb: /* store byte */
+           return 1;
+
+         case 0x8: /* store double word */
+           return 2;
+         } /* end switch store/xmem */
+      break;
+    } /* end switch 32-6 */
+
+  return 0;
+}
+
+/* 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 */
+
+boolean_t
+inst_delayed(unsigned ins)
+{
+  /* check the br, bsr, bb0, bb1, bcnd cases */
+  switch ((ins & 0xfc000000U)>>(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 & 0xfffff7e0U) == 0xf400c400U) ? TRUE : FALSE;
+}
+
+/*
+ * next_instr_address(pc,delay_slot,task) has the following semantics.
+ * Let inst be the instruction at pc.
+ * If delay_slot = 1, next_instr_address should return
+ * the address of the instruction in the delay slot; if this instruction
+ * does not have a delay slot, it should return pc.
+ * If delay_slot = 0, next_instr_address should return the
+ * address of next sequential instruction, or pc if the instruction is
+ * followed by a delay slot.
+ *
+ * 91-11-28 jfriedl: I think the above is wrong. I think it should be:
+ *     if delay_slot true, return address of the delay slot if there is one,
+ *                         return pc otherwise.
+ *     if delay_slot false, return (pc + 4) regardless.
+ *
+ */
+db_addr_t
+next_instr_address(db_addr_t pc, unsigned delay_slot)
+{
+    if (delay_slot == 0)
+       return pc + 4;
+    else
+    {
+       if (inst_delayed(db_get_value(pc,sizeof(int),FALSE)))
+          return pc + 4;
+       else
+          return pc;
+    }
+}
+
+
+/*
+ * 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
+branch_taken(
+    unsigned inst,
+    unsigned pc,
+    db_expr_t (*func)(unsigned int, db_regs_t *),
+    db_regs_t *func_data)  /* 'opaque' */
+{
+
+  /* check if br/bsr */
+  if ((inst & 0xf0000000U) == 0xc0000000U)
+    {
+      /* signed 26 bit pc relative displacement, shift left two bits */
+      inst = (inst & 0x03ffffffU)<<2;
+      /* check if sign extension is needed */
+      if (inst & 0x08000000U)
+       inst |= 0xf0000000U;
+      return pc + inst;
+    }
+
+  /* check if bb0/bb1/bcnd case */
+  switch ((inst & 0xf8000000U))
+    {
+    case 0xd0000000U: /* bb0 */
+    case 0xd8000000U: /* bb1 */
+    case 0xe8000000U: /* bcnd */
+      /* signed 16 bit pc relative displacement, shift left two bits */
+      inst = (inst & 0x0000ffffU)<<2;
+      /* check if sign extension is needed */
+      if (inst & 0x00020000U)
+       inst |= 0xfffc0000U;
+      return pc + inst;
+    }
+
+  /* check jmp/jsr case */
+  /* check bits 5-31, skipping 10 & 11 */
+  if ((inst & 0xfffff3e0U) == 0xf400c000U)
+    return (*func)(inst & 0x1f, func_data);  /* the register value */
+
+  panic("branch_taken");
+  return 0; /* keeps compiler happy */
+}
+
+/*
+ * 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.
+ */
+db_expr_t
+getreg_val(unsigned regno, db_regs_t *frame)
+{
+    if (regno == 0)
+       return 0;
+    else if (regno < 31)
+       return frame->r[regno];
+    else {
+       panic("bad register number to getreg_val.");
+       return 0;/*to make compiler happy */
+    }
+}
diff --git a/sys/arch/mvme88k/ddb/db_trace.c b/sys/arch/mvme88k/ddb/db_trace.c
new file mode 100644 (file)
index 0000000..9af1296
--- /dev/null
@@ -0,0 +1,1145 @@
+/*
+ * 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.
+ */
+
+union instruction {
+    unsigned rawbits;
+
+    struct {
+       unsigned int    : 5;
+       unsigned int   n: 1;
+       signed int   d26:26;
+    } br;
+
+    struct {
+       unsigned int      : 4;
+       unsigned int isbb1: 1;  /* isbb1==0 means bb0, isbb1==1 means bb1 */
+       unsigned int   n  : 1;
+       unsigned int  b5  : 5;
+       unsigned int  s1  : 5;
+       signed   int  d16 :16;
+    } bb; /* bcnd too, except "isbb1" makes no sense for bcnd */
+
+    struct {
+       unsigned int      : 6;
+       unsigned int  b5  : 5;
+       unsigned int  s1  : 5;
+       unsigned int      : 7;
+       unsigned int vec9 : 9;
+    } tb; /* tcnd too */
+
+    struct {
+       unsigned int      :21;
+       unsigned int    n : 1;
+       unsigned int      : 5;
+       unsigned int   s2 : 5;
+    } jump; /* jmp, jsr */
+
+    struct {
+       unsigned int      : 6;
+        unsigned int    d : 5;
+        unsigned int   s1 : 5;
+        unsigned int  i16 :16;
+    } diatic;  /* general reg/reg/i16 instructions */
+
+    struct {
+       unsigned int      : 6;
+        unsigned int    d : 5;
+        unsigned int   s1 : 5;
+        unsigned int      :11;
+        unsigned int   s2 : 5;
+    } triatic;  /* general reg/reg/reg instructions */
+
+};
+
+static inline unsigned br_dest(unsigned addr, union instruction inst)
+{
+    return addr + inst.br.d26 * 4;
+}
+
+
+#define TRACE_DEBUG    /* undefine to disable debugging */
+
+#include <machine/db_machdep.h> /* lots of stuff                  */
+#include <ddb/db_variables.h>  /* db_variable, DB_VAR_GET, etc.  */
+#include <ddb/db_output.h>     /* db_printf                      */
+#include <ddb/db_sym.h>                /* DB_STGY_PROC, etc.             */
+#include <ddb/db_command.h>    /* db_recover                     */
+
+/*
+ * Some macros to tell if the given text is the instruction.
+ */
+#define JMPN_R1(I)         ( (I) == 0xf400c401U)       /* jmp.n   r1 */
+#define JMP_R1(I)          ( (I) == 0xf400c001U)       /* jmp     r1 */
+
+/* gets the IMM16 value from an instruction */
+#define IMM16VAL(I)        (((union instruction)(I)).diatic.i16)
+
+/* subu r31, r31, IMM */
+#define SUBU_R31_R31_IMM(I) (((I) & 0xffff0000U) == 0x67ff0000U)
+
+/* st r1, r31, IMM */
+#define ST_R1_R31_IMM(I)    (((I) & 0xffff0000U) == 0x243f0000U)
+
+static trace_flags = 0;
+#define TRACE_DEBUG_FLAG               0x01
+#define TRACE_SHOWCALLPRESERVED_FLAG   0x02
+#define TRACE_SHOWADDRESS_FLAG         0x04
+#define TRACE_SHOWFRAME_FLAG           0x08
+#define TRACE_USER_FLAG                        0x10
+
+#ifdef TRACE_DEBUG
+  #define DEBUGGING_ON (trace_flags & TRACE_DEBUG_FLAG)
+#endif
+
+#ifndef TRACE_DEBUG
+  #define SHOW_INSTRUCTION(Addr, Inst, Note)   { /*nothing*/ }
+#else
+  #define SHOW_INSTRUCTION(Addr, Inst, Note) if (DEBUGGING_ON) {       \
+    db_printf("%s0x%x: (0x%08x) ", Note, (unsigned)(Addr), (Inst));    \
+    m88k_print_instruction((unsigned)(Addr), (Inst));                  \
+    db_printf("\n");                                   \
+  }
+#endif
+
+extern label_t *db_recover;
+extern int quiet_db_read_bytes;
+/*
+ * m88k trace/register state interface for ddb.
+ */
+
+/* lifted from mips */
+static int
+db_setf_regs(
+       struct db_variable      *vp,
+       db_expr_t               *valuep,
+       int                     op)             /* read/write */
+{
+    register int   *regp = (int *) ((char *) DDB_REGS + (int) (vp->valuep));
+
+    if (op == DB_VAR_GET)
+       *valuep = *regp;
+    else if (op == DB_VAR_SET)
+       *regp = *valuep;
+}
+
+#define N(s, x)  {s, (int *)&(((db_regs_t *) 0)->x), db_setf_regs}
+
+struct db_variable db_regs[] = {
+    N("r1", r[1]),     N("r2", r[2]),   N("r3", r[3]),    N("r4", r[4]),
+    N("r5", r[5]),     N("r6", r[6]),   N("r7", r[7]),    N("r8", r[8]),
+    N("r9", r[9]),     N("r10", r[10]),  N("r11", r[11]),  N("r12", r[12]),
+    N("r13", r[13]),   N("r14", r[14]),  N("r15", r[15]),  N("r16", r[16]),
+    N("r17", r[17]),   N("r18", r[18]),  N("r19", r[19]),  N("r20", r[20]),
+    N("r21", r[21]),   N("r22", r[22]),  N("r23", r[23]),  N("r24", r[24]),
+    N("r25", r[25]),   N("r26", r[26]),  N("r27", r[27]),  N("r28", r[28]),
+    N("r29", r[29]),   N("r30", r[30]),  N("r31", r[31]),  N("epsr", epsr),
+    N("sxip", sxip),   N("snip", snip),  N("sfip", sfip),  N("ssbr", ssbr),
+    N("dmt0", dmt0),   N("dmd0", dmd0),  N("dma0", dma0),  N("dmt1", dmt1),
+    N("dmd1", dmd1),   N("dma1", dma1),  N("dmt2", dmt2),  N("dmd2", dmd2),
+    N("dma2", dma2),   N("fpecr", fpecr),N("fphs1", fphs1),N("fpls1", fpls1),
+    N("fphs2", fphs2), N("fpls2", fpls2),N("fppt", fppt),  N("fprh", fprh),
+    N("fprl", fprl),   N("fpit", fpit),  N("fpsr", fpsr),  N("fpcr", fpcr),
+    N("mask", mask), /* interrupt mask */
+    N("mode", mode), /* interrupt mode */
+    N("exvc", vector), /* exception vector */
+};
+#undef N
+
+struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+
+
+#define TRASHES    0x001       /* clobbers instruction field D */
+#define STORE      0x002       /* does a store to S1+IMM16 */
+#define LOAD       0x004       /* does a load from S1+IMM16 */
+#define DOUBLE     0x008       /* double-register */
+#define FLOW_CTRL  0x010       /* flow-control instruction */
+#define DELAYED    0x020       /* delayed flow control */
+#define JSR       0x040        /* flow-control is a jsr[.n] */
+#define BSR       0x080        /* flow-control is a bsr[.n] */
+
+/*
+ * Given a word of instruction text, return some flags about that
+ * instruction (flags defined above).
+ */
+static unsigned
+m88k_instruction_info(unsigned instruction)
+{
+   static struct { unsigned mask, value, flags; } *ptr, control[] =
+   {
+      /* runs in the same order as 2nd Ed 88100 manual Table 3-14 */
+     { 0xf0000000U, 0x00000000U, /* xmem */     TRASHES | STORE | LOAD    },
+     { 0xec000000U, 0x00000000U, /* ld.d */     TRASHES | LOAD | DOUBLE   },
+     { 0xe0000000U, 0x00000000U, /* load */     TRASHES | LOAD            },
+     { 0xfc000000U, 0x20000000U, /* st.d */     STORE | DOUBLE            },
+     { 0xf0000000U, 0x20000000U, /* store */    STORE                     },
+     { 0xc0000000U, 0x40000000U, /* arith */    TRASHES                   },
+     { 0xfc004000U, 0x80004000U, /* ld cr */    TRASHES                   },
+     { 0xfc004000U, 0x80000000U, /* st cr */    0                         },
+     { 0xfc008060U, 0x84000000U, /* f */        TRASHES                   },
+     { 0xfc008060U, 0x84000020U, /* f.d */      TRASHES | DOUBLE          },
+     { 0xfc000000U, 0xcc000000U, /* bsr.n */    FLOW_CTRL | DELAYED | BSR },
+     { 0xfc000000U, 0xc8000000U, /* bsr */      FLOW_CTRL | BSR           },
+     { 0xe4000000U, 0xc4000000U, /* br/bb.n */  FLOW_CTRL | DELAYED       },
+     { 0xe4000000U, 0xc0000000U, /* br/bb */    FLOW_CTRL                 },
+     { 0xfc000000U, 0xec000000U, /* bcnd.n */   FLOW_CTRL | DELAYED       },
+     { 0xfc000000U, 0xe8000000U, /* bcnd */     FLOW_CTRL                 },
+     { 0xfc00c000U, 0xf0008000U, /* bits */     TRASHES                   },
+     { 0xfc00c000U, 0xf000c000U, /* trap */     0                         },
+     { 0xfc00f0e0U, 0xf4002000U, /* st */       0                         },
+     { 0xfc00cce0U, 0xf4000000U, /* ld.d */     TRASHES | DOUBLE          },
+     { 0xfc00c0e0U, 0xf4000000U, /* ld */       TRASHES                   },
+     { 0xfc00c0e0U, 0xf4004000U, /* arith */    TRASHES                   },
+     { 0xfc00c3e0U, 0xf4008000U, /* bits */     TRASHES                   },
+     { 0xfc00ffe0U, 0xf400cc00U, /* jsr.n */    FLOW_CTRL | DELAYED | JSR },
+     { 0xfc00ffe0U, 0xf400c800U, /* jsr */      FLOW_CTRL | JSR           },
+     { 0xfc00ffe0U, 0xf400c400U, /* jmp.n */    FLOW_CTRL | DELAYED       },
+     { 0xfc00ffe0U, 0xf400c000U, /* jmp */      FLOW_CTRL                 },
+     { 0xfc00fbe0U, 0xf400e800U, /* ff */       TRASHES                   },
+     { 0xfc00ffe0U, 0xf400f800U, /* tbnd */     0                         },
+     { 0xfc00ffe0U, 0xf400fc00U, /* rte */      FLOW_CTRL                 },
+     { 0xfc000000U, 0xf8000000U, /* tbnd */     0                         },
+    };
+    #define ctrl_count (sizeof(control)/sizeof(control[0]))
+    for (ptr = &control[0]; ptr < &control[ctrl_count]; ptr++)
+       if ((instruction & ptr->mask) == ptr->value)
+           return ptr->flags;
+    SHOW_INSTRUCTION(0, instruction, "bad m88k_instruction_info");
+    return 0;
+}
+
+static int
+hex_value_needs_0x(unsigned value)
+{
+    int i;
+    unsigned last = 0;
+    unsigned char c; 
+    unsigned have_a_hex_digit = 0;
+
+    if (value <= 9)
+       return 0;
+
+    for (i = 0; i < 8; i++) {
+       c = value & 0xf;
+       value >>= 4;
+       if (c)
+           last = c;
+       if (c > 9)
+           have_a_hex_digit = 1;
+    }
+    if (have_a_hex_digit == 0)
+       return 1;
+    if (last > 9)
+       return 1;
+    return 0;
+}
+
+
+/*
+ * returns
+ *   1 if regs seems to be a reasonable kernel exception frame.
+ *   2 if regs seems to be a reasonable user exception frame
+ *     (in the current task).
+ *   0 if this looks like neither.
+ */
+int
+frame_is_sane(db_regs_t *regs)
+{
+    /* no good if we can't read the whole frame */
+    if (badwordaddr((vm_offset_t)regs) || badwordaddr((vm_offset_t)&regs->mode))
+       return 0;
+
+#ifndef DIAGNOSTIC
+    /* disabled for now  -- see fpu_enable in luna88k/eh.s */
+    /* r0 must be 0 (obviously) */
+    if (regs->r[0] != 0)
+       return 0;
+#endif
+
+    /* stack sanity ... r31 must be nonzero, but must be word aligned */
+    if (regs->r[31] == 0 || (regs->r[31] & 3) != 0)
+       return 0;
+
+    /* sxip is reasonable */
+#if 0
+    if ((regs->sxip & 1) == 1)
+       return 0;
+#endif
+    /* snip is reasonable */
+    if ((regs->snip & 3) != 2)
+       return 0;
+    /* sfip is reasonable */
+    if ((regs->sfip & 3) != 2)
+       return 0;
+
+    /* epsr sanity */
+    if ((regs->epsr & 0x8FFFFFF5U) == 0x800003f0U) /* kernel mode */
+    {
+       if (regs->epsr & 0x40000000) 
+         db_printf("[WARNING: byte order in kernel frame at %x "
+                   "is little-endian!]\n", regs);
+       return 1;
+    }
+    if ((regs->epsr & 0x8FFFFFFFU) == 0x000003f0U) /* user mode */
+    {
+       if (regs->epsr & 0x40000000) 
+         db_printf("[WARNING: byte order in user frame at %x "
+                   "is little-endian!]\n", regs);
+       return 2;
+    }
+    return 0;
+}
+
+char
+*m88k_exception_name(unsigned vector)
+{
+    switch  (vector)
+    {
+       default:
+       case   0: return "Reset";
+       case   1: return "Interrupt";
+       case   2: return "Instruction Access Exception";
+       case   3: return "Data Access Exception";
+       case   4: return "Misaligned Access Exception";
+       case   5: return "Unimplemented Opcode Exception";
+       case   6: return "Privilege Violation";
+       case   7: return "Bounds Check";
+       case   8: return "Integer Divide Exception";
+       case   9: return "Integer Overflow Exception";
+       case  10: return "Error Exception";
+       case 114: return "FPU precise";
+       case 115: return "FPU imprecise";
+       case 130: return "Ddb break";
+       case 131: return "Ddb trace";
+       case 132: return "Ddb trap";
+       case 451: return "Syscall";
+    }
+}
+
+/*
+ * Read a word at address addr.
+ * Return 1 if was able to read, 0 otherwise.
+ */
+unsigned
+db_trace_get_val(vm_offset_t addr, unsigned *ptr)
+{
+    label_t db_jmpbuf;
+    label_t *prev = db_recover;
+    boolean_t old_quiet_db_read_bytes = quiet_db_read_bytes;
+
+    quiet_db_read_bytes = 1;
+
+    if (setjmp(*(db_recover = &db_jmpbuf)) != 0) {
+       db_recover = prev;
+        quiet_db_read_bytes = old_quiet_db_read_bytes;
+       return 0;
+    } else {
+       db_read_bytes((char*)addr, 4, (char*)ptr);
+       db_recover = prev;
+        quiet_db_read_bytes = old_quiet_db_read_bytes;
+       return 1;
+    }
+}
+
+
+#define FIRST_CALLPRESERVED_REG 14
+#define LAST_CALLPRESERVED_REG  29
+#define FIRST_ARG_REG       2
+#define LAST_ARG_REG        9
+#define RETURN_VAL_REG           1
+
+static unsigned global_saved_list = 0x0; /* one bit per register */
+static unsigned local_saved_list  = 0x0; /* one bit per register */
+static unsigned trashed_list      = 0x0; /* one bit per register */
+static unsigned saved_reg[32];          /* one value per register */
+
+#define reg_bit(reg) (1<<((reg)%32))
+
+static void
+save_reg(int reg, unsigned value)
+{
+    #ifdef TRACE_DEBUG
+       if (DEBUGGING_ON) db_printf("save_reg(%d, %x)\n", reg, value);
+    #endif
+    if (trashed_list & reg_bit(reg)) {
+       #ifdef TRACE_DEBUG
+           if (DEBUGGING_ON) db_printf("<trashed>\n");
+       #endif
+       return; /* don't save trashed registers */
+    }
+    saved_reg[(reg%32)] = value;
+    global_saved_list |= reg_bit(reg);
+    local_saved_list  |= reg_bit(reg);
+}
+
+#define mark_reg_trashed(reg)  (trashed_list |= reg_bit(reg))
+
+#define have_global_reg(reg) (global_saved_list & (1<<(reg)))
+#define have_local_reg(reg)  (local_saved_list & (1<<(reg)))
+
+#define clear_local_saved_regs()  { local_saved_list = trashed_list =      0; }
+#define clear_global_saved_regs() { local_saved_list = global_saved_list = 0; }
+
+#define saved_reg_value(reg) (saved_reg[(reg)])
+
+/*
+ * Show any arguments that we might have been able to determine.
+ */
+static void
+print_args(void)
+{
+    int reg, last_arg;
+
+    /* find the highest argument register saved */
+    for (last_arg = LAST_ARG_REG; last_arg >= FIRST_ARG_REG; last_arg--)
+       if (have_local_reg(last_arg))
+           break;
+    if (last_arg < FIRST_ARG_REG)
+       return; /* none were saved */
+
+    db_printf("(");
+
+    /* print each one, up to the highest */
+    for (reg = FIRST_ARG_REG; /*nothing */; reg++)
+    {
+       if (!have_local_reg(reg))
+           db_printf("?");
+       else {
+           unsigned value = saved_reg_value(reg);
+           db_printf("%s%x", hex_value_needs_0x(value)  ? "0x" : "", value);
+       }
+       if (reg == last_arg)
+           break;
+       else
+           db_printf(", ");
+    }
+    db_printf(")");
+}
+
+
+#define JUMP_SOURCE_IS_BAD             0
+#define JUMP_SOURCE_IS_OK              1
+#define JUMP_SOURCE_IS_UNLIKELY                2
+
+/*
+ * Give an address to where we return, and an address to where we'd jumped,
+ * Decided if it all makes sense.
+ *
+ * Gcc sometimes optimized something like
+ *     if (condition)
+ *             func1();
+ *     else
+ *             OtherStuff...
+ * to
+ *     bcnd   !condition  mark
+ *     bsr.n  func1
+ *     or     r1, r0, mark2
+ *    mark:
+ *     OtherStuff...
+ *    mark2:
+ *
+ * So RETURN_TO will be MARK2, even though we really did branch via
+ * 'bsr.n func1', so this makes it difficult to be certaian about being
+ * wrong.
+ */
+static int
+is_jump_source_ok(unsigned return_to, unsigned jump_to)
+{
+    unsigned flags;
+    union instruction instruction; 
+
+    /*
+     * Delayed branches are most common... look two instructions before
+     * where we were going to return to to see if it's a delayed branch.
+     */
+    if (!db_trace_get_val(return_to - 8, &instruction.rawbits))
+       return JUMP_SOURCE_IS_BAD;
+    flags = m88k_instruction_info(instruction.rawbits);
+
+    if ((flags & FLOW_CTRL) && (flags & DELAYED) && (flags & (JSR|BSR))) {
+       if (flags & JSR)
+           return JUMP_SOURCE_IS_OK; /* have to assume it's correct */
+       /* calculate the offset */
+       if (br_dest(return_to - 8, instruction) == jump_to)
+           return JUMP_SOURCE_IS_OK; /* exactamundo! */
+       else
+           return JUMP_SOURCE_IS_UNLIKELY; /* seems wrong */
+    }
+
+    /*
+     * Try again, looking for a non-delayed jump one back.
+     */
+    if (!db_trace_get_val(return_to - 4, &instruction.rawbits))
+       return JUMP_SOURCE_IS_BAD;
+    flags = m88k_instruction_info(instruction.rawbits);
+
+    if ((flags & FLOW_CTRL) && !(flags & DELAYED) && (flags & (JSR|BSR))) {
+       if (flags & JSR)
+           return JUMP_SOURCE_IS_OK; /* have to assume it's correct */
+       /* calculate the offset */
+       if (br_dest(return_to - 4, instruction) == jump_to)
+           return JUMP_SOURCE_IS_OK; /* exactamundo! */
+       else
+           return JUMP_SOURCE_IS_UNLIKELY; /* seems wrong */
+    }
+
+    return JUMP_SOURCE_IS_UNLIKELY;
+}
+
+static char *note = 0;
+static int next_address_likely_wrong = 0;
+
+/* How much slop we expect in the stack trace */
+#define FRAME_PLAY 8
+
+/*
+ *  Stack decode -
+ *     unsigned addr;    program counter
+ *     unsigned *stack; IN/OUT stack pointer
+ *
+ *     given an address within a function and a stack pointer,
+ *     try to find the function from which this one was called
+ *     and the stack pointer for that function.
+ *
+ *     The return value is zero (if we get confused) or
+ *     we determine that the return address has not yet
+ *     been saved (early in the function prologue). Otherwise
+ *     the return value is the address from which this function
+ *     was called.
+ *
+ *     Note that even is zero is returned (the second case) the
+ *     stack pointer can be adjusted.
+ *
+ */
+static int
+stack_decode(unsigned addr, unsigned *stack)
+{
+    db_sym_t proc;
+    unsigned offset_from_proc;
+    unsigned instructions_to_search;
+    unsigned check_addr;
+    unsigned function_addr;    /* start of function */
+    unsigned r31 = *stack;     /* the r31 of the function */
+    unsigned inst;             /* text of an instruction */
+    unsigned ret_addr;         /* address to which we return */
+    unsigned tried_to_save_r1 = 0;
+
+    #ifdef TRACE_DEBUG
+      if (DEBUGGING_ON)
+       db_printf("\n>>>stack_decode(addr=%x, stack=%x)\n",
+               addr, *stack);
+    #endif
+
+      /* get what we hope will be the db_sym_t for the function name */
+    proc = db_search_symbol(addr, DB_STGY_PROC, &offset_from_proc);
+    if (offset_from_proc == addr) /* i.e. no symbol found */
+       proc = DB_SYM_NULL;
+
+    /*
+     * Somehow, find the start of this function.
+     * If we found a symbol above, it'll have the address.
+     * Otherwise, we've got to search for it....
+     */
+    if (proc != DB_SYM_NULL)
+    {
+       char *names;
+       db_symbol_values(proc, &names, &function_addr);
+       if (names == 0)
+           return 0;
+       #ifdef TRACE_DEBUG
+           if (DEBUGGING_ON) db_printf("name %s address 0x%x\n",
+               names, function_addr);
+       #endif
+    }
+    else
+    {
+       int instructions_to_check = 400;
+       /*
+        * hmm - unable to find symbol. Search back
+        * looking for a function prolog.
+        */
+       for (check_addr = addr; instructions_to_check-- > 0; check_addr -= 4)
+       {
+           if (!db_trace_get_val(check_addr, &inst))
+               break;
+
+           if (SUBU_R31_R31_IMM(inst))
+           {
+               #if 0
+                   /*
+                    * If the next instruction is "st r1, r31, ####"
+                    * then we can feel safe we have the start of
+                    * a function.
+                    */
+                   if (!db_trace_get_val(check_addr + 4, &inst))
+                       continue;
+                   if (ST_R1_R31_IMM(instr))
+                       break; /* sucess */
+               #else
+                   /*
+                    * Latest GCC optimizer is just too good... the store
+                    * of r1 might come much later... so we'll have to
+                    * settle for just the "subr r31, r31, ###" to mark
+                    * the start....
+                    */
+                    break;
+               #endif
+           }
+           /*
+            * if we come across a [jmp r1] or [jmp.n r1] assume we have hit
+            * the previous functions epilogue and stop our search.
+            * Since we know we would have hit the "subr r31, r31" if it was
+            * right in front of us, we know this doesn't have one so
+            * we just return failure....
+            */
+           if (JMP_R1(inst) || JMPN_R1(inst)) {
+               #ifdef TRACE_DEBUG
+                   if (DEBUGGING_ON)
+                       db_printf("ran into a [jmp r1] at %x (addr=%x)\n",
+                               check_addr, addr);
+               #endif
+               return 0;
+           }
+       }
+       if (instructions_to_check < 0) {
+           #ifdef TRACE_DEBUG
+               if (DEBUGGING_ON)
+                   db_printf("couldn't find func start (addr=%x)\n", addr);
+           #endif
+           return 0; /* bummer, couldn't find it */
+       }
+       function_addr = check_addr;
+    }
+
+    /*
+     * We now know the start of the function (function_addr).
+     * If we're stopped right there, or if it's not a
+     *         subu r31, r31, ####
+     * then we're done.
+     */
+    if (addr == function_addr) {
+       #ifdef TRACE_DEBUG
+           if (DEBUGGING_ON) db_printf("at start of func\n");
+       #endif
+       return 0;
+    }
+    if (!db_trace_get_val(function_addr, &inst)) {
+       #ifdef TRACE_DEBUG
+           if (DEBUGGING_ON) db_printf("couldn't read %x at line %d\n",
+               function_addr, __LINE__);
+       #endif
+       return 0;
+    }
+    SHOW_INSTRUCTION(function_addr, inst, "start of function: ");
+    if (!SUBU_R31_R31_IMM(inst)) {
+       #ifdef TRACE_DEBUG
+           if (DEBUGGING_ON) db_printf("<not subu,r31,r31,imm>\n");
+       #endif
+       return 0;
+    }
+
+    /* add the size of this frame to the stack (for the next frame) */
+    *stack += IMM16VAL(inst);
+
+    /*
+     * Search from the beginning of the function (funstart) to where we are
+     * in the function (addr) looking to see what kind of registers have
+     * been saved on the stack.
+     *
+     * We'll stop looking before we get to ADDR if we hit a branch.
+     */
+    clear_local_saved_regs();
+    check_addr = function_addr + 4; /* we know the first inst isn't a store */
+
+    for (instructions_to_search = (addr - check_addr)/sizeof(long);
+       instructions_to_search-- > 0;
+       check_addr += 4)
+    {
+       union instruction instruction;
+       unsigned flags;
+
+       /* read the instruction */
+        if (!db_trace_get_val(check_addr, &instruction.rawbits)) {
+           #ifdef TRACE_DEBUG
+               if (DEBUGGING_ON) db_printf("couldn't read %x at line %d\n",
+                   check_addr, __LINE__);
+           #endif
+            break;
+       }
+
+       SHOW_INSTRUCTION(check_addr, instruction.rawbits, "prolog: ");
+
+       /* find out the particulars about this instruction */
+       flags = m88k_instruction_info(instruction.rawbits);
+
+       /* if a store to something off the stack pointer, note the value */
+       if ((flags & STORE) && instruction.diatic.s1 == /*stack pointer*/31)
+       {
+           unsigned value;
+           if (!have_local_reg(instruction.diatic.d)) {
+               if (instruction.diatic.d == 1)
+                       tried_to_save_r1 = r31 + instruction.diatic.i16 ;
+               if (db_trace_get_val(r31 + instruction.diatic.i16, &value))
+                   save_reg(instruction.diatic.d, value);
+           }
+           if ((flags & DOUBLE) && !have_local_reg(instruction.diatic.d + 1)) {
+               if (instruction.diatic.d == 0)
+                   tried_to_save_r1 = r31+instruction.diatic.i16 +4;
+               if (db_trace_get_val(r31+instruction.diatic.i16 +4, &value))
+                   save_reg(instruction.diatic.d + 1, value);
+           }
+       }
+
+       /* if an inst that kills D (and maybe D+1), note that */
+       if (flags & TRASHES) {
+           mark_reg_trashed(instruction.diatic.d);
+           if (flags & DOUBLE)
+               mark_reg_trashed(instruction.diatic.d + 1);
+       }
+
+       /* if a flow control instruction, stop now (or next if delayed) */
+       if ((flags & FLOW_CTRL) && instructions_to_search != 0)
+           instructions_to_search = (flags & DELAYED) ? 1 : 0;
+    }
+
+    /*
+     * If we didn't save r1 at some point, we're hosed.
+     */
+    if (!have_local_reg(1)) {
+       if (tried_to_save_r1) {
+           db_printf("    <return value of next fcn unreadable in %08x>\n",
+               tried_to_save_r1);
+       }
+       #ifdef TRACE_DEBUG
+           if (DEBUGGING_ON) db_printf("didn't save r1\n");
+       #endif
+       return 0;
+    }
+
+    ret_addr = saved_reg_value(1);
+
+    #ifdef TRACE_DEBUG
+    if (DEBUGGING_ON)
+       db_printf("Return value is = %x, function_addr is %x.\n",
+           ret_addr, function_addr);
+    #endif
+
+    /*
+     * In support of this, continuation.s puts the low bit on the
+     * return address for continuations (the return address will never
+     * be used, so it's ok to do anything you want to it).
+     */
+    if (ret_addr & 1) {
+       note = "<<can not trace past a continuation>>";
+       ret_addr = 0;
+    } else if (ret_addr != 0x00) {
+       switch(is_jump_source_ok(ret_addr, function_addr)) {
+         case JUMP_SOURCE_IS_OK:
+               break; /* excellent */
+
+         case JUMP_SOURCE_IS_BAD:
+               #ifdef TRACE_DEBUG
+                   if (DEBUGGING_ON) db_printf("jump is bad\n");
+               #endif
+               return 0; /* bummer */
+
+         case JUMP_SOURCE_IS_UNLIKELY:
+               next_address_likely_wrong = 1;;
+               break;
+       }
+    }
+
+    return ret_addr;
+}
+
+static void
+db_stack_trace_cmd2(db_regs_t *regs)
+{
+    unsigned stack;
+    unsigned depth=1;
+    unsigned where;
+    unsigned ft;
+    unsigned pair[2];
+    int i;
+
+    /*
+     * Frame_is_sane returns:
+     *   1 if regs seems to be a reasonable kernel exception frame.
+     *   2 if regs seems to be a reasonable user exception frame
+     *      (in the current task).
+     *   0 if this looks like neither.
+     */
+    if (ft = frame_is_sane(regs), ft == 0)
+    {
+       db_printf("Register frame 0x%x is suspicous; skipping trace\n", regs);
+       return;
+    }
+
+    /* if user space and no user space trace specified, puke */
+    if (ft == 2 && !(trace_flags & TRACE_USER_FLAG))
+       return;
+
+    /* fetch address */
+    /* use sxip if valid, otherwise try snip or sfip */
+    where = ((regs->sxip & 2) ? regs->sxip :
+           ((regs->snip & 2) ? regs->snip :
+             regs->sfip) ) & ~3;
+    stack = regs->r[31];
+    db_printf("stack base = 0x%x\n", stack);
+    db_printf("(0) "); /*depth of trace */
+    if (trace_flags & TRACE_SHOWADDRESS_FLAG)
+       db_printf("%08x ", where);
+    db_printsym(where, DB_STGY_PROC);
+    clear_global_saved_regs();
+
+    /* see if this routine had a stack frame */
+    if ((where=stack_decode(where, &stack))==0)
+    {
+       where = regs->r[1];
+       db_printf("(stackless)");
+    }
+    else
+    {
+       print_args();
+       if (trace_flags & TRACE_SHOWFRAME_FLAG)
+           db_printf(" [frame 0x%x]", stack);
+    }
+    db_printf("\n");
+    if (note) {
+       db_printf("   %s\n", note);
+       note = 0;
+    }
+
+    do
+    {
+       /*
+        * If requested, show preserved registers at the time
+        * the next-shown call was made. Only registers known to have
+        * changed from the last exception frame are shown, as others
+        * can be gotten at by looking at the exception frame.
+        */
+       if (trace_flags & TRACE_SHOWCALLPRESERVED_FLAG)
+       {
+           int r, title_printed = 0;
+
+           for (r = FIRST_CALLPRESERVED_REG; r<=LAST_CALLPRESERVED_REG; r++) {
+               if (have_global_reg(r)) {
+                   unsigned value = saved_reg_value(r);
+                   if (title_printed == 0) {
+                      title_printed = 1;
+                      db_printf("[in next func:");
+                   }
+                   if (value == 0)
+                       db_printf(" r%d", r);
+                   else if (value <= 9)
+                       db_printf(" r%d=%x", r, value);
+                   else
+                       db_printf(" r%d=x%x", r, value);
+               }
+           }
+           if (title_printed)
+               db_printf("]\n");
+       }
+
+       db_printf("(%d)%c", depth++, next_address_likely_wrong ? '?':' ');
+       next_address_likely_wrong = 0;
+
+       if (trace_flags & TRACE_SHOWADDRESS_FLAG)
+           db_printf("%08x ", where);
+       db_printsym(where, DB_STGY_PROC);
+       where = stack_decode(where, &stack);
+       print_args();
+       if (trace_flags & TRACE_SHOWFRAME_FLAG)
+           db_printf(" [frame 0x%x]", stack);
+       db_printf("\n");
+       if (note) {
+           db_printf("   %s\n", note);
+           note = 0;
+       }
+    } while (where);
+
+    /* try to trace back over trap/exception */
+
+    stack &= ~7; /* double word aligned */
+    /* take last top of stack, and try to find an exception frame near it */
+
+    i = FRAME_PLAY;
+
+    #ifdef TRACE_DEBUG
+       if (DEBUGGING_ON)
+           db_printf("(searching for exception frame at 0x%x)\n", stack);
+    #endif
+
+    while (i)
+    {
+       /*
+        * On the stack, a pointer to the exception frame is written
+        * in two adjacent words. In the case of a fault from the kernel,
+        * this should point to the frame right above them:
+        *
+        * Exception Frame Top
+        * ..
+        * Exception Frame Bottom  <-- frame addr
+        * frame addr
+        * frame addr           <-- stack pointer
+        *
+        * In the case of a fault from user mode, the top of stack
+        * will just have the address of the frame
+        * replicated twice.
+        *
+        * frame addr           <-- top of stack
+        * frame addr
+        *
+        * Here we are just looking for kernel exception frames.
+        */
+
+       if (badwordaddr((vm_offset_t)stack) ||
+           badwordaddr((vm_offset_t)(stack+4)))
+                   break;
+
+       db_read_bytes((char*)stack, 2*sizeof(int), (char*)pair);
+
+       /* the pairs should match and equal stack+8 */
+       if (pair[0] == pair[1])
+       {
+           if (pair[0] != stack+8)
+           {
+               /*
+               if (!badwordaddr((vm_offset_t)pair[0]) && (pair[0]!=0))
+               db_printf("stack_trace:found pair 0x%x but != to stack+8\n",
+               pair[0]);
+               */
+           }
+           else if (frame_is_sane((db_regs_t*)pair[0]))
+           {
+               db_regs_t *frame = (db_regs_t *) pair[0];
+               char *cause = m88k_exception_name(frame -> vector);
+
+               db_printf("-------------- %s [EF: 0x%x] -------------\n",
+                     cause, frame);
+               db_stack_trace_cmd2(frame);
+               return;
+           }
+           #ifdef TRACE_DEBUG
+               else if (DEBUGGING_ON)
+                   db_printf("pair matched, but frame at 0x%x looks insane\n",
+                       stack+8);
+           #endif
+       }
+       stack += 8;
+       i--;
+    }
+
+    /*
+     * If we go here, crawling back on the stack failed to find us
+     * a previous exception frame. Look for a user frame pointer
+     * pointed to by a word 8 bytes off of the top of the stack
+     * if the "u" option was specified.
+     */
+    if (trace_flags & TRACE_USER_FLAG)
+    {
+       db_regs_t *user;
+
+       /* Make sure we are back on the right page */
+       stack -= 4*FRAME_PLAY;
+       stack = stack & ~(KERNEL_STACK_SIZE-1); /* point to the bottom */
+       stack += KERNEL_STACK_SIZE - 8;
+
+       if (badwordaddr((vm_offset_t)stack) ||
+           badwordaddr((vm_offset_t)stack))
+                   return;
+
+       db_read_bytes((char*)stack, 2*sizeof(int), (char*)pair);
+       if (pair[0] != pair[1])
+           return;
+
+       /* have a hit */
+       user = *((db_regs_t **) stack);
+
+       if (frame_is_sane(user) == 2)
+       {
+           db_printf("---------------- %s [EF : 0x%x] -------------\n",
+               m88k_exception_name(user->vector), user);
+           db_stack_trace_cmd2(user);
+       }
+    }
+}
+
+/*
+ * stack trace - needs a pointer to a m88k saved state.
+ *
+ * If argument f is given, the stack pointer of each call frame is
+ * printed.
+ */
+void
+db_stack_trace_cmd(
+    db_regs_t *addr,
+    int have_addr,
+    db_expr_t count,
+    char *modif)
+{
+    enum { Default, Stack, Proc, Frame } style = Default;
+    db_regs_t frame; /* a m88100_saved_state */
+    db_regs_t *regs;
+    union {
+       db_regs_t *frame;
+       struct proc *proc;
+       unsigned num;
+    } arg;
+    arg.frame = addr;
+
+    trace_flags = 0; /* flags will be set via modifers */
+
+    while (modif && *modif) {
+        switch (*modif++)
+        {
+         case 'd':
+           #ifdef TRACE_DEBUG
+               trace_flags |= TRACE_DEBUG_FLAG;
+           #else
+               db_printtf("<debug trace not compiled in, ignoring>\n");
+           #endif
+           break;
+
+         case 's': style = Stack  ; break;
+         case 'f': style = Frame  ; break;
+         case 'p': trace_flags |= TRACE_SHOWCALLPRESERVED_FLAG; break;
+         case 'a': trace_flags |= TRACE_SHOWADDRESS_FLAG; break;
+         case 'F': trace_flags |= TRACE_SHOWFRAME_FLAG; break;
+         case 'u': trace_flags |= TRACE_USER_FLAG; break;
+         default:
+           db_printf("unknown trace modifier [%c]\n", modif[-1]);
+           /*FALLTHROUGH*/
+         case 'h':
+           db_printf("usage: trace/[MODIFIER]  [ARG]\n");
+           db_printf("  u = include user trace\n");
+           db_printf("  F = print stack frames\n");
+           db_printf("  a = show return addresses\n");
+           db_printf("  p = show call-preserved registers\n");
+           db_printf("  s = ARG is a stack pointer\n");
+           db_printf("  f = ARG is a frame pointer\n");
+           #ifdef TRACE_DEBUG
+               db_printf("  d = trace-debugging output\n");
+           #endif
+           return;
+       }
+    }
+
+    if (!have_addr && style != Default) {
+       db_printf("expecting argument with /s or /f\n");
+       return;
+    }
+    if (have_addr && style == Default)
+       style = Proc;
+
+    switch(style)
+    {
+      case Default:
+       regs = DDB_REGS;
+       break;
+
+      case Frame:
+       regs = arg.frame;
+       break;
+
+      case Stack:
+      {
+       unsigned val1, val2, sxip;
+       unsigned ptr;
+       bzero((void*)&frame, sizeof(frame));
+       #define REASONABLE_FRAME_DISTANCE 2048
+
+       /*
+        * We've got to find the top of a stack frame so we can get both
+        * a PC and and real SP.
+        */
+       for (ptr = arg.num;/**/; ptr += 4) {
+           /* Read a word from the named stack */
+           if (db_trace_get_val(ptr, &val1) == 0) {
+               db_printf("can't read from %x, aborting.\n", ptr);
+               return;
+           }
+
+           /*
+            * See if it's a frame pointer.... if so it will be larger than
+            * the address it was taken from (i.e. point back up the stack)
+            * and we'll be able to read where it points.
+            */
+           if (val1 <= ptr ||
+               (val1 & 3)  ||
+               val1 > (ptr + REASONABLE_FRAME_DISTANCE))
+                   continue;
+
+           /* peek at the next word to see if it could be a return address */
+           if (db_trace_get_val(ptr, &sxip) == 0) {
+               db_printf("can't read from %x, aborting.\n", ptr);
+               return;
+           }
+           if (sxip == 0 || !db_trace_get_val(sxip, &val2))
+               continue;
+
+           if (db_trace_get_val(val1, &val2) == 0) {
+               db_printf("can't read from %x, aborting.\n", val1);
+               continue;
+           }
+
+           /*
+            * The value we've just read will be either another frame pointer,
+            * or the start of another exception frame.
+            */
+           if (
+               #ifdef JEFF_DEBUG
+                   val2 == 0
+               #else
+                   val2 == 0x12345678
+               #endif
+               && db_trace_get_val(val1-4, &val2) && val2 == val1
+               && db_trace_get_val(val1-8, &val2) && val2 == val1)
+           {
+                   /* we've found a frame, so the stack must have been good */
+                   db_printf("%x looks like a frame, accepting %x\n",val1,ptr);
+                   break;
+           }
+
+           if (val2 > val1 && (val2 & 3) == 0) {
+               /* well, looks close enough to be another frame pointer */
+               db_printf("*%x = %x looks like a stack frame pointer, accepting %x\n", val1, val2, ptr);
+               break;
+           }
+       }
+
+       frame.r[31] = ptr;
+       frame.epsr = 0x800003f0U;
+       frame.sxip = sxip | 2;
+       frame.snip = frame.sxip + 4;
+       frame.sfip = frame.snip + 4;
+db_printf("[r31=%x, sxip=%x]\n", frame.r[31], frame.sxip);
+       regs = &frame;
+      }
+    }
+
+    db_stack_trace_cmd2(regs);
+}
diff --git a/sys/arch/mvme88k/dev/bugtty.c b/sys/arch/mvme88k/dev/bugtty.c
new file mode 100644 (file)
index 0000000..0eeafd3
--- /dev/null
@@ -0,0 +1,502 @@
+/*     $NetBSD$ */
+
+/*
+ * Copyright (c) 1995 Dale Rahn.
+ * 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 Dale Rahn.
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/queue.h>
+#include <dev/cons.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+
+#include "bugtty.h"
+
+int bugttymatch __P((struct device *parent, void *self, void *aux));
+void bugttyattach __P((struct device *parent, struct device *self, void *aux));
+
+struct cfattach bugtty_ca = {
+        sizeof(struct device), bugttymatch, bugttyattach
+};      
+
+struct cfdriver bugtty_cd = {
+        NULL, "bugtty", DV_TTY, 0
+};
+
+/* prototypes */
+int bugttycnprobe __P((struct consdev *cp));
+int bugttycninit __P((struct consdev *cp));
+int bugttycngetc __P((dev_t dev));
+int bugttycnputc __P((dev_t dev, char c));
+
+int bugttyopen __P((dev_t dev, int flag, int mode, struct proc *p));
+int bugttyclose __P((dev_t dev, int flag, int mode, struct proc *p));
+int bugttyread __P((dev_t dev, struct uio *uio, int flag));
+int bugttywrite __P((dev_t dev, struct uio *uio, int flag));
+int bugttyioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
+int bugttystop __P((struct tty *tp, int flag));
+
+#define DIALOUT(x) ((x) & 0x80)
+#define SWFLAGS(dev) (bugttyswflags | (DIALOUT(dev) ? TIOCFLAG_SOFTCAR : 0))
+
+#define BUGBUF 80
+char bugtty_ibuffer[BUGBUF+1];
+volatile char *pinchar = bugtty_ibuffer;
+char bug_obuffer[BUGBUF+1];
+
+#define bugtty_tty bugttytty
+struct tty *bugtty_tty[NBUGTTY];
+int needprom = 1;
+
+int
+bugttymatch(parent, self, aux)
+       struct device *parent;
+       void *self;
+       void *aux;
+{
+       extern int needprom;
+       struct confargs *ca = aux;
+       
+       if (needprom == 0)
+               return (0);
+       /*
+        * tell our parent our requirements
+        */
+       ca->ca_paddr = (caddr_t)0xfff45000;
+       ca->ca_size = 0x200;
+       ca->ca_ipl = IPL_TTY;
+       return (1);
+}
+
+void
+bugttyattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       printf("\n");
+}
+
+#define BUGTTYUNIT(x) ((x) & (0x7f))
+void bugttyoutput __P((struct tty *tp));
+
+int bugttydefaultrate = TTYDEF_SPEED;
+int bugttyswflags;
+
+int
+bugttymctl(dev, bits, how)
+       dev_t dev;
+       int bits, how;
+{
+       static int settings = TIOCM_DTR | TIOCM_RTS |
+           TIOCM_CTS | TIOCM_CD | TIOCM_DSR;
+       int s;
+
+       /*printf("mctl: dev %x, bits %x, how %x,",dev, bits, how);*/
+
+       /* settings are currently ignored */
+       s = spltty();
+       switch (how) {
+       case DMSET:
+               break;
+       case DMBIC:
+               break;
+       case DMBIS:
+               break;
+       case DMGET:
+               break;
+       }
+       (void)splx(s);
+
+       bits = 0;
+       /* proper defaults? */
+       bits |= TIOCM_DTR;
+       bits |= TIOCM_RTS;
+       bits |= TIOCM_CTS;
+       bits |= TIOCM_CD;
+       /* bits |= TIOCM_RI; */
+       bits |= TIOCM_DSR;
+
+       /* printf("retbits %x\n", bits); */
+       return (bits);
+}
+
+int
+bugttyopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       int s, unit = BUGTTYUNIT(dev);
+       struct tty *tp;
+       extern int needprom;
+
+       if (needprom == 0)
+               return (ENODEV);
+
+       s = spltty();
+       if (bugtty_tty[unit]) {
+               tp = bugtty_tty[unit];
+       } else {
+               tp = bugtty_tty[unit] = ttymalloc();
+       }
+       tp->t_oproc = bugttyoutput;
+       tp->t_param = NULL;
+       tp->t_dev = dev;
+
+       if ((tp->t_state & TS_ISOPEN) == 0) {
+               tp->t_state |= TS_WOPEN;
+               ttychars(tp);
+               if (tp->t_ispeed == 0) {
+                       /*
+                        * only when cleared do we reset to defaults.
+                        */
+                       tp->t_iflag = TTYDEF_IFLAG;
+                       tp->t_oflag = TTYDEF_OFLAG;
+                       tp->t_cflag = TTYDEF_CFLAG;
+                       tp->t_lflag = TTYDEF_LFLAG;
+                       tp->t_ispeed = tp->t_ospeed = bugttydefaultrate;
+               }
+               /* bugtty does not have carrier */
+               tp->t_cflag |= CLOCAL;
+               /*
+                * do these all the time
+                */
+               if (bugttyswflags & TIOCFLAG_CLOCAL)
+                       tp->t_cflag |= CLOCAL;
+               if (bugttyswflags & TIOCFLAG_CRTSCTS)
+                       tp->t_cflag |= CRTSCTS;
+               if (bugttyswflags & TIOCFLAG_MDMBUF)
+                       tp->t_cflag |= MDMBUF;
+               bugttyparam(tp, &tp->t_termios);
+               ttsetwater(tp);
+
+               (void)bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
+               /*
+               if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) ||
+                   (bugttymctl(dev, 0, DMGET) & TIOCM_CD))
+                       tp->t_state |= TS_CARR_ON;
+               else
+                       tp->t_state &= ~TS_CARR_ON;
+               */
+               tp->t_state |= TS_CARR_ON;
+       } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
+               splx(s);
+               return (EBUSY);
+       }
+
+       /*
+        * if NONBLOCK requested, ignore carrier
+        */
+/*
+       if (flag & O_NONBLOCK)
+               goto done;
+*/
+
+       splx(s);
+       /*
+        * Reset the tty pointer, as there could have been a dialout
+        * use of the tty with a dialin open waiting.
+        */
+       tp->t_dev = dev;
+       return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+int
+bugttyparam()
+{
+       return (0);
+}
+
+void
+bugttyoutput(tp)
+       struct tty *tp;
+{
+       int cc, s, unit, cnt ;
+
+       /* only supports one unit */
+
+       if ((tp->t_state & TS_ISOPEN) == 0)
+               return;
+
+       s = spltty();
+       cc = tp->t_outq.c_cc;
+       while (cc > 0) {
+               cnt = min(BUGBUF, cc);
+               cnt = q_to_b(&tp->t_outq, bug_obuffer, cnt);
+               bugoutstr(bug_obuffer, &bug_obuffer[cnt]);
+               cc -= cnt;
+       }
+       splx(s);
+}
+
+int
+bugttyclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       int unit = BUGTTYUNIT(dev);
+       struct tty *tp = bugtty_tty[unit];
+
+       (*linesw[tp->t_line].l_close)(tp, flag);
+
+       ttyclose(tp);
+#if 0
+       bugtty_tty[unit] = NULL;
+#endif
+       return (0);
+}
+
+int
+bugttyread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       struct tty *tp;
+
+       if ((tp = bugtty_tty[BUGTTYUNIT(dev)]) == NULL)
+               return (ENXIO); 
+       return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+#if 1
+/* only to be called at splclk() */
+bugtty_chkinput()
+{
+       struct tty *tp;
+
+       tp = bugtty_tty[0]; /* Kinda ugly hack */
+       if (tp == NULL )
+               return;
+
+       if (buginstat()) {
+               while (buginstat()) {
+                       u_char c = buginchr() & 0xff;
+                       (*linesw[tp->t_line].l_rint)(c, tp);
+               }
+               /*
+               wakeup(tp);
+               */
+       }
+}
+#endif
+
+int
+bugttywrite(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+#if 0
+       /* bypass tty output routines. */
+       int i, cnt, s;
+       int oldoff;
+
+       s = spltty();
+       oldoff = uio->uio_offset;
+       do  {
+               uiomove(bug_obuffer, BUGBUF, uio);
+               bugoutstr(bug_obuffer, &bug_obuffer[uio->uio_offset - oldoff]);
+               oldoff = uio->uio_offset;
+       } while (uio->uio_resid != 0);
+       splx(s);
+
+       return (0);
+#else
+       struct tty *tp;
+       if((tp = bugtty_tty[BUGTTYUNIT(dev)]) == NULL)
+               return (ENXIO);
+       return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+#endif
+}
+
+int
+bugttyioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       int unit = BUGTTYUNIT(dev);
+       struct tty *tp = bugtty_tty[unit];
+       int error;
+
+       if (!tp)
+               return (ENXIO);
+
+       error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+       if (error >= 0) 
+               return (error);
+
+       error = ttioctl(tp, cmd, data, flag, p);
+       if (error >= 0)
+               return (error);
+
+       switch (cmd) {
+       case TIOCSBRK:
+               /* */
+               break;
+
+       case TIOCCBRK:
+               /* */
+               break;
+
+       case TIOCSDTR:
+               (void) bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
+               break;
+
+       case TIOCCDTR:
+               (void) bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
+               break;
+
+       case TIOCMSET:
+               (void) bugttymctl(dev, *(int *) data, DMSET);
+               break;
+
+       case TIOCMBIS:
+               (void) bugttymctl(dev, *(int *) data, DMBIS);
+               break;
+
+       case TIOCMBIC:
+               (void) bugttymctl(dev, *(int *) data, DMBIC);
+               break;
+
+       case TIOCMGET:
+               *(int *)data = bugttymctl(dev, 0, DMGET);
+               break;
+       case TIOCGFLAGS:
+               *(int *)data = SWFLAGS(dev);
+               break;
+       case TIOCSFLAGS:
+               error = suser(p->p_ucred, &p->p_acflag); 
+               if (error != 0)
+                       return (EPERM); 
+
+               bugttyswflags = *(int *)data;
+               bugttyswflags &= /* only allow valid flags */
+                   (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
+               break;
+       default:
+               return (ENOTTY);
+       }
+
+       return (0);
+}
+
+int
+bugttystop(tp, flag)
+       struct tty *tp;
+       int flag;
+{
+       int s;
+
+       s = spltty();
+       if (tp->t_state & TS_BUSY) {
+               if ((tp->t_state & TS_TTSTOP) == 0)
+                       tp->t_state |= TS_FLUSH;
+       }
+       splx(s);
+       return (0);
+}
+
+/*
+ * bugtty is the last possible choice for a console device.
+ */
+int
+bugttycnprobe(cp)
+       struct consdev *cp;
+{
+       int maj;
+       extern int needprom;
+
+       if (needprom == 0) {
+               cp->cn_pri = CN_DEAD;
+               return (0);
+       }
+               
+#if 0
+       switch (cputyp) {
+       case CPU_147:
+       case CPU_162:
+               cp->cn_pri = CN_NORMAL;
+               return (0);
+       default:
+               break;
+       }
+#else
+       cp->cn_pri = CN_NORMAL;
+       return (0);
+#endif /* 0 */
+
+       /* locate the major number */
+       for (maj = 0; maj < nchrdev; maj++)
+               if (cdevsw[maj].d_open == bugttyopen)
+                       break;
+
+       cp->cn_dev = makedev(maj, 0);
+       cp->cn_pri = CN_NORMAL;
+
+       return (1);
+}
+
+int
+bugttycninit(cp)
+       struct consdev *cp;
+{
+}
+
+int
+bugttycngetc(dev)
+       dev_t dev;
+{
+       return (buginchr());
+}
+
+int
+bugttycnputc(dev, c)
+       dev_t dev;
+       char c;
+{
+       int s;
+
+       if (c == '\n')
+               bugoutchr('\r');
+       bugoutchr(c);
+}
diff --git a/sys/arch/mvme88k/dev/clock.c b/sys/arch/mvme88k/dev/clock.c
new file mode 100644 (file)
index 0000000..352bc42
--- /dev/null
@@ -0,0 +1,371 @@
+/*     $NetBSD: clock.c,v 1.22 1995/05/29 23:57:15 pk Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1995 Nivas Madhur
+ * Copyright (c) 1994 Gordon W. Ross
+ * Copyright (c) 1993 Adam Glass
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)clock.c     8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Clock driver. Has both interval timer as well as statistics timer.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#ifdef GPROF
+#include <sys/gmon.h>
+#endif
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+
+#include <mvme88k/dev/pcctworeg.h>
+
+/*
+ * Statistics clock interval and variance, in usec.  Variance must be a
+ * power of two.  Since this gives us an even number, not an odd number,
+ * we discard one case and compensate.  That is, a variance of 4096 would
+ * give us offsets in [0..4095].  Instead, we take offsets in [1..4095].
+ * This is symmetric about the point 2048, or statvar/2, and thus averages
+ * to that value (assuming uniform random numbers).
+ */
+int statvar = 8192;
+int statmin;                   /* statclock interval - 1/2*variance */
+int timerok;
+
+u_long delay_factor = 1;
+
+static int     clockmatch __P((struct device *, void *, void *));
+static void    clockattach __P((struct device *, struct device *, void *));
+int            clockintr __P((void *, void *));
+int            statintr __P((void *, void *));
+
+struct clocksoftc {
+       struct device                   sc_dev;
+       volatile struct pcc2reg         *sc_pcc2reg;
+};
+
+struct cfattach clock_ca = {
+        sizeof(struct clocksoftc), clockmatch, clockattach
+}; 
+struct cfdriver clock_cd = { 
+        NULL, "clock", DV_DULL, 0
+}; 
+
+struct intrhand clockintrhand, statintrhand;
+
+static int
+clockmatch(struct device *parent, void *self, void *aux)
+{
+       register struct confargs *ca = aux;
+       register struct cfdata *cf = self;
+
+       if (ca->ca_bustype != BUS_PCCTWO ||
+               strcmp(cf->cf_driver->cd_name, "clock")) {
+               return (0);
+       }
+
+       /*
+        * clock has to be at ipl 5
+        * We return the ipl here so that the parent can print
+        * a message if it is different from what ioconf.c says.
+        */
+       ca->ca_ipl   = IPL_CLOCK;
+       /* set size to 0 - see pcctwo.c:match for details */
+       ca->ca_size  = 0;
+
+       return 1;
+}
+
+/* ARGSUSED */
+static void
+clockattach(struct device *parent, struct device *self, void *aux)
+{
+       struct confargs *ca = aux;
+       struct clocksoftc *sc = (struct clocksoftc *)self;
+       u_long  elapsedtime;
+
+       extern void delay(u_long);
+       extern int cpuspeed;
+
+       /*
+        * save virtual address of the pcc2 block since our
+        * registers are in that block.
+        */
+       sc->sc_pcc2reg = (struct pcc2reg *)ca->ca_vaddr;
+
+       /*
+        * calibrate for delay() calls.
+        * We do this by using tick timer1 in free running mode before
+        * cpu_initclocks() is called so turn on clock interrupts etc.
+        * 
+        *      the approach is:
+        *              set count in timer to 0
+        *              call delay(1000) for a 1000 us delay
+        *              after return, stop count and figure out
+        *                      how many us went by (call it x)
+        *              now the factor to multiply the arg. passed to
+        *              delay would be (x/1000) rounded up to an int.
+        */
+       printf("\n");
+       sc->sc_pcc2reg->pcc2_t1ctl      &= ~PCC2_TICTL_CEN;
+       sc->sc_pcc2reg->pcc2_psclkadj   = 256 - cpuspeed;
+       sc->sc_pcc2reg->pcc2_t1irq      &= ~PCC2_TTIRQ_IEN;
+       sc->sc_pcc2reg->pcc2_t1cntr     = 0;
+       sc->sc_pcc2reg->pcc2_t1ctl      |= PCC2_TICTL_CEN;
+       delay(1000);    /* delay for 1 ms */
+       sc->sc_pcc2reg->pcc2_t1ctl      &= ~PCC2_TICTL_CEN;
+       elapsedtime = sc->sc_pcc2reg->pcc2_t1cntr;
+
+       delay_factor = (u_long)(elapsedtime / 1000 + 1);
+
+       /*
+        * program clock to interrupt at IPL_CLOCK. Set everything
+        * except compare registers, interrupt enable and counter
+        * enable registers.
+        */
+       sc->sc_pcc2reg->pcc2_t1ctl &= ~(PCC2_TICTL_CEN);
+       sc->sc_pcc2reg->pcc2_t1cntr= 0;
+       sc->sc_pcc2reg->pcc2_t1ctl |= (PCC2_TICTL_COC|PCC2_TICTL_COVF);
+       sc->sc_pcc2reg->pcc2_t1irq = (PCC2_TTIRQ_ICLR|IPL_CLOCK);
+
+       sc->sc_pcc2reg->pcc2_t2ctl &= ~(PCC2_TICTL_CEN);
+       sc->sc_pcc2reg->pcc2_t2cntr= 0;
+       sc->sc_pcc2reg->pcc2_t2ctl |= (PCC2_TICTL_COC|PCC2_TICTL_COVF);
+       sc->sc_pcc2reg->pcc2_t2irq = (PCC2_TTIRQ_ICLR|IPL_CLOCK);
+
+       /*
+        * Establish inerrupt handlers.
+        */
+       clockintrhand.ih_fn = clockintr;
+       clockintrhand.ih_arg = 0; /* don't want anything */
+       clockintrhand.ih_ipl = IPL_CLOCK;
+       clockintrhand.ih_wantframe = 1;
+       intr_establish(PCC2_VECT+9, &clockintrhand);
+
+       statintrhand.ih_fn = statintr;
+       statintrhand.ih_arg = 0; /* don't want anything */
+       statintrhand.ih_ipl = IPL_CLOCK;
+       statintrhand.ih_wantframe = 1;
+       intr_establish(PCC2_VECT+8, &statintrhand);
+
+       timerok = 1;
+}
+
+/*
+ * Set up the real-time and statistics clocks.  Leave stathz 0 only if
+ * no alternative timer is available. mvme167/mvme187 has 2 tick timers
+ * in pcc2 - we are using timer 1 for clock interrupt and timer 2 for
+ * statistics.
+ *
+ * The frequencies of these clocks must be an even number of microseconds.
+ */
+cpu_initclocks()
+{
+       register int statint, minint;
+       volatile struct pcc2reg *pcc2reg;
+
+       pcc2reg = ((struct clocksoftc *)clock_cd.cd_devs[0])->sc_pcc2reg;
+
+       if (1000000 % hz) {
+               printf("cannot get %d Hz clock; using 100 Hz\n", hz);
+               hz = 100;
+               tick = 1000000 / hz;
+       }
+       if (stathz == 0)
+               stathz = hz;
+       if (1000000 % stathz) {
+               printf("cannot get %d Hz statclock; using 100 Hz\n", stathz);
+               stathz = 100;
+       }
+       profhz = stathz;                /* always */
+
+       statint = 1000000 / stathz;
+       minint = statint / 2 + 100;
+       while (statvar > minint)
+               statvar >>= 1;
+       /*
+        * hz value 100 means we want the clock to interrupt 100
+        * times a sec or 100 times in 1000000 us ie, 1 interrupt
+        * every 10000 us. Program the tick timer compare register
+        * to this value.
+        */
+       pcc2reg->pcc2_t1cmp = tick;
+       pcc2reg->pcc2_t2cmp = statint;
+       statmin = statint - (statvar >> 1);
+
+       /* start the clocks ticking */
+       pcc2reg->pcc2_t1ctl = (PCC2_TICTL_CEN|PCC2_TICTL_COC|PCC2_TICTL_COVF);
+       pcc2reg->pcc2_t2ctl = (PCC2_TICTL_CEN|PCC2_TICTL_COC|PCC2_TICTL_COVF);
+       /* and enable those interrupts */
+       pcc2reg->pcc2_t1irq |= (PCC2_TTIRQ_IEN|PCC2_TTIRQ_ICLR);
+       pcc2reg->pcc2_t2irq |= (PCC2_TTIRQ_IEN|PCC2_TTIRQ_ICLR);
+}
+
+/*
+ * Dummy setstatclockrate(), since we know profhz==hz.
+ */
+/* ARGSUSED */
+void
+setstatclockrate(int newhz)
+{
+       /* nothing */
+}
+
+/*
+ * Delay: wait for `about' n microseconds to pass.
+ */
+void
+delay(volatile u_long n)
+{
+       volatile u_long cnt = n * delay_factor;
+
+       while (cnt-- > 0) {
+               asm volatile("");
+       }
+}
+
+/*
+ * Clock interrupt handler. Calls hardclock() after setting up a
+ * clockframe.
+ */
+int
+clockintr(void *cap, void *frame)
+{
+       volatile struct pcc2reg *reg;
+
+       reg = ((struct clocksoftc *)clock_cd.cd_devs[0])->sc_pcc2reg;
+       
+       /* Clear the interrupt */
+       reg->pcc2_t1irq = (PCC2_TTIRQ_IEN|PCC2_TTIRQ_ICLR|IPL_CLOCK);
+#if 0
+       reg->pcc2_t1irq |= PCC2_TTIRQ_ICLR;
+#endif /* 0 */
+
+       hardclock((struct clockframe *)frame);
+#include "bugtty.h"
+#if NBUGTTY > 0
+       bugtty_chkinput();
+#endif /* NBUGTTY */
+
+       return (1);
+}
+
+/*
+ * Stat clock interrupt handler.
+ */
+int
+statintr(void *cap, void *frame)
+{
+       volatile struct pcc2reg *reg;
+       register u_long newint, r, var;
+
+       reg = ((struct clocksoftc *)clock_cd.cd_devs[0])->sc_pcc2reg;
+       
+       /* Clear the interrupt */
+#if 0
+       reg->pcc2_t2irq |= PCC2_TTIRQ_ICLR;
+#endif /* 0 */
+       reg->pcc2_t2irq = (PCC2_TTIRQ_IEN|PCC2_TTIRQ_ICLR|IPL_CLOCK);
+
+       statclock((struct clockframe *)frame);
+
+       /*
+        * Compute new randomized interval.  The intervals are uniformly
+        * distributed on [statint - statvar / 2, statint + statvar / 2],
+        * and therefore have mean statint, giving a stathz frequency clock.
+        */
+       var = statvar;
+       do {
+               r = random() & (var - 1);
+       } while (r == 0);
+       newint = statmin + r;
+
+       /*
+        * reprogram statistics timer to interrupt at
+        * newint us intervals.
+        */
+       reg->pcc2_t2ctl = ~(PCC2_TICTL_CEN);
+       reg->pcc2_t2cntr = 0;
+       reg->pcc2_t2cmp = newint;
+       reg->pcc2_t2ctl = (PCC2_TICTL_CEN|PCC2_TICTL_COC|PCC2_TICTL_COVF);
+       reg->pcc2_t2irq |= (PCC2_TTIRQ_ICLR|PCC2_TTIRQ_IEN);
+
+       return (1);
+}
+
+/*
+ * Return the best possible estimate of the time in the timeval
+ * to which tvp points.  We do this by returning the current time
+ * plus the amount of time since the last clock interrupt.
+ *
+ * Check that this time is no less than any previously-reported time,
+ * which could happen around the time of a clock adjustment.  Just for
+ * fun, we guarantee that the time will be greater than the value
+ * obtained by a previous call.
+ */
+void
+microtime(tvp)
+       register struct timeval *tvp;
+{
+       int s;
+       static struct timeval lasttime;
+
+       s = splhigh();
+       *tvp = time;
+       while (tvp->tv_usec > 1000000) {
+               tvp->tv_sec++;
+               tvp->tv_usec -= 1000000;
+       }
+       if (tvp->tv_sec == lasttime.tv_sec &&
+           tvp->tv_usec <= lasttime.tv_usec &&
+           (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
+               tvp->tv_sec++;
+               tvp->tv_usec -= 1000000;
+       }
+       lasttime = *tvp;
+       splx(s);
+}
diff --git a/sys/arch/mvme88k/dev/pcc2.c b/sys/arch/mvme88k/dev/pcc2.c
new file mode 100644 (file)
index 0000000..c78cbb2
--- /dev/null
@@ -0,0 +1,253 @@
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <machine/cpu.h>
+#include <machine/pcc2.h>
+
+int    m1x7pccprobe(struct device *parent, struct cfdata *self, void *aux);
+void   m1x7pccattach(struct device *parent, struct device *self, void *aux);
+
+int abort_handler();
+extern void abort_intrv();
+extern void pcc_intrv();
+extern int intrh_debug;
+extern int machineid;
+extern void badtrap();
+extern int submatch( struct device *parent, struct cfdata *self, void *aux);
+/* static */ u_int *pcc_io_base;
+static u_int *pcc_vector_base;
+
+static void abort_setup();
+void timer2_intr();
+
+struct pcctwosoftc {
+       struct device   sc_dev;
+       caddr_t         sc_vaddr;
+       caddr_t         sc_paddr;
+       struct pcctworeg *sc_pcc2;
+};
+
+void pcctwoattach __P((struct device *, struct device *, void *));
+int  pcctwoprobe __P((struct device *, void *, void *));
+int  pcctwoabort __P((struct frame *));
+
+struct cfdriver pcctwocd = {
+       NULL, "pcctwo", pcctwomatch, pcctwoattach,
+       DV_DULL, sizeof(struct pcctwosoftc), 0
+};
+
+struct pcctworeg *sys_pcc2 = NULL;
+
+int
+pcctwomatch(struct device *parent, struct cfdata *self, void *aux)
+{
+#if defined(__m88k__)
+       if (machineid == 0x187) {
+               return 1;
+       }
+#endif
+       return 0;
+}
+
+void
+pcctwoattach(struct device *parent, struct device *self, void *aux)
+{
+       struct cfdata *cf;
+       volatile char *ibvr;    /* Interrupt Base Vector Register */
+       u_int ibv;              /* Interrupt Base Vector, offset from vbr */
+       u_int *iv;              /* interupt vector */
+       int i;
+       u_int vector_base;
+
+       /* attach memory mapped io space */
+       /* map 0xfffe1000 - 0xfffe102f, 0xfffe2800 */
+       /* ppc_io_base = mmio(0xfffe1000, 1800, PG_RW|PG_CI); */
+       pcc_io_base = 0xfffe1000; /* should really be return of virtmem alloc */
+       /* set PCC vector base */
+       ibv = PCC_IBVR(pcc_io_base) & 0xf0;
+       ibvr = &PCC_IBVR(pcc_io_base);
+       printf("pcc:ibvr %x *ibvr %x ibv %x\n",ibvr,*ibvr, ibv);
+       pcc_vector_base =  (u_int *)ibv;
+       asm volatile ("movec vbr,%0": "=d" (vector_base));
+       printf("pcc:vector_base %x\n",vector_base);
+       /* register "standard interupt handlers */
+
+       abort_setup();
+       iv = (u_int *)(vector_base + (ibv * 4));
+printf("iv %x\n",iv);
+       for (i = 0; i <= SOFT2_VECTOR; i++) {
+               iv[i] = (u_int)pcc_intrv;
+       }
+       /*
+       timer2_setup();
+       */
+       iv = (u_int *)(vector_base + (ibv + TICK2_VECTOR) * 4);
+       *iv = (u_int)&pcc_intrv;
+
+#ifdef DEBUG
+       if (intrh_debug)
+               pr_intrh();
+#endif
+       if ((cf = config_search(submatch, self, aux)) != NULL) {
+               return;
+       }
+       return ;
+}
+asm (" .text");
+asm (" .global _pcc_intrv");
+asm ("_pcc_intrv:");
+asm (" link a6,#0");
+asm (" movml a0/a1/d0/d1,sp@-");
+asm (" movel a6,a0");
+asm (" addql #4,a0");
+asm (" movel a0,sp@-");
+asm (" jbsr  _pcc_handler");
+asm (" addql #4,sp");
+asm (" movml sp@+,a0/a1/d0/d1");
+asm (" unlk a6");
+asm (" jra rei");
+
+asm (" .global _abort_intrv");
+asm ("_abort_intrv:");
+asm (" movml a0/a1/d0/d1,sp@-");
+asm (" jbsr  _abort_handler");
+asm (" movml sp@+,a0/a1/d0/d1");
+asm (" jra rei");
+/* asm ("      .previous"); */
+
+void *m147le_arg;
+void
+pcc_handler(struct exception_frame *except)
+{
+       u_int vector;
+       int handled = 0;
+
+#if 0
+       printf("except %x\n",except);
+       printf("sr %x\n",except->sr);
+       printf("pc %x\n",except->pc);
+       printf("type %x\n",except->type);
+#endif
+       vector = except->vo;
+/*     printf("vector %x\n",vector); */
+       vector = (vector/4 - (u_int)pcc_vector_base);
+/*     printf("vector %x\n",vector); */
+
+       switch (vector) {
+       case AC_FAIL_VECTOR:
+               printf("ac_fail vector\n");
+               break;
+       case BERR_VECTOR:
+               printf("berr vector\n");
+               printf("pcc_handler:invalid vector %x\n",vector);
+               break;
+       case ABORT_VECTOR:
+               printf("abort vector\n");
+               abort_handler();
+               handled = 1;
+               break;
+       case SERIAL_VECTOR:
+               printf("serial vector\n");
+               PCC_SERIAL_ICR(0xfffe1000) = 0;
+               break;
+       case LANCE_VECTOR:
+               leintr(m147le_arg);
+               handled = 1;
+               break;
+       case SCSIPORT_VECTOR:
+               printf("scsiport vector\n");
+               m147sc_scintr();
+               break;
+       case SCSIDMA_VECTOR:
+               printf("scsidma vector\n");
+               m147sc_dmaintr();
+               break;
+       case PRINTER_VECTOR:
+               printf("printer vector\n");
+               break;
+       case TICK1_VECTOR:
+               printf("tick1 vector\n");
+               printf("pcc_handler:invalid vector %x\n",vector);
+               break;
+       case TICK2_VECTOR:
+               timer2_intr(except);
+               handled = 1;
+               break;
+       case SOFT1_VECTOR:
+               printf("soft1 vector\n");
+               break;
+       case SOFT2_VECTOR:
+               printf("soft2 vector\n");
+               break;
+       default:
+               printf("pcc_handler:invalid vector %x\n",vector);
+       }
+       
+       if (handled == 0) {
+               printf("except %x\n",except);
+               printf("sr %x\n",except->sr);
+               printf("pc %x\n",except->pc);
+               printf("type %x\n",except->type);
+       }
+}
+
+
+int
+abort_handler()
+{
+       printf("aicr = 0x%x\n",PCC_ABRT_ICR(pcc_io_base));
+       PCC_ABRT_ICR(pcc_io_base) = 0x88;
+       printf("aicr = 0x%x\n",PCC_ABRT_ICR(pcc_io_base));
+       Debugger();
+       return 0;
+}
+static void abort_setup()
+{
+       printf("PCC_ABRT_ICR %x\n",&PCC_ABRT_ICR(pcc_io_base));
+       printf("aicr = 0x%x\n",PCC_ABRT_ICR(pcc_io_base));
+       PCC_ABRT_ICR(pcc_io_base) = 0x88;
+       printf("aicr = 0x%x\n",PCC_ABRT_ICR(pcc_io_base));
+}
+
+/* timer2 (clock) driver */
+
+/*const u_int timer_reload = 0;  /* .4096 sec ? */
+/* const u_int timer_reload = 62870;  1/60 sec ? */
+const u_int timer_reload = 63936;  /* 1/100 sec ? */
+
+#if 0
+void
+timer2_setup()
+{
+       u_int *io_base;
+       pcc_io_base = 0xfffe1000; /* should really be return of virtmem alloc */
+       io_base = pcc_io_base;
+       printf("pcc_io_base %x io_base %x\n",pcc_io_base, io_base);
+       printf("PCC_TIMER2_PRE %x\n",&PCC_TIMER2_PRE(io_base));
+       printf("PCC_TIMER2_CTR %x\n",&PCC_TIMER2_CTR(io_base));
+       printf("PCC_TIMER2_ICR %x\n",&PCC_TIMER2_ICR(io_base));
+       PCC_TIMER2_PRE(io_base) = timer_reload;
+       PCC_TIMER2_CTR(io_base) = 0x7;
+       PCC_TIMER2_ICR(io_base) = 0x8e;
+}
+#endif
+void
+timer2_intr(struct exception_frame *except)
+{
+       u_int *io_base;
+       pcc_io_base = 0xfffe1000; /* should really be return of virtmem alloc */
+       io_base = pcc_io_base;
+
+       if (0x80 && PCC_TIMER2_ICR(io_base)) {
+               PCC_TIMER2_ICR(io_base) = 0x8e;
+               /* hardclock(); */
+               hardclock(except);
+
+       } else {
+               printf("timer2_intr: vector called without interrupt\n");
+       }
+       /* REALLY UGLY  HACK */
+       bugtty_chkinput();
+
+       return;
+}
diff --git a/sys/arch/mvme88k/dev/pcctwo.c b/sys/arch/mvme88k/dev/pcctwo.c
new file mode 100644 (file)
index 0000000..7ad4c3a
--- /dev/null
@@ -0,0 +1,210 @@
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+
+#include <mvme88k/dev/pcctworeg.h>
+
+struct pcctwosoftc {
+       struct device           sc_dev;
+       volatile struct pcc2reg *sc_pcc2reg;
+};
+
+int    pcctwomatch     __P((struct device *, void *, void *));
+int    pcctwoscan      __P((struct device *, void *, void *));
+void   pcctwoattach    __P((struct device *, struct device *, void *));
+
+#ifdef MVME187
+void   setupiackvectors __P((void));
+#endif /* MVME187 */
+
+struct cfattach pcctwo_ca = { 
+        sizeof(struct pcctwosoftc), pcctwomatch, pcctwoattach
+};
+
+struct cfdriver pcctwo_cd = {
+        NULL, "pcctwo", DV_DULL, 0
+}; 
+
+/*ARGSUSED*/
+int
+pcctwomatch(struct device *parent, void *self, void *aux)
+{
+       int             ret;
+       u_char          id, rev; 
+       caddr_t         base;
+       struct confargs *ca = aux;
+       struct cfdata *cf = self;
+       
+#if 0
+       if (cputyp != CPU_167 && cputyp != CPU_166
+#ifdef MVME187
+               && cputyp != CPU_187
+#endif
+               )
+       {
+               return 0;
+       }
+#endif /* 0 */
+       if (cputyp != CPU_187) {
+               return 0;
+       }
+       
+       /* 
+        * If bus or name do not match, fail.
+        */
+       if (ca->ca_bustype != BUS_MAIN ||
+               strcmp(cf->cf_driver->cd_name, "pcctwo")) {
+               return 0;
+       }
+
+       if ((base = (caddr_t)cf->cf_loc[0]) == (caddr_t)-1) {
+               return 0;
+       }
+
+       id  = badpaddr(base, 1);
+       rev = badpaddr(base + 1, 1);
+
+       if (id != PCC2_CHIP_ID || rev != PCC2_CHIP_REV) {
+               return 0;
+       }
+
+       ca->ca_size = PCC2_SIZE;
+       ca->ca_paddr = base;
+
+       return 1;
+}
+
+int
+pcctwoprint(void *aux, char *parent)
+{
+       struct confargs *ca = aux;
+
+       /*
+        * We call pcctwoprint() via config_attach(). Parent
+        * will always be null and config_attach() would have already
+        * printed "nvram0 at pcctwo0".
+        */
+       printf(" addr %x size %x", ca->ca_paddr, ca->ca_size);
+       if (ca->ca_ipl != -1) {
+               printf(" ipl %x", ca->ca_ipl);
+       }
+
+       return (UNCONF);
+}
+
+/*ARGSUSED*/
+int
+pcctwoscan(struct device *parent, void *self, void *aux)
+{
+       struct confargs ca;
+       struct cfdata *cf = self;
+       struct pcctwosoftc *sc = (struct pcctwosoftc *)parent;
+
+       /*
+        * Pcctwoscan gets called by config_search() for each
+        * child of parent (pcctwo) specified in ioconf.c.
+        * Fill in the bus type to be PCCTWO and call the child's
+        * match routine. If the child's match returns 1, then
+        * we need to allocate device memory, set it in confargs
+        * and call config_attach(). This, in turn, will call the
+        * child's attach.
+        */
+
+       ca.ca_bustype = BUS_PCCTWO;
+       
+       if ((*cf->cf_attach->ca_match)(parent, cf, &ca) == 0)
+               return 0;
+       
+       /*
+        * The child would have fixed up ca to reflect what its
+        * requirements are.
+        */
+       
+       if (cf->cf_loc[2] != ca.ca_ipl) {
+               printf("Changing ipl %x specified in ioconf.c to %x for %s\n",
+                       cf->cf_loc[2], ca.ca_ipl, cf->cf_driver->cd_name);
+       }
+
+       /*
+        * If the size specified by the child is 0, don't map
+        * any IO space, but pass in the address of pcc2reg as vaddr.
+        * This is for clock and parallel port which don't have a
+        * separate address space by themselves but use pcc2's register
+        * block.
+        */
+       if (ca.ca_size == 0) {
+               /*
+                * pcc2regs addr
+                */
+#if 0
+               ca.ca_vaddr = ((struct confargs *)aux)->ca_vaddr;
+#endif /* 0 */
+               ca.ca_vaddr = (caddr_t)sc->sc_pcc2reg;
+
+       } else  {
+               ca.ca_vaddr = ca.ca_paddr;
+       }
+
+#if 0
+       ca.ca_parent = ((struct confargs *)aux)->ca_vaddr;
+#endif /* 0 */
+       ca.ca_parent = (caddr_t)sc->sc_pcc2reg;
+
+       /*
+        * Call child's attach using config_attach().
+        */
+       config_attach(parent, cf, &ca, pcctwoprint);
+       return 1;
+}
+
+/*
+ * This function calls the match routine of the configured children
+ * in turn. For each configured child, map the device address into
+ * iomap space and then call config_attach() to attach the child.
+ */
+
+/* ARGSUSED */
+void
+pcctwoattach(struct device *parent, struct device *self, void *aux)
+{
+       struct pcctwosoftc      *sc = (struct pcctwosoftc *)self;
+       struct confargs         *ca = aux;
+       caddr_t base;
+
+       if (self->dv_unit > 0) {
+               printf(" unsupported\n");
+               return;
+       }
+
+       base = ca->ca_vaddr;
+
+       printf(": PCCTWO id 0x%2x rev 0x%2x\n",
+               *(u_char *)base, *((u_char *)base + 1));
+
+       /*
+        * mainbus driver would have mapped Pcc2 at base. Save
+        * the address in pcctwosoftc.
+        */
+       sc->sc_pcc2reg = (struct pcc2reg *)base;
+
+       /*
+        * Set pcc2intr_mask and pcc2intr_ipl.
+        */
+       pcc2intr_ipl = (u_char *)&(sc->sc_pcc2reg->pcc2_ipl);
+       pcc2intr_mask = (u_char *)&(sc->sc_pcc2reg->pcc2_imask);
+
+#ifdef MVME187
+       /*
+        * Get mappings for iack vectors. This doesn't belong here
+        * but is more closely related to pcc than anything I can
+        * think of. (could probably do it in locore.s).
+        */
+       
+       setupiackvectors();
+#endif /* MVME187 */
+
+       (void)config_search(pcctwoscan, self, aux);
+}
diff --git a/sys/arch/mvme88k/include/ansi.h b/sys/arch/mvme88k/include/ansi.h
new file mode 100644 (file)
index 0000000..a1d9d66
--- /dev/null
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)ansi.h        8.2 (Berkeley) 1/4/94
+ *      $Id: ansi.h,v 1.3 1997/03/03 20:20:43 rahnds Exp $
+ */
+
+#ifndef        _ANSI_H_
+#define        _ANSI_H_
+
+/*
+ * Types which are fundamental to the implementation and may appear in
+ * more than one standard header are defined here.  Standard headers
+ * then use:
+ *     #ifdef  _BSD_SIZE_T_
+ *     typedef _BSD_SIZE_T_ size_t;
+ *     #undef  _BSD_SIZE_T_
+ *     #endif
+ */
+#define        _BSD_CLOCK_T_   unsigned long           /* clock() */
+#define        _BSD_PTRDIFF_T_ int                     /* ptr1 - ptr2 */
+#define        _BSD_SIZE_T_    unsigned int            /* sizeof() */
+#define        _BSD_SSIZE_T_   int                     /* byte count or error */
+#define        _BSD_TIME_T_    long                    /* time() */
+
+#include "va-m88k.h"
+
+#define _BSD_VA_LIST_  __gnuc_va_list
+
+/*
+ * Runes (wchar_t) is declared to be an ``int'' instead of the more natural
+ * ``unsigned long'' or ``long''.  Two things are happening here.  It is not
+ * unsigned so that EOF (-1) can be naturally assigned to it and used.  Also,
+ * it looks like 10646 will be a 31 bit standard.  This means that if your
+ * ints cannot hold 32 bits, you will be in trouble.  The reason an int was
+ * chosen over a long is that the is*() and to*() routines take ints (says
+ * ANSI C), but they use _RUNE_T_ instead of int.  By changing it here, you
+ * lose a bit of ANSI conformance, but your programs will still work.
+ *    
+ * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type.  When wchar_t
+ * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains
+ * defined for ctype.h.
+ */
+#define        _BSD_WCHAR_T_   int                     /* wchar_t */
+#define        _BSD_RUNE_T_    int                     /* rune_t */
+
+#endif /* _ANSI_H_ */
diff --git a/sys/arch/mvme88k/include/asm.h b/sys/arch/mvme88k/include/asm.h
new file mode 100644 (file)
index 0000000..2c89b9e
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-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.
+ */
+
+#ifndef __M88K_ASM_H__
+#define __M88K_ASM_H__
+
+#ifdef __STDC__
+#      define FUNC(NAME) _##NAME
+#else
+#      define FUNC(NAME) _/**/NAME
+#endif
+
+/* Define EH_DEBUG to be non-zero to compile-in various debugging things */
+#ifndef        EH_DEBUG
+#define EH_DEBUG 0
+#endif EH_DEBUG
+
+/* this gives the offsets into various structures of various elements, etc */
+#include "assym.s"
+
+#define        ENTRY(NAME) \
+    .align 8; .globl FUNC(NAME); FUNC(NAME):
+    
+
+#define  LABEL(name)   name:;  .globl name ;
+/*
+ * _LABEL(name)
+ *     Defines one visible only to the file, unless debugging
+ *     is enabled, in which case it's visible to the world (and
+ *     hence to debuggers, and such).
+ */
+#if EH_DEBUG
+#  define _LABEL(name) name:   .globl name ;
+#else
+#  define _LABEL(name) name:               ;
+#endif
+
+#define RTE    NOP ; rte
+
+#define PID    cr0
+#define PSR    cr1
+#define EPSR   cr2
+#define SSBR   cr3
+#define SXIP   cr4
+#define SNIP   cr5
+#define SFIP   cr6
+#define VBR    cr7
+#define DMT0   cr8
+#define DMD0   cr9
+#define DMA0   cr10
+#define DMT1   cr11
+#define DMD1   cr12
+#define DMA1   cr13
+#define DMT2   cr14
+#define DMD2   cr15
+#define DMA2   cr16
+#define SR0    cr17
+#define SR1    cr18
+#define SR2    cr19
+#define SR3    cr20
+#define FPECR  fcr0
+#define FPHS1  fcr1
+#define FPLS1  fcr2
+#define FPHS2  fcr3
+#define FPLS2  fcr4
+#define FPPT   fcr5
+#define FPRH   fcr6
+#define FPRL   fcr7
+#define FPIT   fcr8
+#define FPSR   fcr62
+#define FPCR   fcr63
+
+/*
+ * At various times, there is the need to clear the pipeline (i.e.
+ * synchronize).  A "tb1 0, r0, foo" will do that (because a trap
+ * instruction always synchronizes, and this particular instruction
+ * will never actually take the trap).
+ */
+#define FLUSH_PIPELINE tb1 0, r0, 0
+#define NOP            or r0, r0, r0
+
+/*
+ * Useful in some situations.
+ * NOTE: If ARG1 or ARG2 are r2 or r3, strange things may happen.  Watch out!
+ */
+#define CALL(NAME, ARG1, ARG2)             \
+               subu    r31, r31, 32    ; \
+                or      r2, r0, ARG1    ; \
+                bsr.n   NAME            ; \
+                or      r3, r0, ARG2   ; \
+               addu    r31, r31, 32
+
+/*
+ * SR1 - CPU FLAGS REGISTER
+ * XXX clean this when the trap handler is reworked. Among the things
+ * I like to see is having the trap frame on the kernel stack instead
+ * of putting in the PCB. If done properly, we don't need SR1 for doing
+ * anything special. nivas
+ * 
+ * SR1 contains flags about the current CPU status.
+ *
+ * The bit FLAG_IGNORE_DATA_EXCEPTION indicates that any data exceptions
+ *     should be ignored (well, at least treated in a special way).
+ * The bit FLAG_INTERRUPT_EXCEPTION indicates that the current exception
+ *     is the interrupt exception.  Such information can be gotten
+ *     in other ways, but having it in the flags makes it easy for the
+ *     exception handler to check quickly.
+ * The bit FLAG_ENABLING_FPU indicates that the exception handler is
+ *     in the process of enabling the FPU (so that an exception can
+ *     be serviced).  This is needed because enabling the FPU can
+ *     cause other exceptions to happen, and the whole system is
+ *     in a rather precarious state and so special cautions must
+ *     be taken.
+ */
+#define FLAG_CPU_FIELD_WIDTH           4       /* must be <= 12 */
+
+#define FLAG_IGNORE_DATA_EXCEPTION     5       /* bit number 5 */
+#define FLAG_INTERRUPT_EXCEPTION       6       /* bit number 6 */
+#define FLAG_ENABLING_FPU              7       /* bit number 7 */
+
+
+/* REGister OFFset into the E.F. (exception frame) */
+#define REG_OFF(reg_num)  ((reg_num) * 4) /* (num * sizeof(register int))  */
+#define GENREG_OFF(num)        (REG_OFF(EF_R0 + (num))) /* GENeral REGister OFFset */
+
+
+#define GENERAL_BREATHING_ROOM /* arbitrarily */ 200
+#define KERNEL_STACK_BREATHING_ROOM    \
+       (GENERAL_BREATHING_ROOM + SIZEOF_STRUCT_PCB + SIZEOF_STRUCT_UTHREAD)
+
+/*
+ * Some registers used during the setting up of the new exception frame.
+ * Don't choose r1, r30, or r31 for any of them.
+ *
+ * Also, if any are 'r2' or 'r3', be careful using with CALL above!
+ */
+#define FLAGS  r2
+#define TMP    r3
+#define TMP2   r10
+#define TMP3   r11
+#define SAVE_TMP2      st      r10, r31, GENREG_OFF(10)
+#define SAVE_TMP3      st      r11, r31, GENREG_OFF(11)
+#define RESTORE_TMP2   ld      r10, r31, GENREG_OFF(10)
+#define RESTORE_TMP3   ld      r11, r31, GENREG_OFF(11)
+
+/*
+ * Info about the PSR 
+ */
+#define PSR_SHADOW_FREEZE_BIT           0
+#define PSR_INTERRUPT_DISABLE_BIT       1
+#define PSR_FPU_DISABLE_BIT             3
+#define PSR_BIG_ENDIAN_MODE            30
+#define PSR_SUPERVISOR_MODE_BIT                31
+
+/*
+ * Status bits for an SXIP/SNIP/SFIP address.
+ */
+#define RTE_VALID_BIT   1
+#define RTE_ERROR_BIT   0
+
+/*
+ * Info about DMT0/DMT1/DMT2
+ */
+#define DMT_VALID_BIT   0
+#define DMT_WRITE_BIT   1
+#define DMT_LOCK_BIT   12
+#define DMT_DOUBLE_BIT 13
+#define DMT_DAS_BIT     14
+#define DMT_DREG_OFFSET         7
+#define DMT_DREG_WIDTH  5
+
+/*
+ * Bits for eh_debug.
+ */
+#define DEBUG_INTERRUPT_BIT             0
+#define DEBUG_DATA_BIT                  1
+#define DEBUG_INSTRUCTION_BIT           2
+#define DEBUG_MISALIGN_BIT              3
+#define DEBUG_UNIMP_BIT                         4
+#define DEBUG_DIVIDE_BIT                5
+#define DEBUG_OF_BIT                    6
+#define DEBUG_FPp_BIT                   7
+#define DEBUG_FPi_BIT                   8
+#define DEBUG_SYSCALL_BIT               9
+#define DEBUG_MACHSYSCALL_BIT          10
+#define DEBUG_UNIMPLEMENTED_BIT                11
+#define DEBUG_PRIVILEGE_BIT            12
+#define DEBUG_BOUNDS_BIT               13
+#define DEBUG_OVERFLOW_BIT             14
+#define DEBUG_ERROR_BIT                        15
+#define DEBUG_SIGSYS_BIT               16
+#define DEBUG_SIGTRAP_BIT              17
+#define DEBUG_BREAK_BIT                        18
+#define DEBUG_TRACE_BIT                        19
+#define DEBUG_KDB_BIT                  20
+#define DEBUG_JKDB_BIT                 21
+#define DEBUG_BUGCALL_BIT              22
+
+#define DEBUG_UNKNOWN_BIT              31
+
+/*
+ * These things for vector_init.c and locore.c
+ */
+#if defined(ASSEMBLER)
+# define  PREDEFINED_BY_ROM       0xffffffff
+# define  END_OF_VECTOR_LIST      0xfffffffe
+#else
+# define  PREDEFINED_BY_ROM       0xffffffffU
+# define  END_OF_VECTOR_LIST      0xfffffffeU
+#endif
+
+/*
+ * Define ERROR__XXX_USR if the xxx.usr bug (mask C82N) is present.
+ * This implements the workaround.
+ */
+#define ERRATA__XXX_USR        1
+
+#if !defined(CMMU_I)
+#define CMMU_I 0xFFF77000
+#endif
+#if !defined(CMMU_D)
+#define CMMU_D 0xFFF7F000
+#endif
+
+#endif /* __M88K_ASM_H__ */
diff --git a/sys/arch/mvme88k/include/asm_macro.h b/sys/arch/mvme88k/include/asm_macro.h
new file mode 100644 (file)
index 0000000..87aac4b
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+/*
+ * HISTORY
+ * $Log: asm_macro.h,v $
+ * Revision 1.3  1997/03/03 20:20:46  rahnds
+ * Cleanup after import. This also seems to bring up the current version.
+ *
+ * Revision 1.1.1.1  1995/10/18 10:54:22  deraadt
+ * initial 88k import; code by nivas and based on mach luna88k
+ *
+ * Revision 2.2  93/01/26  18:07:26  danner
+ *     Created.
+ *     [93/01/24            jfriedl]
+ * 
+ */
+
+#ifndef __M88K_ASM_MACRO_H__
+#define __M88K_ASM_MACRO_H__
+
+/*
+ ** Various compiler macros used for speed and efficiency.
+ ** Anyone can include.
+  */
+
+/*
+ * PSR_TYPE is the type of the Process Status Register.
+ */
+typedef unsigned long m88k_psr_type;
+
+/*
+ * disable_interrupts_return_psr()
+ *
+ *    The INTERRUPT_DISABLE bit is set in the PSR and the *PREVIOUS*
+ *    PSR is returned.  Intended to be used with set_psr() [below] as in:
+ *
+ *     {
+ *         m88k_psr_type psr;
+ *             .
+ *             .
+ *         psr = disable_interrupts_return_psr();
+ *             .
+ *             SHORT [time-wise] CRITICAL SECTION HERE
+ *             .
+ *         set_psr(psr);
+ *             .
+ *             .
+ */
+static inline m88k_psr_type disable_interrupts_return_psr(void)
+{
+    m88k_psr_type temp, oldpsr;
+    asm volatile (
+       "ldcr %0, cr1      \n"
+       "set  %1, %0, 1<1> \n"
+       "stcr %1, cr1      \n"
+       "tcnd ne0, r0, 0     " : "=r" (oldpsr), "=r" (temp));
+    return oldpsr;
+}
+#define disable_interrupt() (void)disable_interrupts_return_psr()
+
+/*
+ * Sets the PSR. See comments above.
+ */
+static inline void set_psr(m88k_psr_type psr)
+{
+    asm volatile ("stcr %0, cr1" :: "r" (psr));
+}
+
+/*
+ * Enables interrupts.
+ */
+static inline m88k_psr_type enable_interrupts_return_psr(void)
+{
+    m88k_psr_type temp, oldpsr; /* need a temporary register */
+    asm volatile (
+       "ldcr %0, cr1      \n"
+        "clr  %1, %0, 1<1> \n"
+        "stcr %1, cr1        " : "=r" (oldpsr), "=r" (temp));
+    return oldpsr;
+}
+#define enable_interrupt() (void)enable_interrupts_return_psr()
+
+#define db_enable_interrupt enable_interrupt
+#define db_disable_interrupt disable_interrupt
+
+/*
+ * flushes the data pipeline.
+ */
+static inline void flush_pipeline()
+{
+    asm volatile ("tcnd ne0, r0, 0");
+}
+#define db_flush_pipeline flush_pipeline
+
+#endif /* __M88K_ASM_MACRO_H__ */
diff --git a/sys/arch/mvme88k/include/assert.h b/sys/arch/mvme88k/include/assert.h
new file mode 100644 (file)
index 0000000..c9e7255
--- /dev/null
@@ -0,0 +1,8 @@
+#define assert(x) \
+({\
+       if (!(x)) {\
+               printf("assertion failure \"%s\" line %d file %s\n", \
+               #x, __LINE__, __FILE__); \
+               panic("assertion"); \
+       } \
+})
diff --git a/sys/arch/mvme88k/include/assym.s b/sys/arch/mvme88k/include/assym.s
new file mode 100644 (file)
index 0000000..e394deb
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __GENASSYM_INCLUDED
+#define __GENASSYM_INCLUDED 1
+
+#define        P_FORW 0
+#define        P_BACK 4
+#define        P_VMSPACE 32
+#define        P_ADDR 236
+#define        P_PRIORITY 208
+#define        P_STAT 45
+#define        P_WCHAN 104
+#define        SRUN 2
+#define        VM_PMAP 132
+#define        V_INTR 12
+#define        UPAGES 3
+#define        PGSHIFT 12
+#define        USIZE 12288
+#define        NBPG 4096
+#define        U_PROF 840
+#define        U_PROFSCALE 852
+#define        PCB_ONFAULT 336
+#define        SIZEOF_PCB 344
+#define        PCB_USER_STATE 80
+#define        SYS_exit 1
+#define        SYS_execve 59
+#define        SYS_sigreturn 103
+#define EF_R0 0
+#define EF_R31 31
+#define EF_FPSR 32
+#define EF_FPCR 33
+#define EF_EPSR 34
+#define EF_SXIP 35
+#define EF_SFIP 37
+#define EF_SNIP 36
+#define EF_SSBR 38
+#define EF_DMT0 39
+#define EF_DMD0 40
+#define EF_DMA0 41
+#define EF_DMT1 42
+#define EF_DMD1 43
+#define EF_DMA1 44
+#define EF_DMT2 45
+#define EF_DMD2 46
+#define EF_DMA2 47
+#define EF_FPECR 48
+#define EF_FPHS1 49
+#define EF_FPLS1 50
+#define EF_FPHS2 51
+#define EF_FPLS2 52
+#define EF_FPPT 53
+#define EF_FPRH 54
+#define EF_FPRL 55
+#define EF_FPIT 56
+#define EF_VECTOR 57
+#define EF_MASK 58
+#define EF_MODE 59
+#define EF_RET 60
+#define EF_IPFSR 61
+#define EF_DPFSR 62
+#define EF_NREGS 64
+#define SIZEOF_EF 256
+#define PCB_PC 0
+#define PCB_IPL 4
+#define PCB_R14 8
+#define PCB_R15 12
+#define PCB_R16 16
+#define PCB_R17 20
+#define PCB_R18 24
+#define PCB_R19 28
+#define PCB_R20 32
+#define PCB_R21 36
+#define PCB_R22 40
+#define PCB_R23 44
+#define PCB_R24 48
+#define PCB_R25 52
+#define PCB_R26 56
+#define PCB_R27 60
+#define PCB_R28 64
+#define PCB_R29 68
+#define PCB_R30 72
+#define PCB_SP 76
+
+#endif /* __GENASSYM_INCLUDED */
diff --git a/sys/arch/mvme88k/include/autoconf.h b/sys/arch/mvme88k/include/autoconf.h
new file mode 100644 (file)
index 0000000..c5220fa
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ *
+ */
+/*
+ * Autoconfiguration information.
+ */
+struct confargs {
+       int     ca_bustype;
+       caddr_t ca_parent;
+       caddr_t ca_vaddr;
+       caddr_t ca_paddr;
+       int     ca_size;
+       int     ca_ipl;
+       int     ca_vec;
+};
+
+#define BUS_MAIN       0
+#define BUS_MC         1
+#define BUS_PCC                2
+#define BUS_PCCTWO     3
+#define BUS_VMES       4
+#define BUS_VMEL       5
+
+int always_match __P((struct device *, struct cfdata *, void *));
+
+#define DEVICE_UNIT(device) (device->dv_unit)
+#define CFDATA_LOC(cfdata) (cfdata->cf_loc)
diff --git a/sys/arch/mvme88k/include/board.h b/sys/arch/mvme88k/include/board.h
new file mode 100644 (file)
index 0000000..22011cb
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ *
+ */
+#ifndef _MACHINE_BOARD_H
+#define _MACHINE_BOARD_H
+/*
+ *      VME187 CPU board constants - derived from Luna88k
+ */
+
+/*
+ * Something to put append a 'U' to a long constant if it's C so that
+ * it'll be unsigned in both ANSI and traditional.
+ */
+#if defined(ASSEMBLER)
+#      define U(num)   num
+#else
+#  if defined(__STDC__)
+#      define U(num)   num ## U
+#  else
+#      define U(num)   num/**/U
+#  endif
+#endif
+
+#define        MAX_CPUS        1               /* no. of CPUs */
+#define MAX_CMMUS      2               /* 2 CMMUs - 1 data and 1 code */
+
+#define        SYSV_BASE       U(0x00000000)   /* system virtual base */
+
+#define        MAXU_ADDR       U(0x40000000)   /* size of user virtual space */
+#define MAXPHYSMEM     U(0x10000000)   /* max physical memory */
+
+#define BUGROM_START   U(0xFF800000)   /* start of BUG PROM */
+#define BUGROM_SIZE    U(0x003FFFFF)   /* size of BUG PROM */
+#define SRAM_START     U(0xFFE00000)   /* start of sram used by bug */
+#define SRAM_SIZE      U(0x0001FFFF)   /* size of sram */
+#define OBIO_START     U(0xFFF00000)   /* start of local IO */
+#define OBIO_SIZE      U(0x000EFFFF)   /* size of obio space */
+
+#define INT_PRI_LEVEL  U(0xFFF4203E)   /* interrupt priority level */
+#define INT_MASK_LEVEL U(0xFFF4203F)   /* interrupt mask level */
+
+#define LOCAL_IO_DEVS  U(0xFFF00000)   /* local IO devices */
+#define VMEA16         U(0xFFFF0000)   /* VMEbus A16 */
+
+#define        PCC2_ADDR       U(0xFFF42000)   /* PCCchip2 Regs */
+#define        MEM_CTLR        U(0xFFF43000)   /* MEMC040 mem controller */
+#define SCC_ADDR       U(0xFFF45000)   /* Cirrus Chip */
+#define LANCE_ADDR     U(0xFFF46000)   /* 82596CA */
+#define SCSI_ADDR      U(0xFFF47000)   /* NCR 710 address */
+#define NCR710_SIZE    U(0x00000040)   /* NCR 710 size */
+#define MK48T08_ADDR   U(0xFFFC0000)   /* BBRAM, TOD */
+
+#define        TOD_CAL_CTL     U(0xFFFC1FF8)   /* calendar control register */
+#define TOD_CAL_SEC    U(0xFFFC1FF9)   /* seconds */
+#define TOD_CAL_MIN    U(0xFFFC1FFA)   /* minutes */
+#define TOD_CAL_HOUR   U(0xFFFC1FFB)   /* hours */
+#define TOD_CAL_DOW    U(0xFFFC1FFC)   /* Day Of the Week */
+#define TOD_CAL_DAY    U(0xFFFC1FFD)   /* days */
+#define TOD_CAL_MON    U(0xFFFC1FFE)   /* months */
+#define TOD_CAL_YEAR   U(0xFFFC1FFF)   /* years */
+
+#define CMMU_I         U(0xFFF77000)   /* CMMU instruction  */
+#define CMMU_D         U(0xFFF7F000)   /* CMMU data */
+#define CMMU_SIZE      0x1000
+
+#if 0
+/* interrupt vectors */
+
+#define PPBSY          0x50            /* printer port busy */
+#define PPPE           0x51            /* printer port PE   */
+#define PPSEL          0x52            /* printer port select */
+#define PPFLT          0x53            /* printer port fault */
+#define PPACK          0x54            /* printer port ack */
+#define SCSIIRQ                0x55            /* SCSI IRQ */
+#define LANCERR                0x56            /* LANC ERR */
+#define LANCIRQ                0x57            /* LANC IRQ */
+#define TIMER2IRQ      0x58            /* Tick Timer 2 vec */
+#define TIMER1IRQ      0x59            /* Tick Timer 1 vec */
+#define GPIOIRQ                0x5A            /* GPIO IRQ */
+#define SRXEXIRQ       0x5C            /* Serial RX Exception IRQ */
+#define SRMIRQ         0x5D            /* Serial Modem IRQ */
+#define STXIRQ         0x5E            /* Serial TX IRQ */
+#define SRXIRQ         0x5F            /* Serial RX IRQ */
+#endif /* 0 */
+
+#endif /* _MACHINE_BOARD_H */
diff --git a/sys/arch/mvme88k/include/bug.h b/sys/arch/mvme88k/include/bug.h
new file mode 100644 (file)
index 0000000..b1c3686
--- /dev/null
@@ -0,0 +1,12 @@
+#include <machine/bugio.h>
+
+struct bugenv {
+       int     clun;
+       int     dlun;
+       int     ipl;
+       int     ctlr;
+       int     (*entry)();
+       int     cfgblk;
+       char    *argstart;
+       char    *argend;
+};
diff --git a/sys/arch/mvme88k/include/bugio.h b/sys/arch/mvme88k/include/bugio.h
new file mode 100644 (file)
index 0000000..0bb0269
--- /dev/null
@@ -0,0 +1,80 @@
+#include "sys/cdefs.h"
+
+struct bugdisk_io {
+       char    clun;
+       char    dlun;
+       short   status;
+       void    *addr;
+       int     blkno;
+#define        fileno  blkno
+       short   nblks;
+       char    flag;
+#define        FILEMARKFLAG    0x80
+#define        IGNOREFILENO    0x02
+#define        ENDOFFILE       0x01
+       char    am;
+};     
+
+/* values are in BCD {upper nibble+lower nibble} */
+
+struct bugrtc {
+       unsigned char   Y;
+       unsigned char   M;
+       unsigned char   D;
+       unsigned char   d;
+       unsigned char   H;
+       unsigned char   m;
+       unsigned char   s;
+       unsigned char   c;
+};
+
+/* Board ID - lots of info */
+
+struct bugbrdid {
+       unsigned char   eye[4];
+       char    rev;
+       char    month;
+       char    day;
+       char    year;
+       short   packetsize;
+       short   dummy;
+       short   brdno;
+       unsigned char   brdsuf[2];
+       char    options[3];
+       char    family:4;
+       char    cpu:4;
+       short   clun;
+       short   dlun;
+       short   type;
+       short   dev;
+       int     option;
+};
+
+struct bugniocall {
+       unsigned char clun;
+       unsigned char dlun;
+       unsigned char ci;
+       unsigned char cd;
+#define        NETCTRL_INITDEVICE      0
+#define        NETCTRL_GETHDW          1
+#define        NETCTRL_TX              2
+#define        NETCTRL_RX              3
+#define        NETCTRL_FLUSH           4
+#define        NETCTRL_RESET           5
+       unsigned int  cid;
+       unsigned int  memaddr;
+       unsigned int  nbytes;
+       unsigned int  csword;
+};
+
+char buginchr  __P((void));
+int buginstat  __P((void));
+int bugoutchr  __P((unsigned char));
+int bugoutstr  __P((char *, char *));
+int bugpcrlf   __P((void));
+int bugdskrd   __P((struct bugdisk_io *));
+int bugdskwr   __P((struct bugdisk_io *));
+int bugrtcrd   __P((struct bugrtc *));
+int bugreturn  __P((void));
+int bugbrdid   __P((struct bugbrdid *));
+int bugnetctrl __P((struct bugniocall *));
diff --git a/sys/arch/mvme88k/include/cdefs.h b/sys/arch/mvme88k/include/cdefs.h
new file mode 100644 (file)
index 0000000..36f4990
--- /dev/null
@@ -0,0 +1,35 @@
+/*     $NetBSD: cdefs.h,v 1.2 1995/03/23 20:10:48 jtc Exp $    */
+
+/*
+ * Written by J.T. Conklin <jtc@wimsey.com> 01/17/95.
+ * Public domain.
+ */
+
+#ifndef        _MACHINE_CDEFS_H_
+#define        _MACHINE_CDEFS_H_
+
+#ifdef __STDC__
+#define _C_LABEL(x)    _STRING(_ ## x)
+#else
+#define _C_LABEL(x)    _STRING(_/**/x)
+#endif
+
+#ifdef __GNUC__
+#ifdef __STDC__
+#define __indr_reference(sym,alias)    \
+       __asm__(".stabs \"_" #alias "\",11,0,0,0");     \
+       __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#define __warn_references(sym,msg)     \
+       __asm__(".stabs \"" msg "\",30,0,0,0");         \
+       __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#else
+#define __indr_reference(sym,alias)    \
+       __asm__(".stabs \"_/**/alias\",11,0,0,0");      \
+       __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#define __warn_references(sym,msg)     \
+       __asm__(".stabs msg,30,0,0,0");                 \
+       __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#endif
+#endif
+
+#endif /* !_MACHINE_CDEFS_H_ */
diff --git a/sys/arch/mvme88k/include/cpu.h b/sys/arch/mvme88k/include/cpu.h
new file mode 100644 (file)
index 0000000..850b29a
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1996 Nivas Madhur
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CPU_H_
+#define _CPU_H_
+
+/*
+ * CTL_MACHDEP definitinos.
+ */
+#define        CPU_MAXID       1       /* no valid machdep ids */
+
+#define        CTL_MACHDEP_NAMES { \
+       { 0, 0 }, \
+}
+
+#ifdef _KERNEL
+
+#include <machine/psl.h>
+#include <machine/pcb.h>
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+#define        COPY_SIGCODE            /* copy sigcode above user stack in exec */
+
+#define        cpu_exec(p)     /* nothing */
+#define        cpu_wait(p)     /* nothing */
+#define        cpu_swapout(p)  /* nothing */
+
+/*
+ * Arguments to hardclock and gatherstats encapsulate the previous
+ * machine state in an opaque clockframe. CLKF_INTR is only valid
+ * if the process is in kernel mode. Clockframe is really trapframe,
+ * so pointer to clockframe can be safely cast into a pointer to
+ * trapframe.
+ */
+struct clockframe {
+       struct trapframe tf;
+};
+
+extern intstack;
+
+#define        CLKF_USERMODE(framep)   ((((struct trapframe *)(framep))->epsr & 80000000) == 0)
+#define        CLKF_BASEPRI(framep)    (((struct trapframe *)(framep))->mask == 0)
+#define        CLKF_PC(framep)         (((struct trapframe *)(framep))->sxip & ~3)
+#define        CLKF_INTR(framep)       (((struct trapframe *)(framep))->r[31] > intstack)
+
+#define SIR_NET                1
+#define SIR_CLOCK      2
+
+#define setsoftnet()   (ssir |= SIR_NET)
+#define setsoftclock() (ssir |= SIR_CLOCK)
+
+#define siroff(x)      (ssir &= ~x)
+
+int    ssir;
+int    want_ast;
+
+/*
+ * Preempt the current process if in interrupt from user mode,
+ * or after the current trap/syscall if in system mode.
+ */
+int    want_resched;           /* resched() was called */
+#define        need_resched()          (want_resched = 1, want_ast = 1)
+
+/*
+ * Give a profiling tick to the current process when the user profiling
+ * buffer pages are invalid.  On the sparc, request an ast to send us 
+ * through trap(), marking the proc as needing a profiling tick.
+ */
+#define        need_proftick(p)        ((p)->p_flag |= P_OWEUPC, want_ast = 1)
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+#define        signotify(p)            (want_ast = 1)
+
+struct intrhand {
+       int     (*ih_fn)();
+       void    *ih_arg;
+       int     ih_ipl;
+       int     ih_wantframe;
+       struct  intrhand *ih_next;
+};
+
+int    intr_establish __P((int vec, struct intrhand *));
+
+/*
+ * return values for intr_establish()
+ */
+
+#define INTR_EST_SUCC          0
+#define INTR_EST_BADVEC                1
+#define INTR_EST_BADIPL                2
+
+
+/*
+ * There are 256 possible vectors on a MVME1x7 platform (including
+ * onboard and VME vectors. Use intr_establish() to register a
+ * handler for the given vector. vector number is used to index
+ * into the intr_handlers[] table.
+ */
+extern struct intrhand *intr_handlers[256];
+
+/*
+ * switchframe - should be double word aligned.
+ */
+struct switchframe {
+       u_int   sf_pc;                  /* pc */
+       void    *sf_proc;               /* proc pointer */
+};
+
+#endif /* _KERNEL */
+#endif /* _CPU_H_ */
diff --git a/sys/arch/mvme88k/include/cpus.h b/sys/arch/mvme88k/include/cpus.h
new file mode 100644 (file)
index 0000000..14501d9
--- /dev/null
@@ -0,0 +1,64 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1993-1992 Carnegie Mellon University
+ * 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 ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS 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 Mellon 
+ * the rights to redistribute these changes.
+ */
+/*
+ *
+ * HISTORY
+ */
+/* 
+  Versions Idents for 88k family chips 
+ */
+
+#ifndef _M88K_CPUS_
+#define _M88K_CPUS_
+
+/*
+ * cpu Processor Identification Register (PID).
+ */
+#ifndef ASSEMBLER
+union cpupid {
+    unsigned cpupid;
+    struct {
+       unsigned
+           /*empty*/:16,
+           arc:8,
+           version:7,
+           master:1;
+    } m88100;
+    struct {
+       unsigned
+           id:8,
+           type:3,
+           version:5,
+           /*empty*/:16;
+    } m88200;
+};
+#endif ASSEMBLER
+
+#define        M88100          0
+#define M88200         5
+#define M88204         6
+
+#endif  _M88K_CPUS_
diff --git a/sys/arch/mvme88k/include/db_machdep.h b/sys/arch/mvme88k/include/db_machdep.h
new file mode 100644 (file)
index 0000000..9bafbf3
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+/*
+ * HISTORY
+ */
+
+/*
+ * Machine-dependent defined for the new kernel debugger
+ */
+
+#ifndef  _M88K_DB_MACHDEP_H_
+#define  _M88K_DB_MACHDEP_H_ 1
+
+#include <sys/types.h>
+#include <vm/vm_prot.h>
+#include <vm/vm_param.h>
+#include <vm/vm_inherit.h>
+#include <vm/lock.h>
+#include <machine/pcb.h>       /* m88100_saved_state */
+#include <machine/psl.h>
+#include <machine/trap.h>
+
+#define BKPT_SIZE        (4)                /* number of bytes in bkpt inst. */
+#define BKPT_INST       (0xF000D082U)             /* tb0, 0,r0, vector 132 */
+#define BKPT_SET(inst)  (BKPT_INST)
+
+/* Entry trap for the debugger - used for inline assembly breaks*/
+#define ENTRY_ASM              "tb0 0, r0, 132"
+#define DDB_ENTRY_TRAP_NO      132
+
+typedef vm_offset_t   db_addr_t;
+typedef int           db_expr_t;
+typedef struct m88100_saved_state db_regs_t;
+db_regs_t            ddb_regs; /* register state */
+#define DDB_REGS      (&ddb_regs)
+
+/*
+ * the low two bits of sxip, snip, sfip have valid bits
+ * in them that need to masked to get the correct addresses
+ */
+
+#define m88k_pc(regs) \
+({ \
+    int ret; \
+ \
+    if (regs->sxip & 2) /* is valid */ \
+       ret = regs->sxip & ~3; \
+    else if (regs->snip & 2) \
+       ret = regs->snip & ~3; \
+    else if (regs->sfip & 2) \
+       ret = regs->sfip & ~3; \
+    /* we are in trouble - none of the program counters is valid */ \
+    ret;  \
+})
+
+/*
+ * This is an actual function due to the fact that the sxip
+ * or snip could be nooped out due to a jmp or rte
+ */
+#define PC_REGS(regs) ((regs->sxip & 2) ?  regs->sxip & ~3 : \
+       (regs->snip & 2 ? regs->snip & ~3 : regs->sfip & ~3))
+#define l_PC_REGS(regs) ((regs->sxip & 2) ?  regs->sxip : \
+       (regs->snip & 2 ? regs->snip : regs->sfip ))
+
+#define pC_REGS(regs) (regs->sxip & 2) ? regs->sxip : (regs->snip & 2 ? \
+                               regs->snip : regs->sfip)
+extern int db_noisy;
+#define NOISY(x) if (db_noisy) x
+#define NOISY2(x) if (db_noisy >= 2) x
+#define NOISY3(x) if (db_noisy >= 3) x
+
+extern int quiet_db_read_bytes;
+
+/* These versions are not constantly doing SPL */
+#define        cnmaygetc       db_getc
+#define        cngetc          db_getc
+#define        cnputc          db_putc
+
+/* breakpoint/watchpoint foo */
+#define IS_BREAKPOINT_TRAP(type,code) ((type)==T_KDB_BREAK)
+#if defined(T_WATCHPOINT)
+#define IS_WATCHPOINT_TRAP(type,code) ((type)==T_KDB_WATCH)
+#else
+#define IS_WATCHPOINT_TRAP(type,code) 0
+#endif /* T_WATCHPOINT */
+
+/* we don't want coff support */
+#define DB_NO_COFF 1
+
+/* need software single step */
+#define SOFTWARE_SSTEP 1 /* we need this XXX nivas */
+
+/*
+ * Debugger can get to any address space
+ */
+
+#define DB_ACCESS_LEVEL DB_ACCESS_ANY
+
+#define DB_VALID_KERN_ADDR(addr) (!badaddr((void*)(addr), 1))
+#define DB_VALID_ADDRESS(addr,user) \
+  (user ? db_check_user_addr(addr) : DB_VALID_KERN_ADDR(addr))
+
+/* instruction type checking - others are implemented in db_sstep.c */
+
+#define inst_trap_return(ins)  ((ins) == 0xf400fc00U)
+
+/* don't need to load symbols */
+#define DB_SYMBOLS_PRELOADED 1
+
+/* machine specific commands have been added to ddb */
+#define DB_MACHINE_COMMANDS 1
+/* inst_return(ins) - is the instruction a function call return.
+ * Not mutually exclusive with inst_branch. Should be a jmp r1. */
+#define inst_return(I) (((I)&0xfffffbffU) == 0xf400c001U ? TRUE : FALSE)
+
+#ifdef __GNUC__
+/*
+ * inst_call - function call predicate: is the instruction a function call.
+ * Could be either bsr or jsr
+ */
+#define inst_call(I) ({ unsigned i = (I); \
+       ((((i) & 0xf8000000U) == 0xc8000000U || /*bsr*/ \
+          ((i) & 0xfffffbe0U) == 0xf400c800U)   /*jsr*/ \
+       ? TRUE : FALSE) \
+;})
+
+/*
+ * This routine should return true for instructions that result in unconditonal
+ * transfers of the flow of control. (Unconditional Jumps, subroutine calls,
+ * subroutine returns, etc).
+ *
+ *  Trap and return from trap  should not  be listed here.
+ */
+#define inst_unconditional_flow_transfer(I) ({ unsigned i = (I); \
+    ((((i) & 0xf0000000U) == 0xc0000000U || /* br, bsr */ \
+      ((i) & 0xfffff3e0U) == 0xf400c000U)   /* jmp, jsr */ \
+     ? TRUE: FALSE) \
+;})
+
+/* Return true if the instruction has a delay slot.  */
+#define db_branch_is_delayed(I)        inst_delayed(I)
+
+#endif /* __GNUC__ */
+
+#define        db_printf_enter db_printing
+
+#endif /* _M88K_DB_MACHDEP_H_ */
diff --git a/sys/arch/mvme88k/include/disklabel.h b/sys/arch/mvme88k/include/disklabel.h
new file mode 100644 (file)
index 0000000..493f045
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1996 Nivas Madhur
+ * Copyright (c) 1995 Dale Rahn.
+ * 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 Dale Rahn.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */  
+
+#ifndef _MACHINE_DISKLABEL_H_
+#define _MACHINE_DISKLABEL_H_
+
+/* number of boot pieces , ie xxboot bootxx */
+#define NUMBOOT                2
+
+#define        PARTITIONSHIFT  4
+
+#define LABELSECTOR     0                       /* sector containing label */
+#define LABELOFFSET    0                       /* offset of label in sector */
+#define MAXPARTITIONS  (1 << PARTITIONSHIFT)   /* number of partitions */
+#define RAW_PART       2                       /* raw partition: xx?c */
+
+/* 
+ * used to encode disk minor numbers
+ * this should probably be moved to sys/disklabel.h
+ */
+#define DISKUNIT(dev)  (minor(dev) / MAXPARTITIONS)
+#define DISKPART(dev)  (minor(dev) % MAXPARTITIONS)
+#define MAKEDISKDEV(maj, unit, part) \
+    (makedev((maj), ((unit) * MAXPARTITIONS) + (part)))
+
+/*
+ * Note: this structure is exactly 512 bytes in size. If you move fields
+ * around, make sure the various members are properly aligned and the
+ * compiler won't do any additional padding.
+ */
+
+struct cpu_disklabel {
+       /* VID */
+       u_char          vid_id[4];
+       u_char          vid_0[16];
+       u_int           vid_oss;
+       u_short         vid_osl;
+       u_char          vid_1[4];
+       u_short         vid_osa_u;
+       u_short         vid_osa_l;
+       u_char          version;
+       u_char          vid_2[1];
+       u_short         checksum;       /* 2 */
+       u_short         partitions;
+       u_char          vid_vd[16];
+       u_long          bbsize;
+       u_long          magic1;         /* 4 */
+       u_short         type;           /* 2 */
+       u_short         subtype;        /* 2 */
+       u_char          packname[16];   /* 16 */
+       u_long          flags;          /* 4 */
+       u_long          drivedata[5];   /* 4 */
+       u_long          spare[5];       /* 4 */
+
+       u_long          secpercyl;      /* 4 */
+       u_long          secperunit;     /* 4 */
+       u_long          headswitch;     /* 4 */
+
+       u_char          vid_3[4];
+       u_int           vid_cas;
+       u_char          vid_cal;
+       u_char          vid_4_0[3];
+       u_char          vid_4[64];
+       u_char          vid_4_1[28];
+       u_long          sbsize;
+       u_char          vid_mot[8];
+
+       /* CFG */
+       u_char          cfg_0[4];
+       u_short         cfg_atm;
+       u_short         cfg_prm;
+       u_short         cfg_atw;
+       u_short         cfg_rec;
+
+       u_short         sparespertrack;
+       u_short         sparespercyl;
+       u_long          acylinders;
+       u_short         rpm;
+       u_short         cylskew;
+
+       u_char          cfg_spt;
+       u_char          cfg_hds;
+       u_short         cfg_trk;
+       u_char          cfg_ilv;
+       u_char          cfg_sof;
+       u_short         cfg_psm;
+       u_short         cfg_shd;
+       u_char          cfg_2[2];
+       u_short         cfg_pcom;
+       u_char          cfg_3;
+       u_char          cfg_ssr;
+       u_short         cfg_rwcc;
+       u_short         cfg_ecc;
+       u_short         cfg_eatm;
+       u_short         cfg_eprm;
+       u_short         cfg_eatw;
+       u_char          cfg_gpb1;
+       u_char          cfg_gpb2;
+       u_char          cfg_gpb3;
+       u_char          cfg_gpb4;
+       u_char          cfg_ssc;
+       u_char          cfg_runit;
+       u_short         cfg_rsvc1;
+       u_short         cfg_rsvc2;
+       u_long          magic2;
+       u_char          cfg_4[192];
+};
+#endif _MACHINE_DISKLABEL_H_
diff --git a/sys/arch/mvme88k/include/endian.h b/sys/arch/mvme88k/include/endian.h
new file mode 100644 (file)
index 0000000..de4a384
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1987, 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)endian.h      8.1 (Berkeley) 6/11/93
+ *      $Id: endian.h,v 1.4 1997/03/03 20:20:58 rahnds Exp $
+ */
+
+#ifndef _ENDIAN_H_
+#define        _ENDIAN_H_
+
+/*
+ * Define the order of 32-bit words in 64-bit words.
+ */
+#define _QUAD_HIGHWORD 0
+#define _QUAD_LOWWORD 1
+
+#ifndef _POSIX_SOURCE
+/*
+ * Definitions for byte order, according to byte significance from low
+ * address to high.
+ */
+
+#define        LITTLE_ENDIAN   1234    /* LSB first: i386, vax */
+#define        BIG_ENDIAN      4321    /* MSB first: 68000, 88000 ibm, net */
+#define        PDP_ENDIAN      3412    /* LSB first in word, MSW first in long */
+
+#define        BYTE_ORDER      BIG_ENDIAN
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+unsigned long  htonl __P((unsigned long));
+unsigned short htons __P((unsigned short));
+unsigned long  ntohl __P((unsigned long));
+unsigned short ntohs __P((unsigned short));
+__END_DECLS
+
+/*
+ * Macros for network/external number representation conversion.
+ */
+#if BYTE_ORDER == BIG_ENDIAN && !defined(lint)
+#define        ntohl(x)        (x)
+#define        ntohs(x)        (x)
+#define        htonl(x)        (x)
+#define        htons(x)        (x)
+
+#define        NTOHL(x)        (x)
+#define        NTOHS(x)        (x)
+#define        HTONL(x)        (x)
+#define        HTONS(x)        (x)
+
+#else
+
+#define        NTOHL(x)        (x) = ntohl((u_long)x)
+#define        NTOHS(x)        (x) = ntohs((u_short)x)
+#define        HTONL(x)        (x) = htonl((u_long)x)
+#define        HTONS(x)        (x) = htons((u_short)x)
+#endif
+#endif /* ! _POSIX_SOURCE */
+#endif /* !_ENDIAN_H_ */
diff --git a/sys/arch/mvme88k/include/exception_vectors.h b/sys/arch/mvme88k/include/exception_vectors.h
new file mode 100644 (file)
index 0000000..5a9457f
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+#ifndef UNDEFINED
+# define UNDEFINED unknown_handler
+#endif
+/* vector 0x00 (#0)   */  word   error_handler
+/* vector 0x01 (#1)   */  word   interrupt_handler
+/* vector 0x02 (#2)   */  word   instruction_access_handler
+/* vector 0x03 (#3)   */  word   data_exception_handler
+/* vector 0x04 (#4)   */  word   misaligned_handler
+/* vector 0x05 (#5)   */  word   unimplemented_handler
+/* vector 0x06 (#6)   */  word   privilege_handler
+/* vector 0x07 (#7)   */  word   bounds_handler
+/* vector 0x08 (#8)   */  word   divide_handler
+/* vector 0x09 (#9)   */  word   overflow_handler
+/* vector 0x0a (#10)  */  word   error_handler
+/* vector 0x0b (#11)  */  word   UNDEFINED
+/* vector 0x0c (#12)  */  word   UNDEFINED
+/* vector 0x0d (#13)  */  word   UNDEFINED
+/* vector 0x0e (#14)  */  word   UNDEFINED
+/* vector 0x0f (#15)  */  word   UNDEFINED
+/* vector 0x10 (#16)  */  word   UNDEFINED
+/* vector 0x11 (#17)  */  word   UNDEFINED
+/* vector 0x12 (#18)  */  word   UNDEFINED
+/* vector 0x13 (#19)  */  word   UNDEFINED
+/* vector 0x14 (#20)  */  word   UNDEFINED
+/* vector 0x15 (#21)  */  word   UNDEFINED
+/* vector 0x16 (#22)  */  word   UNDEFINED
+/* vector 0x17 (#23)  */  word   UNDEFINED
+/* vector 0x18 (#24)  */  word   UNDEFINED
+/* vector 0x19 (#25)  */  word   UNDEFINED
+/* vector 0x1a (#26)  */  word   UNDEFINED
+/* vector 0x1b (#27)  */  word   UNDEFINED
+/* vector 0x1c (#28)  */  word   UNDEFINED
+/* vector 0x1d (#29)  */  word   UNDEFINED
+/* vector 0x1e (#30)  */  word   UNDEFINED
+/* vector 0x1f (#31)  */  word   UNDEFINED
+/* vector 0x20 (#32)  */  word   UNDEFINED
+/* vector 0x21 (#33)  */  word   UNDEFINED
+/* vector 0x22 (#34)  */  word   UNDEFINED
+/* vector 0x23 (#35)  */  word   UNDEFINED
+/* vector 0x24 (#36)  */  word   UNDEFINED
+/* vector 0x25 (#37)  */  word   UNDEFINED
+/* vector 0x26 (#38)  */  word   UNDEFINED
+/* vector 0x27 (#39)  */  word   UNDEFINED
+/* vector 0x28 (#40)  */  word   UNDEFINED
+/* vector 0x29 (#41)  */  word   UNDEFINED
+/* vector 0x2a (#42)  */  word   UNDEFINED
+/* vector 0x2b (#43)  */  word   UNDEFINED
+/* vector 0x2c (#44)  */  word   UNDEFINED
+/* vector 0x2d (#45)  */  word   UNDEFINED
+/* vector 0x2e (#46)  */  word   UNDEFINED
+/* vector 0x2f (#47)  */  word   UNDEFINED
+/* vector 0x30 (#48)  */  word   UNDEFINED
+/* vector 0x31 (#49)  */  word   UNDEFINED
+/* vector 0x32 (#50)  */  word   UNDEFINED
+/* vector 0x33 (#51)  */  word   UNDEFINED
+/* vector 0x34 (#52)  */  word   UNDEFINED
+/* vector 0x35 (#53)  */  word   UNDEFINED
+/* vector 0x36 (#54)  */  word   UNDEFINED
+/* vector 0x37 (#55)  */  word   UNDEFINED
+/* vector 0x38 (#56)  */  word   UNDEFINED
+/* vector 0x39 (#57)  */  word   UNDEFINED
+/* vector 0x3a (#58)  */  word   UNDEFINED
+/* vector 0x3b (#59)  */  word   UNDEFINED
+/* vector 0x3c (#60)  */  word   UNDEFINED
+/* vector 0x3d (#61)  */  word   UNDEFINED
+/* vector 0x3e (#62)  */  word   UNDEFINED
+/* vector 0x3f (#63)  */  word   UNDEFINED
+/* vector 0x40 (#64)  */  word   UNDEFINED
+/* vector 0x41 (#65)  */  word   UNDEFINED
+/* vector 0x42 (#66)  */  word   UNDEFINED
+/* vector 0x43 (#67)  */  word   UNDEFINED
+/* vector 0x44 (#68)  */  word   UNDEFINED
+/* vector 0x45 (#69)  */  word   UNDEFINED
+/* vector 0x46 (#70)  */  word   UNDEFINED
+/* vector 0x47 (#71)  */  word   UNDEFINED
+/* vector 0x48 (#72)  */  word   UNDEFINED
+/* vector 0x49 (#73)  */  word   UNDEFINED
+/* vector 0x4a (#74)  */  word   UNDEFINED
+/* vector 0x4b (#75)  */  word   UNDEFINED
+/* vector 0x4c (#76)  */  word   UNDEFINED
+/* vector 0x4d (#77)  */  word   UNDEFINED
+/* vector 0x4e (#78)  */  word   UNDEFINED
+/* vector 0x4f (#79)  */  word   UNDEFINED
+/* vector 0x50 (#80)  */  word   UNDEFINED
+/* vector 0x51 (#81)  */  word   UNDEFINED
+/* vector 0x52 (#82)  */  word   UNDEFINED
+/* vector 0x53 (#83)  */  word   UNDEFINED
+/* vector 0x54 (#84)  */  word   UNDEFINED
+/* vector 0x55 (#85)  */  word   UNDEFINED
+/* vector 0x56 (#86)  */  word   UNDEFINED
+/* vector 0x57 (#87)  */  word   UNDEFINED
+/* vector 0x58 (#88)  */  word   UNDEFINED
+/* vector 0x59 (#89)  */  word   UNDEFINED
+/* vector 0x5a (#90)  */  word   UNDEFINED
+/* vector 0x5b (#91)  */  word   UNDEFINED
+/* vector 0x5c (#92)  */  word   UNDEFINED
+/* vector 0x5d (#93)  */  word   UNDEFINED
+/* vector 0x5e (#94)  */  word   UNDEFINED
+/* vector 0x5f (#95)  */  word   UNDEFINED
+/* vector 0x60 (#96)  */  word   UNDEFINED
+/* vector 0x61 (#97)  */  word   UNDEFINED
+/* vector 0x62 (#98)  */  word   UNDEFINED
+/* vector 0x63 (#99)  */  word   UNDEFINED
+/* vector 0x64 (#100) */  word   UNDEFINED
+/* vector 0x65 (#101) */  word   UNDEFINED
+/* vector 0x66 (#102) */  word   UNDEFINED
+/* vector 0x67 (#103) */  word   UNDEFINED
+/* vector 0x68 (#104) */  word   UNDEFINED
+/* vector 0x69 (#105) */  word   UNDEFINED
+/* vector 0x6a (#106) */  word   UNDEFINED
+/* vector 0x6b (#107) */  word   UNDEFINED
+/* vector 0x6c (#108) */  word   UNDEFINED
+/* vector 0x6d (#109) */  word   UNDEFINED
+/* vector 0x6e (#110) */  word   UNDEFINED
+/* vector 0x6f (#111) */  word   UNDEFINED
+/* vector 0x70 (#112) */  word   UNDEFINED
+/* vector 0x71 (#113) */  word   UNDEFINED
+/* vector 0x72 (#114) */  word   fp_precise_handler
+/* vector 0x73 (#115) */  word   fp_imprecise_handler
+/* vector 0x74 (#116) */  word   unimplemented_handler
+/* vector 0x75 (#117) */  word   UNDEFINED
+/* vector 0x76 (#118) */  word   unimplemented_handler
+/* vector 0x77 (#119) */  word   UNDEFINED
+/* vector 0x78 (#120) */  word   unimplemented_handler
+/* vector 0x79 (#121) */  word   UNDEFINED
+/* vector 0x7a (#122) */  word   unimplemented_handler
+/* vector 0x7b (#123) */  word   UNDEFINED
+/* vector 0x7c (#124) */  word   unimplemented_handler
+/* vector 0x7d (#125) */  word   UNDEFINED
+/* vector 0x7e (#126) */  word   unimplemented_handler
+/* vector 0x7f (#127) */  word   UNDEFINED
+/* vector 0x80 (#128) */  word   _syscall_handler
+/* vector 0x81 (#129) */  word   _syscall_handler
+/* vector 0x82 (#130) */  word   break
+/* vector 0x83 (#131) */  word   trace
+/* vector 0x84 (#132) */  word   entry
+#if defined(RAW_PRINTF) && RAW_PRINTF
+/* vector 0x85 (#133) */  word   user_raw_putstr /* for USER raw_printf() */
+/* vector 0x85 (#134) */  word   user_raw_xpr   /* for USER raw_xpr() */
+#endif
diff --git a/sys/arch/mvme88k/include/exec.h b/sys/arch/mvme88k/include/exec.h
new file mode 100644 (file)
index 0000000..b6b1a45
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _MACHINE_EXEC_H_
+#define _MACHINE_EXEC_H_ 
+
+#define __LDPGSZ        4096
+
+struct relocation_info_m88k { 
+        unsigned int r_address;         /* offset in text or data segment */
+        unsigned int r_symbolnum : 24,  /* ordinal number of add symbol */
+                        r_extern :  1,  /* 1 if need to add symbol to value */
+                        r_baserel : 1,
+                        r_pcrel : 1,
+                        r_jmptable : 1,
+                        r_type : 4;
+
+        int r_addend;
+};
+#define relocation_info relocation_info_m88k
+
+#define        _NLIST_DO_AOUT
+
+#define        _KERN_DO_AOUT
+
+#endif _MACHINE_EXEC_H_ 
diff --git a/sys/arch/mvme88k/include/limits.h b/sys/arch/mvme88k/include/limits.h
new file mode 100644 (file)
index 0000000..7633e58
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)limits.h      8.3 (Berkeley) 1/4/94
+ *      $Id: limits.h,v 1.3 1997/03/03 20:21:01 rahnds Exp $
+ */
+
+#define        CHAR_BIT        8               /* number of bits in a char */
+#define        MB_LEN_MAX      6               /* Allow 31 bit UTF2 */
+
+/*
+ * According to ANSI (section 2.2.4.2), the values below must be usable by
+ * #if preprocessing directives.  Additionally, the expression must have the
+ * same type as would an expression that is an object of the corresponding
+ * type converted according to the integral promotions.  The subtraction for
+ * INT_MIN and LONG_MIN is so the value is not unsigned; 2147483648 is an
+ * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2).
+ * These numbers work for pcc as well.  The UINT_MAX and ULONG_MAX values
+ * are written as hex so that GCC will be quiet about large integer constants.
+ */
+#define        SCHAR_MAX       127             /* min value for a signed char */
+#define        SCHAR_MIN       (-128)          /* max value for a signed char */
+
+#define        UCHAR_MAX       255             /* max value for an unsigned char */
+#define        CHAR_MAX        127             /* max value for a char */
+#define        CHAR_MIN        (-128)          /* min value for a char */
+
+#define        USHRT_MAX       65535           /* max value for an unsigned short */
+#define        SHRT_MAX        32767           /* max value for a short */
+#define        SHRT_MIN        (-32768)        /* min value for a short */
+
+#define        UINT_MAX        0xffffffff      /* max value for an unsigned int */
+#define        INT_MAX         2147483647      /* max value for an int */
+#define        INT_MIN         (-2147483647-1) /* min value for an int */
+
+#define        ULONG_MAX       0xffffffff      /* max value for an unsigned long */
+#define        LONG_MAX        2147483647      /* max value for a long */
+#define        LONG_MIN        (-2147483647-1) /* min value for a long */
+
+#if !defined(_ANSI_SOURCE)
+#define        SSIZE_MAX       INT_MAX         /* max value for a ssize_t */
+
+#if !defined(_POSIX_SOURCE)
+#define        SIZE_T_MAX      UINT_MAX        /* max value for a size_t */
+
+/* GCC requires that quad constants be written as expressions. */
+#define        UQUAD_MAX       ((u_quad_t)0-1) /* max value for a uquad_t */
+                                       /* max value for a quad_t */
+#define        QUAD_MAX        ((quad_t)(UQUAD_MAX >> 1))
+#define        QUAD_MIN        (-QUAD_MAX-1)   /* min value for a quad_t */
+
+#endif /* !_POSIX_SOURCE */
+#endif /* !_ANSI_SOURCE */
diff --git a/sys/arch/mvme88k/include/locore.h b/sys/arch/mvme88k/include/locore.h
new file mode 100644 (file)
index 0000000..fba0a94
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+/*     "locore.h"                Omron Corporation
+ * This file created by Omron Corporation, 1990.
+ * NOTE: Any assembly file that includes this one must define ASSEMBLER first
+ */
+
+#ifndef __MACHINE_LOCORE_H__
+#define __MACHINE_LOCORE_H__
+
+
+/*
+ **********************************************************************
+       SYNTACTICAL AND SEMANTIC DOO-DADS
+ **********************************************************************
+ */
+/*
+ * NEWLINE is defined in 'assmy.s' in the object area to be a double
+ * backslash, which 'as' interprets the same as '\n'
+ */
+
+/*
+ * If this has been included in an assembly file, make sure
+ * LOCORE is defined.  Always make sure KERNEL is defined.
+ */
+#if defined(ASSEMBLER) && !defined(LOCORE)
+#  define LOCORE
+#endif
+#if !defined(KERNEL)
+#  define KERNEL
+#endif
+
+/* Define EH_DEBUG to be non-zero to compile-in various debugging things */
+#ifndef        EH_DEBUG
+#define EH_DEBUG 0
+#endif EH_DEBUG
+
+/* this gives the offsets into various structures of various elements, etc */
+#include "assym.s"
+
+/*
+ * LABEL(name)
+ *     Defines the name to be a label visible to the world.
+ *
+ * _LABEL(name)
+ *     Defines one visible only to the file, unless debugging
+ *     is enabled, in which case it's visible to the world (and
+ *     hence to debuggers, and such).
+ */
+#define LABEL(name)    name:   global name NEWLINE
+#if EH_DEBUG
+#  define _LABEL(name) name:   global name NEWLINE
+#else
+#  define _LABEL(name) name:               NEWLINE
+#endif
+
+
+/*
+ * Useful in some situations.
+ * NOTE: If ARG1 or ARG2 are r2 or r3, strange things may happen.  Watch out!
+ */
+#define CALL(NAME, ARG1, ARG2)             \
+               subu    r31, r31, 32    NEWLINE \
+                or      r2, r0, ARG1    NEWLINE \
+                bsr.n   NAME            NEWLINE \
+                or      r3, r0, ARG2   NEWLINE \
+               addu    r31, r31, 32
+
+/*
+ **********************************************************************
+       SYMBOLIC CONSTANTS AND VALUES and other important things
+ **********************************************************************
+ */
+
+/*
+ * SR1 - CPU FLAGS REGISTER
+ * 
+ * SR1 contains flags about the current CPU status.
+ *
+ * The lowest FLAG_CPU_FIELD_WIDTH bits hold the cpu number (currently 0-3).
+ *
+ *
+ * The bit FLAG_IGNORE_DATA_EXCEPTION indicates that any data exceptions
+ *     should be ignored (well, at least treated in a special way).
+ * The bit FLAG_INTERRUPT_EXCEPTION indicates that the current exception
+ *     is the interrupt exception.  Such information can be gotten
+ *     in other ways, but having it in the flags makes it easy for the
+ *     exception handler to check quickly.
+ * The bit FLAG_ENABLING_FPU indicates that the exception handler is
+ *     in the process of enabling the FPU (so that an exception can
+ *     be serviced).  This is needed because enabling the FPU can
+ *     cause other exceptions to happen, and the whole system is
+ *     in a rather precarious state and so special cautions must
+ *     be taken.
+ */
+#define FLAG_CPU_FIELD_WIDTH           4       /* must be <= 12 */
+
+#define FLAG_IGNORE_DATA_EXCEPTION     5       /* bit number 5 */
+#define FLAG_INTERRUPT_EXCEPTION       6       /* bit number 6 */
+#define FLAG_ENABLING_FPU              7       /* bit number 7 */
+
+
+/* REGister OFFset into the E.F. (exception frame) */
+#define REG_OFF(reg_num)  ((reg_num) * 4) /* (num * sizeof(register int))  */
+#define GENREG_OFF(num)        (REG_OFF(EF_R0 + (num))) /* GENeral REGister OFFset */
+
+
+#define GENERAL_BREATHING_ROOM /* arbitrarily */ 200
+#define KERNEL_STACK_BREATHING_ROOM    \
+       (GENERAL_BREATHING_ROOM + SIZEOF_STRUCT_PCB + SIZEOF_STRUCT_UTHREAD)
+
+/*
+ * Some registers used during the setting up of the new exception frame.
+ * Don't choose r1, r30, or r31 for any of them.
+ *
+ * Also, if any are 'r2' or 'r3', be careful using with CALL above!
+ */
+#define FLAGS  r2
+#define TMP    r3
+#define TMP2   r10
+#define TMP3   r11
+#define SAVE_TMP2      st      r10, r31, GENREG_OFF(10)
+#define SAVE_TMP3      st      r11, r31, GENREG_OFF(11)
+#define RESTORE_TMP2   ld      r10, r31, GENREG_OFF(10)
+#define RESTORE_TMP3   ld      r11, r31, GENREG_OFF(11)
+
+
+/* alternate CPU control register names */
+#define PID    cr0
+#define PSR    cr1
+#define EPSR   cr2
+#define SSBR   cr3
+#define SXIP   cr4
+#define SNIP   cr5
+#define SFIP   cr6
+#define VBR    cr7
+#define DMT0   cr8
+#define DMD0   cr9
+#define DMA0   cr10
+#define DMT1   cr11
+#define DMD1   cr12
+#define DMA1   cr13
+#define DMT2   cr14
+#define DMD2   cr15
+#define DMA2   cr16
+#define SR0    cr17
+#define SR1    cr18
+#define SR2    cr19
+#define SR3    cr20
+#define FPECR  fcr0
+#define FPHS1  fcr1
+#define FPLS1  fcr2
+#define FPHS2  fcr3
+#define FPLS2  fcr4
+#define FPPT   fcr5
+#define FPRH   fcr6
+#define FPRL   fcr7
+#define FPIT   fcr8
+#define FPSR   fcr62
+#define FPCR   fcr63
+
+/*
+ * Info about the PSR 
+ */
+#define PSR_SHADOW_FREEZE_BIT           0
+#define PSR_INTERRUPT_DISABLE_BIT       1
+#define PSR_FPU_DISABLE_BIT             3
+#define PSR_BIG_ENDIAN_MODE            30
+#define PSR_SUPERVISOR_MODE_BIT                31
+
+/*
+ * Status bits for an SXIP/SNIP/SFIP address.
+ */
+#define RTE_VALID_BIT   1
+#define RTE_ERROR_BIT   0
+
+/*
+ * Info about DMT0/DMT1/DMT2
+ */
+#define DMT_VALID_BIT   0
+#define DMT_WRITE_BIT   1
+#define DMT_LOCK_BIT   12
+#define DMT_DOUBLE_BIT 13
+#define DMT_DAS_BIT     14
+#define DMT_DREG_OFFSET         7
+#define DMT_DREG_WIDTH  5
+
+/*
+ * Bits for eh_debug.
+ */
+#define DEBUG_INTERRUPT_BIT             0
+#define DEBUG_DATA_BIT                  1
+#define DEBUG_INSTRUCTION_BIT           2
+#define DEBUG_MISALIGN_BIT              3
+#define DEBUG_UNIMP_BIT                         4
+#define DEBUG_DIVIDE_BIT                5
+#define DEBUG_OF_BIT                    6
+#define DEBUG_FPp_BIT                   7
+#define DEBUG_FPi_BIT                   8
+#define DEBUG_SYSCALL_BIT               9
+#define DEBUG_MACHSYSCALL_BIT          10
+#define DEBUG_UNIMPLEMENTED_BIT                11
+#define DEBUG_PRIVILEGE_BIT            12
+#define DEBUG_BOUNDS_BIT               13
+#define DEBUG_OVERFLOW_BIT             14
+#define DEBUG_ERROR_BIT                        15
+#define DEBUG_SIGSYS_BIT               16
+#define DEBUG_SIGTRAP_BIT              17
+#define DEBUG_BREAK_BIT                        18
+#define DEBUG_TRACE_BIT                        19
+#define DEBUG_KDB_BIT                  20
+#define DEBUG_JKDB_BIT                 21
+#define DEBUG_BUGCALL_BIT              22
+
+#define DEBUG_UNKNOWN_BIT              31
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#define YES            1
+#define NO             0
+
+#define        SCSI_INTS       0x10
+#define        SCSI_SSTS       0x18
+#define SCSI_DREG      0x28
+
+/* change software timer for 8mm device support -- 90/08/21 CEC OKUI */
+#define        SCSI_WAIT       0x5000000
+
+/*
+ * At various times, there is the need to clear the pipeline (i.e.
+ * synchronize).  A "tcnd ne0, r0, foo" will do that (because a trap
+ * instruction always synchronizes, and this particular instruction
+ * will never actually take the trap).
+ */
+#define FLUSH_PIPELINE tcnd    ne0, r0, 0
+
+/*
+ * NOP -- NO-Operation.
+ *
+ * A do-nothing one clock doesn't-touch-the-scoreboard type of instruction,
+ * in case one's needed (sometimes useful for debugging).
+ */
+#define NOP            or r0, r0, r0
+
+/*
+ * These things for vector_init.c and locore.c
+ */
+#if defined(ASSEMBLER)
+# define  PREDEFINED_BY_ROM       0xffffffff
+# define  END_OF_VECTOR_LIST      0xfffffffe
+#else
+# define  PREDEFINED_BY_ROM       0xffffffffU
+# define  END_OF_VECTOR_LIST      0xfffffffeU
+#endif
+
+/*
+ * Define ERROR__XXX_USR if the xxx.usr bug (mask C82N) is present.
+ * This implements the workaround.
+ */
+#define ERRATA__XXX_USR        1
+
+#define USERMODE(x) (!(x & (1 << PSR_SUPERVISOR_MODE_BIT)))
+
+#endif /* __MACHINE_LOCORE_H__ */
diff --git a/sys/arch/mvme88k/include/m88100.h b/sys/arch/mvme88k/include/m88100.h
new file mode 100644 (file)
index 0000000..eb047bb
--- /dev/null
@@ -0,0 +1,69 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1993-1992 Carnegie Mellon University
+ * 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 ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS 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 Mellon 
+ * the rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ */
+/*
+ * M88100 flags
+ */
+
+#ifndef _M88100_H_
+#define _M88100_H_
+
+
+/*
+ *     88100 RISC definitions
+ */
+
+/* DMT0, DMT1, DMT2 */
+#define DMT_BO         0x00008000      /* Byte-Ordering */
+#define DMT_DAS                0x00004000      /* Data Access Space */
+#define DMT_DOUB1      0x00002000      /* Double Word */
+#define DMT_LOCKBAR    0x00001000      /* Bud Lock */
+#define DMT_DREG       0x00000F80      /* Destination Registers 5bits */
+#define DMT_SIGNED     0x00000040      /* Sign-Extended Bit */
+#define DMT_EN         0x0000003C      /* Byte Enable Bit */
+#define DMT_WRITE      0x00000002      /* Read/Write Transaction Bit */
+#define        DMT_VALID       0x00000001      /* Valid Transaction Bit */
+
+#ifndef        ASSEMBLER
+#include "sys/types.h"
+
+struct dmt_reg {
+    unsigned int :16,
+         dmt_bo:1,
+          dmt_das:1,
+         dmt_doub1:1,
+         dmt_lockbar:1,
+         dmt_dreg:5,
+         dmt_signed:1,
+         dmt_en:4,
+         dmt_write:1,
+         dmt_valid:1;
+};
+#endif 
+
+#endif  _M88100_H_
diff --git a/sys/arch/mvme88k/include/m882xx.h b/sys/arch/mvme88k/include/m882xx.h
new file mode 100644 (file)
index 0000000..4c9759d
--- /dev/null
@@ -0,0 +1,259 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1993-1992 Carnegie Mellon University
+ * 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 ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS 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 Mellon 
+ * the rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * 
+ */
+
+
+#ifndef        __MACHINE_M882XX_H__
+#define        __MACHINE_M882XX_H__
+
+#ifndef ASSEMBLER
+# include <machine/mmu.h>               /* batc_template_t */
+#endif
+
+#include <machine/board.h>
+
+/*
+ *     88200 CMMU definitions
+ */
+#define CMMU_IDR       0x000   /* CMMU id register */
+#define CMMU_SCR       0x004   /* system command register */
+#define CMMU_SSR       0x008   /* system status register */
+#define CMMU_SAR       0x00C   /* system address register */
+#define CMMU_SCTR      0x104   /* system control register */
+#define CMMU_PFSR      0x108   /* P bus fault status register */
+#define CMMU_PFAR      0x10C   /* P bus fault address register */
+#define CMMU_SAPR      0x200   /* supervisor area pointer register */
+#define CMMU_UAPR      0x204   /* user area pointer register */
+#define CMMU_BWP0      0x400   /* block ATC writer port 0 */
+#define CMMU_BWP1      0x404   /* block ATC writer port 1 */
+#define CMMU_BWP2      0x408   /* block ATC writer port 2 */
+#define CMMU_BWP3      0x40C   /* block ATC writer port 3 */
+#define CMMU_BWP4      0x410   /* block ATC writer port 4 */
+#define CMMU_BWP5      0x414   /* block ATC writer port 5 */
+#define CMMU_BWP6      0x418   /* block ATC writer port 6 */
+#define CMMU_BWP7      0x41C   /* block ATC writer port 7 */
+#define CMMU_CDP0      0x800   /* cache data port 0 */
+#define CMMU_CDP1      0x804   /* cache data port 1 */
+#define CMMU_CDP2      0x808   /* cache data port 2 */
+#define CMMU_CDP3      0x80C   /* cache data port 3 */
+#define CMMU_CTP0      0x840   /* cache tag port 0 */
+#define CMMU_CTP1      0x844   /* cache tag port 1 */
+#define CMMU_CTP2      0x848   /* cache tag port 2 */
+#define CMMU_CTP3      0x84C   /* cache tag port 3 */
+#define CMMU_CSSP      0x880   /* cache set status register */
+
+/* 88204 CMMU definitions  */
+#define CMMU_CSSP0     0x880   /* cache set status register */
+#define CMMU_CSSP1     0x890   /* cache set status register */
+#define CMMU_CSSP2     0x8A0   /* cache set status register */
+#define CMMU_CSSP3     0x8B0   /* cache set status register */
+
+/* CMMU systerm commands */
+#define CMMU_FLUSH_USER_LINE           0x30    /* flush PATC */
+#define CMMU_FLUSH_USER_PAGE           0x31
+#define CMMU_FLUSH_USER_SEGMENT                0x32
+#define CMMU_FLUSH_USER_ALL            0x33
+#define CMMU_FLUSH_SUPER_LINE          0x34
+#define CMMU_FLUSH_SUPER_PAGE          0x35
+#define CMMU_FLUSH_SUPER_SEGMENT       0x36
+#define CMMU_FLUSH_SUPER_ALL           0x37
+#define CMMU_PROBE_USER                        0x20    /* probe user address */
+#define CMMU_PROBE_SUPER               0x24    /* probe supervisor address */
+#define CMMU_FLUSH_CACHE_INV_LINE      0x14    /* data cache invalidate */
+#define CMMU_FLUSH_CACHE_INV_PAGE      0x15
+#define CMMU_FLUSH_CACHE_INV_SEGMENT   0x16
+#define CMMU_FLUSH_CACHE_INV_ALL       0x17
+#define CMMU_FLUSH_CACHE_CB_LINE       0x18    /* data cache copyback */
+#define CMMU_FLUSH_CACHE_CB_PAGE       0x19
+#define CMMU_FLUSH_CACHE_CB_SEGMENT    0x1A
+#define CMMU_FLUSH_CACHE_CB_ALL                0x1B
+#define CMMU_FLUSH_CACHE_CBI_LINE      0x1C    /* copyback and invalidate */
+#define CMMU_FLUSH_CACHE_CBI_PAGE      0x1D
+#define CMMU_FLUSH_CACHE_CBI_SEGMENT   0x1E
+#define CMMU_FLUSH_CACHE_CBI_ALL       0x1F
+
+/* CMMU system control command */
+#define CMMU_SCTR_PE   0x00008000      /* parity enable */
+#define CMMU_SCTR_SE   0x00004000      /* snoop enable */
+#define CMMU_SCTR_PR   0x00002000      /* priority arbitration */
+
+/* CMMU P bus fault status */
+#define CMMU_PFSR_SUCCESS      0       /* no fault */
+#define CMMU_PFSR_BERROR       3       /* bus error */
+#define CMMU_PFSR_SFAULT       4       /* segment fault */
+#define CMMU_PFSR_PFAULT       5       /* page fault */
+#define CMMU_PFSR_SUPER                6       /* supervisor violation */
+#define CMMU_PFSR_WRITE                7       /* writer violation */
+
+/* Area Description */
+#define AREA_D_WT      0x00000200      /* write through */
+#define AREA_D_G       0x00000080      /* global */
+#define AREA_D_CI      0x00000040      /* cache inhibit */
+#define AREA_D_TE      0x00000001      /* translation enable */
+
+/* Segment Description */
+#define SEG_D_WT       0x00000200      /* write through */
+#define SEG_D_SP       0x00000100      /* supervisor protection */
+#define SEG_D_G                0x00000080      /* global */
+#define SEG_D_CI       0x00000040      /* cache inhibit */
+#define SEG_D_WP       0x00000004      /* write protect */
+#define SEG_D_V                0x00000001      /* valid */
+
+/*
+ * Flags for cmmu_flush_tlb
+ */
+#define FLUSH_KERNEL    1
+#define FLUSH_USER      0
+#define FLUSH_ALL       ((vm_offset_t)~0)
+
+
+#ifndef        ASSEMBLER
+/*
+ * This file defines the data structures for the mmu.
+ * One major data structure, the page descriptor, is not defined here
+ * but rather in pte.h as struct pte.
+ */
+
+struct area_d {                /* area descriptor */
+    unsigned
+       ad_addr:20,     /* segment table base address */
+              : 2,
+       ad_wt  : 1,     /* write through */
+              : 1,
+       ad_g   : 1,     /* global */
+       ad_ci  : 1,     /* cache inhibit */
+              : 5,
+       ad_te  : 1;     /* translation enable */
+};
+
+struct segment_d {     /* segment descriptor */
+    unsigned
+       sd_addr:20,     /* page table base address */
+              : 2,
+       sd_wt  : 1,     /* write through */ 
+       sd_sp  : 1,     /* supervisor protection */
+       sd_g   : 1,     /* global */
+       sd_ci  : 1,     /* cache inhibit */
+              : 3,
+       sd_wp  : 1,     /* write protect */
+              : 1,
+       sd_v   : 1;     /* valid */
+};
+
+typedef        struct segment_d segment_d_t;
+
+struct pfsr {          /* P bus fault status register */
+    unsigned
+              :13,
+       pfsr_fc: 3,     /* falut code */
+              :16;
+};
+
+struct batc {          /* block address translation register */
+    unsigned
+       batc_lba:13,    /* logical block address */
+       batc_pba:13,    /* physical block address */
+       batc_s  : 1,    /* supervisor */
+       batc_wt : 4,    /* write through */
+       batc_g  : 1,    /* global */
+       batc_ci : 1,    /* cache inhibit */
+       batc_wp : 1,    /* write protect */
+       batc_v  : 1;    /* valid */
+};
+
+/*
+ * Prototypes and stuff for cmmu.c.
+ */
+extern unsigned cpu_sets[MAX_CPUS];
+extern unsigned ncpus;
+extern unsigned cache_policy;
+
+#ifdef CMMU_DEBUG
+ void show_apr(unsigned value);
+ void show_sctr(unsigned value);
+#endif
+
+/*
+ * Prototypes from "motorola/m88k/m88100/cmmu.c"
+ */
+unsigned cmmu_cpu_number(void);
+#if !DDB
+static
+#endif /* !DDB */
+unsigned cmmu_remote_get(unsigned cpu, unsigned r, unsigned data);
+unsigned cmmu_get_idr(unsigned data);
+void cmmu_init(void);
+void cmmu_shutdown_now(void);
+void cmmu_parity_enable(void);
+#if !DDB
+static
+#endif /* !DDB */
+void cmmu_remote_set(unsigned cpu, unsigned r, unsigned data, unsigned x);
+void cmmu_set_sapr(unsigned ap);
+void cmmu_remote_set_sapr(unsigned cpu, unsigned ap);
+void cmmu_set_uapr(unsigned ap);
+void cmmu_flush_tlb(unsigned kernel, vm_offset_t vaddr, int size);
+void cmmu_flush_remote_cache(int cpu, vm_offset_t physaddr, int size);
+void cmmu_flush_cache(vm_offset_t physaddr, int size);
+void cmmu_flush_remote_inst_cache(int cpu, vm_offset_t physaddr, int size);
+void cmmu_flush_inst_cache(vm_offset_t physaddr, int size);
+void cmmu_flush_remote_data_cache(int cpu, vm_offset_t physaddr, int size);
+void cmmu_flush_data_cache(vm_offset_t physaddr, int size);
+
+void cmmu_pmap_activate(
+    unsigned cpu,
+    unsigned uapr,
+    batc_template_t i_batc[BATC_MAX],
+    batc_template_t d_batc[BATC_MAX]);
+
+void cmmu_flush_remote_tlb(
+       unsigned cpu,
+       unsigned kernel,
+       vm_offset_t vaddr,
+       int size);
+
+void cmmu_set_batc_entry(
+     unsigned cpu,
+     unsigned entry_no,
+     unsigned data,   /* 1 = data, 0 = instruction */
+     unsigned value);  /* the value to stuff into the batc */
+
+void cmmu_set_pair_batc_entry(
+     unsigned cpu,
+     unsigned entry_no,
+     unsigned value);  /* the value to stuff into the batc */
+
+#endif /* ASSEMBLER */
+
+#define INST_CMMU 0
+#define DATA_CMMU 1
+
+#define NBSG    (4*1024*1024) /* segment size */
+
+#endif /* __MACHINE_M882XX_H__ */
diff --git a/sys/arch/mvme88k/include/mmu.h b/sys/arch/mvme88k/include/mmu.h
new file mode 100644 (file)
index 0000000..b172c59
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * Ashura Project
+ */
+/*
+ * HISTORY
+ *
+ * Original SCCS ID in ISEDL 
+ * @(#)mmu.h 1.22               90/09/20 19:13:34
+ */
+
+#ifndef        _MACHINE_MMU_
+#define        _MACHINE_MMU_
+
+/* for m88k_pgbytes, m8kk_pgshift */
+#include <machine/vmparam.h> 
+
+
+/*
+ * Parameters which determine the 'geometry' of the M88K page tables in memory.
+ */
+#define SDT_BITS       10      /* M88K segment table size bits */
+#define PDT_BITS       10      /* M88K page table size bits */
+#define PG_BITS                M88K_PGSHIFT    /* M88K hardware page size bits */
+
+/*
+ * Shifts and masks for M88K (hardware) page
+ */
+/* M88K_PGBYTES, PG_SHIFT in vm_param.h */
+#define M88K_PGOFSET   (M88K_PGBYTES-1)        /* offset into M88K page */
+#define M88K_PGMASK    (~M88K_PGOFSET)         /* page mask */ 
+
+/*
+ * Convert byte address to page frame number
+ */
+#define M88K_BTOP(x)   (((unsigned) (x)) >> M88K_PGSHIFT)
+#define M88K_PTOB(x)   (((unsigned) (x)) << M88K_PGSHIFT)
+
+/* 
+ * Round off or truncate to the nearest page. These will work for
+ * either addresses of counts. (i.e. 1 byte round to 1 page bytes).
+ */
+#define M88K_TRUNC_PAGE(x)     (((unsigned) (x) & M88K_PGMASK))
+#define M88K_ROUND_PAGE(x)     M88K_TRUNC_PAGE((x) + M88K_PGOFSET)
+
+/*
+ * M88K area descriptors
+ */
+typedef struct cmmu_apr {
+       unsigned long
+                       st_base:20,     /* segment table base address */
+                       rsvA:2,         /* reserved */
+                       wt:1,           /* writethrough (cache control) */
+                       rsvB:1,         /* reserved */
+                       g:1,            /* global (cache control) */
+                       ci:1,           /* cache inhibit */
+                       rsvC:5,         /* reserved */
+                       te:1;           /* transration enable */
+} cmmu_apr_t;
+
+typedef union apr_template {
+       cmmu_apr_t      field;
+       unsigned long   bits;
+} apr_template_t;
+
+/*
+ * M88K segment descriptors
+ */
+typedef struct sdt_entry {
+       unsigned long
+                       table_addr:20,  /* page table base address */
+                       rsvA:2,         /* reserved */
+                       wt:1,           /* writethrough (cache control) */
+                       sup:1,          /* supervisor protection */
+                       g:1,            /* global (cache control) */
+                       no_cache:1,     /* cache inhibit */
+                       rsvB:3,         /* reserved */
+                       prot:1,         /* write protect */
+                       rsvC:1,         /* reserved */
+                       dtype:1;        /* valid */
+} sdt_entry_t;
+
+typedef union sdt_entry_template {
+       sdt_entry_t     sdt_desc;
+       unsigned long   bits;
+} sdt_entry_template_t;
+
+#define SDT_ENTRY_NULL ((sdt_entry_t *) 0)
+           
+/*
+ * M88K page descriptors
+ */
+typedef struct pt_entry {
+       unsigned long
+                       pfn:20,         /* page frame address */
+                       rsvA:1,         /* reserved */
+                       wired:1,        /* wired bit <<software>> */
+                       wt:1,           /* writethrough (cache control) */
+                       sup:1,          /* supervisor protection */
+                       g:1,            /* global (cache control) */
+                       ci:1,           /* cache inhibit */
+                       rsvB:1,         /* reserved */
+                       modified:1,     /* modified */
+                       pg_used:1,      /* used (referenced) */
+                       prot:1,         /* write protect */
+                       rsvC:1,         /* reserved */
+                       dtype:1;        /* valid */
+} pt_entry_t;
+
+typedef union pte_template {
+       pt_entry_t      pte;
+       unsigned long   bits;
+} pte_template_t;
+
+#define PT_ENTRY_NULL  ((pt_entry_t *) 0)
+
+/*
+ * 88200 PATC (TLB)
+ */
+
+#define PATC_ENTRIES   56
+
+/*
+ * M88K BATC entries
+ */
+typedef struct {
+       unsigned long
+                       lba:13,         /* logical block address */
+                       pba:13,         /* physical block address */
+                       sup:1,          /* supervisor mode bit */
+                       wt:1,           /* writethrough (cache control) */
+                       g:1,            /* global (cache control) */
+                       ci:1,           /* cache inhibit */
+                       wp:1,           /* write protect */
+                       v:1;            /* valid */
+} batc_entry_t;
+
+typedef union batc_template {
+       batc_entry_t    field;
+       unsigned long   bits;
+} batc_template_t;
+
+/*
+ * Parameters and macros for BATC
+ */
+#define BATC_BLKBYTES  (512*1024)      /* 'block' size of a BATC entry mapping */
+#define BATC_BLKSHIFT  19              /* number of bits to BATC shift (log2(BATC_BLKBYTES)) */
+#define BATC_BLKMASK   (BATC_BLKBYTES-1)       /* BATC block mask */
+
+#define BATC_MAX       8               /* number of BATC entries */
+
+#define BATC_BLK_ALIGNED(x)    ((x & BATC_BLKMASK) == 0)
+
+#define M88K_BTOBLK(x) (x >> BATC_BLKSHIFT)
+
+/*
+ * protection codes (prot field)
+ */
+#define M88K_RO                1       /* read only */
+#define M88K_RW                0       /* read/write */
+
+/*
+ * protection codes (sup field)
+ */
+#define M88K_SUPV      1       /* translation can only be done in supervisor mode */
+#define M88K_USER      0       /* translation can be done supv. or user mode */
+
+/*
+ * descriptor types
+ */
+#define DT_INVALID     0
+#define DT_VALID       1
+
+/*
+ * Number of entries in a page table.
+ */
+#define        SDT_ENTRIES     (1<<(SDT_BITS))
+#define PDT_ENTRIES    (1<<(PDT_BITS))
+
+/*
+ * Size in bytes of a single page table.
+ */
+#define SDT_SIZE       (sizeof(sdt_entry_t) * SDT_ENTRIES)
+#define PDT_SIZE       (sizeof(pt_entry_t) * PDT_ENTRIES)
+
+/*
+ * Shifts and masks 
+ */
+#define SDT_SHIFT      (PDT_BITS + PG_BITS)
+#define PDT_SHIFT      (PG_BITS)
+
+#define SDT_MASK       (((1<<SDT_BITS)-1) << SDT_SHIFT)
+#define PDT_MASK       (((1<<PDT_BITS)-1) << PDT_SHIFT)
+
+#define SDT_NEXT(va)   ((va + (1<<SDT_SHIFT)) & SDT_MASK)
+#define PDT_NEXT(va)   ((va + (1<<PDT_SHIFT)) & (SDT_MASK|PDT_MASK))
+
+#define        SDTIDX(va)      ((va & SDT_MASK) >> SDT_SHIFT)
+#define        PDTIDX(va)      ((va & PDT_MASK) >> PDT_SHIFT)
+
+#define SDTENT(map, va)        ((sdt_entry_t *)(map->sdt_vaddr + SDTIDX(va)))
+
+/*
+ * Size of a PDT table group.
+ */
+#define LOG2_PDT_SIZE                  (PDT_BITS + 2)
+#define LOG2_PDT_TABLE_GROUP_SIZE      (PAGE_SHIFT - LOG2_PDT_SIZE)
+#define PDT_TABLE_GROUP_SIZE           (1 << LOG2_PDT_TABLE_GROUP_SIZE)
+#define PT_FREE(tbl)           kmem_free(kernel_map, (vm_offset_t)tbl, PAGE_SIZE)
+
+/*
+ * Va spaces mapped by tables and PDT table group.
+ */
+#define PDT_VA_SPACE                   (PDT_ENTRIES * M88K_PGBYTES)
+#define PDT_TABLE_GROUP_VA_SPACE       (PDT_VA_SPACE * PDT_TABLE_GROUP_SIZE)
+
+/*
+ * Number of sdt entries used to map user and kernel space.
+ */
+#define USER_SDT_ENTRIES       SDTIDX(VM_MIN_KERNEL_ADDRESS)
+#define KERNEL_SDT_ENTRIES     (SDT_ENTRIES - USER_SDT_ENTRIES)
+
+/*
+ * Macros to check if the descriptor is valid.
+ */
+#define SDT_VALID(sd_ptr)      ((sd_ptr)->dtype == DT_VALID)
+#define PDT_VALID(pd_ptr)      ((pd_ptr)->dtype == DT_VALID)
+
+/*
+ * Alignment checks for pages (must lie on page boundaries).
+ */
+#define PAGE_ALIGNED(ad)       (((vm_offset_t)(ad) & ~M88K_PGMASK) == 0)
+#define        CHECK_PAGE_ALIGN(ad,who)        \
+    if (!PAGE_ALIGNED(ad))             \
+       printf("%s: addr  %x not page aligned.\n", who, ad)
+
+/*
+ * Validate PTE's for all hardware pages in a VM page.
+ * "ptes_per_vm_page" should be set in pmap_bootstrap.
+ *
+ * PARAMETERS:
+ *             pt_entry_t      *start;
+ *             unsigned long   template;
+ */
+#define DO_PTES(start, template)                       \
+{                                                      \
+    int i_;                                            \
+    pt_entry_t *p_ = start;                            \
+                                                       \
+    for (i_ = ptes_per_vm_page; i_>0; i_--) {          \
+       *(int *)p_++ = (unsigned long)(template);       \
+       template += M88K_PGBYTES;                       \
+       /* (unsigned long)(template) for m88k C compiler\
+               '90.7.24        Fuzzy           */      \
+    }                                                  \
+}
+
+/*
+ * Flags for cmmu_store() <cmmu.s>
+ */
+#define STORE_CMD      0
+#define STORE_UAPR     4
+#define STORE_SAPR     8
+#define STORE_BATCWP   0x400
+
+#define C_CMMU         0
+#define D_CMMU         0x1000
+
+/*
+ * Parameters for ATC(TLB) fulsh
+ */
+
+#define CMMU_SCR       0x004
+
+#define FLUSH_SUP_ALL  0x37
+#define FLUSH_USR_ALL  0x33
+#define FLUSH_SUP_SEG  0x36
+#define FLUSH_USR_SEG  0x32
+#define FLUSH_SUP_PG   0x35
+#define FLUSH_USR_PG   0x31
+
+/*
+ * Cache coontrol bits for pte
+ */
+#define CACHE_DFL      0
+#define CACHE_INH      0x40
+#define CACHE_GLOBAL   0x80
+#define CACHE_WT       0x200
+
+#define CACHE_MASK     (~(unsigned)(CACHE_INH | CACHE_GLOBAL | CACHE_WT))
+
+/*
+ * Prototype for invalidate_pte found in "motorola/m88k/m88100/misc.s"
+ */
+unsigned invalidate_pte(pt_entry_t *pointer);
+
+extern vm_offset_t kmapva;
+
+#define kvtopte(va)    \
+({                                                                     \
+       sdt_entry_t *sdt;                                               \
+       sdt = (sdt_entry_t *)kmapva + SDTIDX(va) + SDT_ENTRIES;         \
+       (pte_template_t *)(sdt->table_addr << PDT_SHIFT) + PDTIDX(va);  \
+})
+
+
+#define DMA_CACHE_SYNC         0x1
+#define DMA_CACHE_SYNC_INVAL   0x2
+#define DMA_CACHE_INV          0x3
+extern void dma_cachectl(vm_offset_t, int, int);
+
+#endif
+/* endif _MACHINE_MMU_ */
diff --git a/sys/arch/mvme88k/include/param.h b/sys/arch/mvme88k/include/param.h
new file mode 100644 (file)
index 0000000..f5ef483
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: machparam.h 1.11 89/08/14$
+ *
+ *     @(#)param.h     7.8 (Berkeley) 6/28/91
+ *     $Id: param.h,v 1.5 1997/03/03 20:21:06 rahnds Exp $
+ */
+#ifndef _MACHINE_PARAM_H_
+#define _MACHINE_PARAM_H_
+
+#define        MACHINE         "m88k"
+#define MACHINE_ARCH   "m88k"
+#define MID_MACHINE    MID_M88K
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value
+ * for all data types (int, long, ...).   The result is u_int and
+ * must be cast to any desired pointer type. ALIGN() is used for
+ * aligning stack, which needs to be on a double word boundary for
+ * 88k.
+ */
+#define ALIGNBYTES     (sizeof(int) - 1)
+#define        ALIGN(p)        (((u_int)(p) + (sizeof(double) - 1)) & ~(sizeof(double) - 1))
+
+#ifndef NBPG
+#define        NBPG            4096            /* bytes/page */
+#endif /* NBPG */
+#define        PGOFSET         (NBPG-1)        /* byte offset into page */
+#define        PGSHIFT         12              /* LOG2(NBPG) */
+#define        NPTEPG          (NBPG/(sizeof(u_int)))
+
+#define NBSEG          (1<<22)         /* bytes/segment */
+#define        SEGOFSET        (NBSEG-1)       /* byte offset into segment */
+#define        SEGSHIFT        22              /* LOG2(NBSEG) */
+
+/*
+ * 187 Bug uses the bottom 64k. We allocate ptes to map this into the
+ * kernel. But when we link the kernel, we tell it to start linking
+ * past this 64k. How does this change KERNBASE? XXX
+ */
+
+#define        KERNBASE        0x0             /* start of kernel virtual */
+#define        BTOPKERNBASE    ((u_long)KERNBASE >> PGSHIFT)
+
+#define        DEV_BSIZE       512
+#define        DEV_BSHIFT      9               /* log2(DEV_BSIZE) */
+#define BLKDEV_IOSIZE  2048            /* Should this be changed? XXX */
+#define        MAXPHYS         (64 * 1024)     /* max raw I/O transfer size */
+
+#define        CLSIZE          1
+#define        CLSIZELOG2      0
+
+/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */
+#define        SSIZE           1               /* initial stack size/NBPG */
+#define        SINCR           1               /* increment of stack/NBPG */
+#define USPACE         ctob(UPAGES)
+
+#define        UPAGES          3               /* pages of u-area */
+#define        UADDR           0xEEE00000      /* address of u */
+#define        UVPN            (UADDR>>PGSHIFT)/* virtual page number of u */
+#define        KERNELSTACK     (UADDR+UPAGES*NBPG)     /* top of kernel stack */
+
+#define PHYSIO_MAP_START       0xEEF00000
+#define PHYSIO_MAP_SIZE        0x00100000
+#define IOMAP_MAP_START                0xEF000000 /* VME etc */
+#define IOMAP_SIZE             0x018F0000
+#define NIOPMAP                        32
+
+/*
+ * Constants related to network buffer management.
+ * MCLBYTES must be no larger than CLBYTES (the software page size), and,
+ * on machines that exchange pages of input or output buffers with mbuf
+ * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple
+ * of the hardware page size.
+ */
+#define        MSIZE           128             /* size of an mbuf */
+#define        MCLBYTES        1024
+#define        MCLSHIFT        10
+#define        MCLOFSET        (MCLBYTES - 1)
+#ifndef NMBCLUSTERS
+#ifdef GATEWAY
+#define        NMBCLUSTERS     512             /* map size, max cluster allocation */
+#else
+#define        NMBCLUSTERS     256             /* map size, max cluster allocation */
+#endif
+#endif
+
+/*
+ * Size of kernel malloc arena in CLBYTES-sized logical pages
+ */ 
+#ifndef NKMEMCLUSTERS
+#define        NKMEMCLUSTERS   (3072*1024/CLBYTES)
+#endif
+
+/* pages ("clicks") to disk blocks */
+#define        ctod(x) ((x)<<(PGSHIFT-DEV_BSHIFT))
+#define        dtoc(x) ((x)>>(PGSHIFT-DEV_BSHIFT))
+#define        dtob(x) ((x)<<DEV_BSHIFT)
+
+/* pages to bytes */
+#define        ctob(x) ((x)<<PGSHIFT)
+
+/* bytes to pages */
+#define        btoc(x) (((unsigned)(x)+(NBPG-1))>>PGSHIFT)
+
+#define        btodb(bytes)                    /* calculates (bytes / DEV_BSIZE) */ \
+       ((unsigned)(bytes) >> DEV_BSHIFT)
+#define        dbtob(db)                       /* calculates (db * DEV_BSIZE) */ \
+       ((unsigned)(db) << DEV_BSHIFT)
+
+/*
+ * Map a ``block device block'' to a file system block.
+ * This should be device dependent, and should use the bsize
+ * field from the disk label.
+ * For now though just use DEV_BSIZE.
+ */
+#define        bdbtofsb(bn)    ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE))
+#include <machine/psl.h>
+
+#ifdef _KERNEL
+#define        DELAY(x)        delay(x)
+#endif
+
+#ifdef _KERNEL
+extern int cputyp;
+extern int cpumod;
+#endif
+/*
+ * Values for the cputyp variable.
+ */
+#define CPU_187                0x187
+#endif /* !_MACHINE_PARAM_H_ */
diff --git a/sys/arch/mvme88k/include/pcb.h b/sys/arch/mvme88k/include/pcb.h
new file mode 100644 (file)
index 0000000..65437b1
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 1996 Nivas Madhur
+ * Mach Operating System
+ * Copyright (c) 1993-1992 Carnegie Mellon University
+ * 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/* 
+ * Motorola 88100 pcb definitions 
+ *
+ */
+/*
+ */
+#ifndef _PCB_H_
+#define _PCB_H_
+
+/* 
+ * Our PCB is the regular PCB+Save area for kernel frame.
+ * Upon entering kernel mode from user land, save the user context
+ * in the saved_state area - this is passed as the exception frame.
+ * On a context switch, only registers that need to be saved by the
+ * C calling convention and few other regs (pc, psr etc) are saved
+ * in the kernel_state part of the PCB. Typically, trap fames are
+ * save on the stack (by low level handlers or by hardware) but,
+ * we just decided to do it in the PCB.
+ */
+
+/*
+ * This must always be an even number of words long so that our stack
+ * will always be properly aligned (88k need 8 byte alignmet). Also,
+ * place r14 on double word boundary so that we can use st.d while
+ * saving the regs.
+ */
+
+struct m88100_pcb {
+    unsigned pcb_pc;   /* address to return */
+    unsigned pcb_ipl;
+    unsigned pcb_r14;
+    unsigned pcb_r15;
+    unsigned pcb_r16;
+    unsigned pcb_r17;
+    unsigned pcb_r18;
+    unsigned pcb_r19;
+    unsigned pcb_r20;
+    unsigned pcb_r21;
+    unsigned pcb_r22;
+    unsigned pcb_r23;
+    unsigned pcb_r24;
+    unsigned pcb_r25;
+    unsigned pcb_r26;
+    unsigned pcb_r27;
+    unsigned pcb_r28;
+    unsigned pcb_r29;
+    unsigned pcb_r30;
+    unsigned pcb_sp;   /* kernel stack pointer */
+};
+
+
+/*
+ *     m88100_saved_state      this structure corresponds to the state
+ *                             of the user registers as saved on the
+ *                             stack upon kernel entry.  This structure
+ *                             is used internally only.  Since this
+ *                             structure may change from version to
+ *                             version, it is hidden from the user.
+ */
+
+/* This must always be an even number of words long */
+
+struct m88100_saved_state {
+    unsigned r[32];
+    unsigned fpsr;
+    unsigned fpcr;
+    unsigned epsr;
+    unsigned sxip;
+    unsigned snip;
+    unsigned sfip;
+    unsigned ssbr;
+    unsigned dmt0;
+    unsigned dmd0;
+    unsigned dma0;
+    unsigned dmt1;
+    unsigned dmd1;
+    unsigned dma1;
+    unsigned dmt2;
+    unsigned dmd2;
+    unsigned dma2;
+    unsigned fpecr;
+    unsigned fphs1;
+    unsigned fpls1;
+    unsigned fphs2;
+    unsigned fpls2;
+    unsigned fppt;
+    unsigned fprh;
+    unsigned fprl;
+    unsigned fpit;
+    unsigned vector;   /* exception vector number */
+    unsigned mask;     /* interrupt mask level */
+    unsigned mode;     /* interrupt mode */
+    unsigned scratch1; /* used by locore trap handling code */
+    unsigned ipfsr;      /* P BUS status - used in inst fault handling */
+    unsigned dpfsr;      /* P BUS status - used in data fault handling */
+    unsigned pad;      /* alignment */
+};
+
+#define trapframe m88100_saved_state
+
+struct pcb
+{
+  struct m88100_pcb            kernel_state;
+  struct m88100_saved_state    user_state;
+  int                         pcb_onfault;     /* for copyin/copyout faults */
+  int                         pcb_pad;         /* pad it XXX */
+};
+
+typedef        struct pcb      *pcb_t;         /* exported */
+
+/*
+ *     Location of saved user registers for the proc.
+ */
+#define        USER_REGS(p) \
+       (((struct m88100_saved_state *)  (&((p)->p_addr->u_pcb.user_state))))
+/*
+ * The pcb is augmented with machine-dependent additional data for
+ * core dumps.  Note that the trapframe here is a copy of the one
+ * from the top of the kernel stack (included here so that the kernel
+ * stack itself need not be dumped).
+ */
+struct md_coredump {
+       struct  trapframe md_tf;
+};
+
+#endif  _PCB_H_
diff --git a/sys/arch/mvme88k/include/pcctworeg.h b/sys/arch/mvme88k/include/pcctworeg.h
new file mode 100644 (file)
index 0000000..eecc7d4
--- /dev/null
@@ -0,0 +1,146 @@
+/*     $NetBSD$ */
+
+/*
+ * Copyright (c) 1995 Theo de Raadt
+ * 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 Theo de Raadt
+ * 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.
+ */
+
+/*
+ * MVME1x7/16x PCC2 chip: sort of a confused mish-mash of the MC in the 162
+ * and the PCC in the 147
+ */
+struct pcctworeg {
+       volatile u_char         pcc2_chipid;
+       volatile u_char         pcc2_chiprev;
+       volatile u_char         pcc2_genctl;
+       volatile u_char         pcc2_vecbase;   /* irq vector base */
+       volatile u_long         pcc2_t1cmp;     /* timer1 compare */
+       volatile u_long         pcc2_t1count;   /* timer1 count */
+       volatile u_long         pcc2_t2cmp;     /* timer2 compare */
+       volatile u_long         pcc2_t2count;   /* timer2 count */
+       volatile u_char         pcc2_pscalecnt; /* timer prescaler counter */
+       volatile u_char         pcc2_pscaleadj; /* timer prescaler adjust */
+       volatile u_char         pcc2_t2ctl;     /* timer2 ctrl reg */
+       volatile u_char         pcc2_t1ctl;     /* timer1 ctrl reg */
+       volatile u_char         pcc2_gpioirq;   /* gpio irq */
+       volatile u_char         pcc2_gpio;      /* gpio i/o */
+       volatile u_char         pcc2_t2irq;
+       volatile u_char         pcc2_t1irq;
+       volatile u_char         pcc2_sccerr;
+       volatile u_char         pcc2_sccirq;
+       volatile u_char         pcc2_scctx;
+       volatile u_char         pcc2_sccrx;
+       volatile u_char         :8;
+       volatile u_char         :8;
+       volatile u_char         :8;
+       volatile u_char         pcc2_sccmoiack;
+       volatile u_char         :8;
+       volatile u_char         pcc2_scctxiack;
+       volatile u_char         :8;
+       volatile u_char         pcc2_sccrxiack;
+       volatile u_char         pcc2_ieerr;
+       volatile u_char         :8;
+       volatile u_char         pcc2_iectl;
+       volatile u_char         pcc2_ieirq;
+       volatile u_char         pcc2_ncrerr;
+       volatile u_char         :8;
+       volatile u_char         :8;
+       volatile u_char         pcc2_ncrirq;
+       volatile u_char         pcc2_prtairq;
+       volatile u_char         pcc2_prtfirq;
+       volatile u_char         pcc2_prtsirq;
+       volatile u_char         pcc2_prtpirq;
+       volatile u_char         pcc2_prtbirq;
+       volatile u_char         :8;
+       volatile u_char         pcc2_prtstat;
+       volatile u_char         pcc2_prtctl;
+       volatile u_short        pcc2_speed;     /* DO NOT USE */
+       volatile u_short        pcc2_prtdat;
+       volatile u_short        :16;
+       volatile u_char         pcc2_ipl;
+       volatile u_char         pcc2_mask;
+};
+#define PCC2_PCC2CHIP_ADDR     0xFFF42000
+#define PCC2_PCC2CHIP_OFF      0x42000
+#define PCC2_CHIPID            0x20
+
+/*
+ * points to system's PCCTWO. This is not active until the pcctwo0
+ * device has been attached. After that, it gives the virtual address
+ * at which the PCCTWO can be accessed.
+ */
+extern struct pcctworeg *sys_pcc2;
+
+/*
+ * We lock off our interrupt vector at 0x50.
+ */
+#define PCC2_VECBASE           0x50
+#define PCC2_NVEC              12
+
+/*
+ * Vectors we use
+ */
+#define PCC2V_NCR              0x05
+#define PCC2V_IE_ERR           0x06
+#define PCC2V_IE               0x07
+#define PCC2V_TIMER2           0x08
+#define PCC2V_TIMER1           0x09
+#define PCC2V_GPIO             0x0A
+
+#define PCC2_TCTL_CEN          0x01
+#define PCC2_TCTL_COC          0x02
+#define PCC2_TCTL_COVF         0x04
+#define PCC2_TCTL_OVF          0xf0
+
+#define PCC2_GPIO_PLTY         0x80
+#define PCC2_GPIO_EL           0x40
+
+#define PCC2_GPIOCR_OE         0x2
+#define PCC2_GPIOCR_O          0x1
+
+#define PCC2_SCC_AVEC          0x08
+#define PCC2_SCCRX_INHIBIT     (0 << 6)
+#define PCC2_SCCRX_SNOOP       (1 << 6)
+#define PCC2_SCCRX_INVAL       (2 << 6)
+#define PCC2_SCCRX_RESV                (3 << 6)
+
+#define pcc2_timer_us2lim(us)  (us)            /* timer increments in "us" */
+
+#define PCC2_IRQ_IPL           0x07
+#define PCC2_IRQ_ICLR          0x08
+#define PCC2_IRQ_IEN           0x10
+#define PCC2_IRQ_INT           0x20
+
+#define PCC2_GENCTL_FAST       0x01
+#define PCC2_GENCTL_IEN                0x02
+#define PCC2_GENCTL_C040       0x03
+
+#define PCC2_SC_INHIBIT                (0 << 6)
+#define PCC2_SC_SNOOP          (1 << 6)
+#define PCC2_SC_INVAL          (2 << 6)
+#define PCC2_SC_RESV           (3 << 6)
diff --git a/sys/arch/mvme88k/include/pmap.h b/sys/arch/mvme88k/include/pmap.h
new file mode 100644 (file)
index 0000000..ef1fd3b
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ *
+ */
+#ifndef _MACHINE_PMAP_H_
+#define _MACHINE_PMAP_H_
+#define OMRON_PMAP
+
+#include <machine/psl.h>               /* get standard goodies         */
+#include <vm/vm_param.h>
+#include <vm/vm_prot.h>                        /* vm_prot_t                    */
+#include <machine/mmu.h>               /* batc_template_t, BATC_MAX, etc.*/
+#include <machine/pcb.h>               /* pcb_t, etc.*/
+
+typedef struct sdt_entry *sdt_ptr_t;
+
+/*
+ * PMAP structure
+ */
+typedef struct pmap *pmap_t;
+
+struct pmap {
+    sdt_ptr_t          sdt_paddr;      /* physical pointer to sdt */
+    sdt_ptr_t          sdt_vaddr;      /* virtual pointer to sdt */
+    int                        ref_count;      /* reference count */
+
+    struct pmap_statistics stats;      /* pmap statistics */
+
+#ifdef DEBUG
+    pmap_t             next;
+    pmap_t             prev;
+#endif
+
+   /* for OMRON_PMAP */
+   batc_template_t i_batc[BATC_MAX];  /* instruction BATCs */
+   batc_template_t d_batc[BATC_MAX];  /* data BATCs */
+   /* end OMRON_PMAP */
+
+}; 
+
+#include <vm/vm.h>
+
+#define PMAP_NULL ((pmap_t) 0)
+
+extern pmap_t  kernel_pmap;
+
+#define PMAP_ACTIVATE(pmap, th, my_cpu)        _pmap_activate(pmap, th, my_cpu)
+#define PMAP_DEACTIVATE(pmap, th, my_cpu) _pmap_deactivate(pmap, th, my_cpu)
+
+#define PMAP_CONTEXT(pmap, thread)
+
+#define pmap_resident_count(pmap) ((pmap)->stats.resident_count)
+
+/* Used in builtin/device_pager.c */
+#define pmap_phys_address(frame)        ((vm_offset_t) (M88K_PTOB(frame)))
+
+/* Used in kern/mach_timedev.c */
+#define pmap_phys_to_frame(phys)        ((int) (M88K_BTOP(phys)))
+
+/*
+ * Since Our PCB has no infomation about the mapping,
+ * we have nothing to do in PMAP_PCB_INITIALIZE.
+ * XXX
+ */
+/* Used in machine/pcb.c */
+#define PMAP_PCB_INITIALIZE(x)
+
+/*
+ * Modes used when calling pmap_cache_fulsh().
+ */
+#define        FLUSH_CACHE             0
+#define        FLUSH_CODE_CACHE        1
+#define        FLUSH_DATA_CACHE        2
+#define        FLUSH_LOCAL_CACHE       3
+#define        FLUSH_LOCAL_CODE_CACHE  4
+#define        FLUSH_LOCAL_DATA_CACHE  5
+
+/**************************************************************************/
+/*** Prototypes for public functions defined in pmap.c ********************/
+/**************************************************************************/
+
+void _pmap_activate(pmap_t pmap, pcb_t, int my_cpu);
+void _pmap_deactivate(pmap_t pmap, pcb_t, int my_cpu);
+void pmap_activate(pmap_t my_pmap, pcb_t);
+void pmap_deactivate(pmap_t pmap, pcb_t);
+int pmap_check_transaction(pmap_t pmap, vm_offset_t va, vm_prot_t type);
+
+vm_offset_t pmap_map_batc(
+      vm_offset_t virt,
+      vm_offset_t start,
+      vm_offset_t end,
+      vm_prot_t prot,
+      unsigned cmode);
+
+#ifdef JUNK
+int pmap_attribute(
+    pmap_t pmap,
+    vm_offset_t address,
+    vm_size_t size,
+    vm_machine_attribute_t attribute,
+    vm_machine_attribute_val_t* value);  /* IN/OUT */
+#endif /* JUNK */
+
+void pmap_bootstrap(
+    vm_offset_t load_start, /* IN */
+    vm_offset_t *phys_start, /* IN/OUT */
+    vm_offset_t *phys_end, /* IN */
+    vm_offset_t *virt_start, /* OUT */
+    vm_offset_t *virt_end); /* OUT */
+
+pt_entry_t *pmap_pte(pmap_t map, vm_offset_t virt);
+void pmap_cache_ctrl(pmap_t pmap, vm_offset_t s, vm_offset_t e, unsigned mode);
+void pmap_zero_page(vm_offset_t phys);
+void pmap_remove_all(vm_offset_t phys);
+vm_offset_t pmap_extract_unlocked(pmap_t pmap, vm_offset_t va);
+pmap_t pmap_kernel(void);
+void copy_to_phys(vm_offset_t srcva, vm_offset_t dstpa, int bytecount);
+void copy_from_phys(vm_offset_t srcpa, vm_offset_t dstva, int bytecount);
+void pmap_redzone(pmap_t pmap, vm_offset_t va);
+boolean_t pmap_verify_free(vm_offset_t phys);
+boolean_t pmap_valid_page(vm_offset_t p);
+void icache_flush(vm_offset_t pa);
+void pmap_dcache_flush(pmap_t pmap, vm_offset_t va);
+void pmap_cache_flush(pmap_t pmap, vm_offset_t virt, int bytes, int mode);
+void pmap_print (pmap_t pmap);
+void pmap_print_trace (pmap_t pmap, vm_offset_t va, boolean_t long_format);
+
+#if 0
+#ifdef OMRON_PMAP
+ void pmap_set_batc(
+    pmap_t pmap,
+    boolean_t data,
+    int i,
+    vm_offset_t va,
+    vm_offset_t pa,
+    boolean_t super,
+    boolean_t wt,
+    boolean_t global,
+    boolean_t ci,
+    boolean_t wp,
+    boolean_t valid);
+
+ void use_batc(
+    task_t task, 
+    boolean_t data,         /* for data-cmmu ? */
+    int i,                  /* batc number */
+    vm_offset_t va,         /* virtual address */
+    vm_offset_t pa,         /* physical address */
+    boolean_t s,            /* for super-mode ? */
+    boolean_t wt,           /* is writethrough */
+    boolean_t g,            /* is global ? */
+    boolean_t ci,           /* is cache inhibited ? */
+    boolean_t wp,           /* is write-protected ? */
+    boolean_t v);           /* is valid ? */
+#endif
+#endif /* 0 */
+
+#endif /* endif  _MACHINE_PMAP_H_ */
diff --git a/sys/arch/mvme88k/include/pmap_table.h b/sys/arch/mvme88k/include/pmap_table.h
new file mode 100644 (file)
index 0000000..5557891
--- /dev/null
@@ -0,0 +1,44 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * 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 ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS 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 Mellon 
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * HISTORY
+ */
+
+
+/* an entry is considered invalid if pm_size = 0 */
+/* end of list is indicated by pm_size 0xffffffff */
+
+typedef struct {
+  vm_offset_t  phys_start;   /* in bytes */
+  vm_offset_t   virt_start;   /* in bytes */
+  unsigned int size;      /* in bytes */
+  unsigned int  prot;        /* vm_prot_read, vm_prot_write */
+  unsigned int  cacheability; /* none, writeback, normal */
+} pmap_table_entry;
+
+typedef pmap_table_entry *pmap_table_t;
+
diff --git a/sys/arch/mvme88k/include/proc.h b/sys/arch/mvme88k/include/proc.h
new file mode 100644 (file)
index 0000000..a58ed3c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)proc.h      8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: proc.h,v 1.6 92/11/26 02:04:41 torek Exp  (LBL)
+ * $Id: proc.h,v 1.3 1997/03/03 20:21:10 rahnds Exp $
+ */
+
+#include <machine/pcb.h>
+#include <machine/mmu.h>
+
+/*
+ * Machine-dependent part of the proc structure for VME1X7.
+ */
+struct mdproc {
+       struct  trapframe *md_tf;       /* trap/syscall registers */
+       struct  fpstate *md_fpstate;    /* fpu state, if any; always resident */
+       int     md_upte[UPAGES];        /* ptes for mapping u page */
+};
diff --git a/sys/arch/mvme88k/include/profile.h b/sys/arch/mvme88k/include/profile.h
new file mode 100644 (file)
index 0000000..84dd1e1
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1996 Nivas Madhur
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)profile.h     8.1 (Berkeley) 6/11/93
+ *     $Id: profile.h,v 1.5 1997/03/03 20:21:11 rahnds Exp $
+ */
+
+#define        _MCOUNT_DECL static inline void _mcount
+
+#define        MCOUNT \
+extern void mcount() asm("mcount");                                    \
+void                                                                   \
+mcount()                                                               \
+{                                                                      \
+       int selfret;                                                    \
+       register int callerret;                                         \
+       /*                                                              \
+        * find the return address for mcount,                          \
+        * and the return address for mcount's caller.                  \
+        *                                                              \
+        * selfret = ret pushed by mcount call                          \
+        */                                                             \
+       asm volatile("st r1,%0" : "=m" (selfret));                      \
+       /*                                                              \
+        * callerret = ret pushed by call into self.                    \
+        */                                                             \
+       /*                                                              \
+        * This may not be right. It all depends on where the           \
+        * caller stores the return address. XXX                        \
+        */                                                             \
+       asm volatile("addu       r10,r31,48");                          \
+       asm volatile("ld %0,r10,36" : "=r" (callerret));                \
+       _mcount(callerret, selfret);                                    \
+}
+
+#ifdef KERNEL
+/*
+ * Note that we assume splhigh() and splx() cannot call mcount()
+ * recursively.
+ */
+#define        MCOUNT_ENTER    s = splhigh()
+#define        MCOUNT_EXIT     splx(s)
+#endif /* KERNEL */
diff --git a/sys/arch/mvme88k/include/psl.h b/sys/arch/mvme88k/include/psl.h
new file mode 100644 (file)
index 0000000..9205c93
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ *
+ */
+#ifndef __M88K_M88100_PSL_H__
+#define __M88K_M88100_PSL_H__
+
+/* needs major cleanup - XXX nivas */
+
+#if 0
+spl0 is a function by itself. I really am serious about the clean up
+above...
+#define spl0()         spln(0)
+#endif /* 0 */
+#define spl1()         setipl(1)
+#define spl2()         setipl(2)
+#define spl3()         setipl(3)
+#define spl4()         setipl(4)
+#define spl5()         setipl(5)
+#define spl6()         setipl(6)
+#define spl7()         setipl(7)
+
+/*
+ * IPL levels.
+ * We use 6 as IPL_HIGH so that abort can be programmed at 7 so that
+ * it is always possible to break into the system unless interrupts
+ * are disabled.
+ */
+
+#define IPL_NONE       0
+#define IPL_SOFTCLOCK  1
+#define IPL_SOFTNET    1
+#define IPL_BIO                2
+#define IPL_NET                3
+#define IPL_TTY                3
+#define IPL_CLOCK      5
+#define IPL_STATCLOCK  5
+#define IPL_IMP                6
+#define IPL_VM         6
+#define IPL_HIGH       6
+#define IPL_SCHED      6
+#define IPL_NMI                7
+#define IPL_ABORT      7
+
+#define splnone                spl0
+#define splsoftclock() setipl(IPL_SOFTCLOCK)
+#define splsoftnet()   setipl(IPL_SOFTNET)
+#define splbio()       setipl(IPL_BIO)
+#define splnet()       setipl(IPL_NET)
+#define spltty()       setipl(IPL_TTY)
+#define splclock()     setipl(IPL_CLOCK)
+#define splstatclock() setipl(IPL_STATCLOCK)
+#define splimp()       setipl(IPL_IMP)
+#define splvm()                setipl(IPL_VM)
+#define splhigh()      setipl(IPL_HIGH)
+#define splsched()     setipl(IPL_SCHED)
+
+#define splx(x)                ((x) ? setipl((x)) : spl0())
+
+/* 
+ * 88100 control registers
+ */
+
+/*
+ * processor identification register (PID)
+ */
+#define PID_ARN                0x0000FF00U     /* architectural revision number */
+#define PID_VN         0x000000FEU     /* version number */
+#define PID_MC         0x00000001U     /* master/checker */
+
+/*
+ * processor status register
+ */
+#define PSR_MODE       0x80000000U     /* supervisor/user mode */
+#define PSR_BO         0x40000000U     /* byte-ordering 0:big 1:little */
+#define PSR_SER                0x20000000U     /* serial mode */
+#define PSR_C          0x10000000U     /* carry */
+#define PSR_SFD                0x000003F0U     /* SFU disable */
+#define PSR_SFD1       0x00000008U     /* SFU1 (FPU) disable */
+#define PSR_MXM                0x00000004U     /* misaligned access enable */
+#define PSR_IND                0x00000002U     /* interrupt disable */
+#define PSR_SFRZ       0x00000001U     /* shadow freeze */
+
+/*
+ *     This is used in ext_int() and hard_clock().
+ */
+#define PSR_IPL                0x00001000      /* for basepri */
+#define PSR_IPL_LOG    12              /* = log2(PSR_IPL) */
+
+#define PSR_MODE_LOG   31              /* = log2(PSR_MODE) */
+#define PSR_BO_LOG     30              /* = log2(PSR_BO) */
+#define PSR_SER_LOG    29              /* = log2(PSR_SER) */
+#define PSR_SFD1_LOG   3               /* = log2(PSR_SFD1) */
+#define PSR_MXM_LOG    2               /* = log2(PSR_MXM) */
+#define PSR_IND_LOG    1               /* = log2(PSR_IND) */
+#define PSR_SFRZ_LOG   0               /* = log2(PSR_SFRZ) */
+
+#define PSR_SUPERVISOR (PSR_MODE | PSR_SFD)
+#define PSR_USER       (PSR_SFD)
+#define PSR_SET_BY_USER        (PSR_BO | PSR_SER | PSR_C | PSR_MXM)
+
+#ifndef        ASSEMBLER
+struct psr {
+    unsigned
+       psr_mode: 1,
+       psr_bo  : 1,
+       psr_ser : 1,
+       psr_c   : 1,
+               :18,
+       psr_sfd : 6,
+       psr_sfd1: 1,
+       psr_mxm : 1,
+       psr_ind : 1,
+       psr_sfrz: 1;
+};
+#endif 
+
+#define FIP_V          0x00000002U     /* valid */
+#define FIP_E          0x00000001U     /* exception */
+#define FIP_ADDR       0xFFFFFFFCU     /* address mask */
+#define NIP_V          0x00000002U     /* valid */
+#define NIP_E          0x00000001U     /* exception */
+#define NIP_ADDR       0xFFFFFFFCU     /* address mask */
+#define XIP_V          0x00000002U     /* valid */
+#define XIP_E          0x00000001U     /* exception */
+#define XIP_ADDR       0xFFFFFFFCU     /* address mask */
+
+#endif /* __M88K_M88100_PSL_H__ */
+
diff --git a/sys/arch/mvme88k/include/ptrace.h b/sys/arch/mvme88k/include/ptrace.h
new file mode 100644 (file)
index 0000000..ff20fff
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ptrace.h    8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: ptrace.h,v 1.6 92/11/26 02:04:43 torek Exp  (LBL)
+ * $Id: ptrace.h,v 1.3 1997/03/03 20:21:13 rahnds Exp $
+ */
+
+/*
+ * m88k-dependent ptrace definitions.
+ */
+#define        PT_GETREGS      (PT_FIRSTMACH + 0)
+#define        PT_SETREGS      (PT_FIRSTMACH + 1)
+#define        PT_GETFPREGS    (PT_FIRSTMACH + 2)
+#define        PT_SETFPREGS    (PT_FIRSTMACH + 3)
diff --git a/sys/arch/mvme88k/include/reg.h b/sys/arch/mvme88k/include/reg.h
new file mode 100644 (file)
index 0000000..3d5034c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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 <machine/pcb.h>
+
+struct reg {
+    unsigned r_r[32];
+    unsigned r_fpsr;
+    unsigned r_fpcr;
+    unsigned r_epsr;
+    unsigned r_sxip;
+    unsigned r_snip;
+    unsigned r_sfip;
+    unsigned r_ssbr;
+    unsigned r_dmt0;
+    unsigned r_dmd0;
+    unsigned r_dma0;
+    unsigned r_dmt1;
+    unsigned r_dmd1;
+    unsigned r_dma1;
+    unsigned r_dmt2;
+    unsigned r_dmd2;
+    unsigned r_dma2;
+    unsigned r_fpecr;
+    unsigned r_fphs1;
+    unsigned r_fpls1;
+    unsigned r_fphs2;
+    unsigned r_fpls2;
+    unsigned r_fppt;
+    unsigned r_fprh;
+    unsigned r_fprl;
+    unsigned r_fpit;
+    unsigned r_vector;   /* exception vector number */
+    unsigned r_mask;      /* interrupt mask level */
+    unsigned r_mode;     /* interrupt mode */
+    unsigned r_scratch1; /* used by locore trap handling code */
+    unsigned r_pad;      /* to make an even length */
+} ;
+
+struct fpreg {
+    unsigned fp_fpecr;
+    unsigned fp_fphs1;
+    unsigned fp_fpls1;
+    unsigned fp_fphs2;
+    unsigned fp_fpls2;
+    unsigned fp_fppt;
+    unsigned fp_fprh;
+    unsigned fp_fprl;
+    unsigned fp_fpit;
+};
diff --git a/sys/arch/mvme88k/include/setjmp.h b/sys/arch/mvme88k/include/setjmp.h
new file mode 100644 (file)
index 0000000..ac2959d
--- /dev/null
@@ -0,0 +1,7 @@
+/*     $NetBSD: setjmp.h,v 1.1 1994/12/20 10:37:10 cgd Exp $   */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ */
+
+#define        _JBLEN  22              /* size, in longs, of a jmp_buf */
diff --git a/sys/arch/mvme88k/include/signal.h b/sys/arch/mvme88k/include/signal.h
new file mode 100644 (file)
index 0000000..82152bb
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ */
+typedef int sig_atomic_t;
+
+/*
+ * Information pushed on stack when a signal is delivered.
+ * This is used by the kernel to restore state following
+ * execution of the signal handler. It is also made available
+ * to the handler to allow it to restore state properly if
+ * a non-standard exit is performed.
+ *
+ * All machines must have an sc_onstack and sc_mask.
+ */
+struct  sigcontext {
+        int     sc_onstack;             /* sigstack state to restore */
+        int     sc_mask;                /* signal mask to restore */
+       /* begin machine dependent portion */
+       int     sc_regs[32];
+#define        sc_sp   sc_regs[31]
+       int     sc_xip;
+       int     sc_nip;
+       int     sc_fip;
+       int     sc_ps;
+       int     sc_fpsr;
+       int     sc_fpcr;
+       int     sc_ssbr;
+       int     sc_dmt0;
+       int     sc_dmd0;
+       int     sc_dma0;
+       int     sc_dmt1;
+       int     sc_dmd1;
+       int     sc_dma1;
+       int     sc_dmt2;
+       int     sc_dmd2;
+       int     sc_dma2;
+       int     sc_fpecr;
+       int     sc_fphs1;
+       int     sc_fpls1;
+       int     sc_fphs2;
+       int     sc_fpls2;
+       int     sc_fppt;
+       int     sc_fprh;
+       int     sc_fprl;
+       int     sc_fpit;
+       int     sc_xxxx;        /* padd to double word boundary */
+};
diff --git a/sys/arch/mvme88k/include/stdarg.h b/sys/arch/mvme88k/include/stdarg.h
new file mode 100644 (file)
index 0000000..7b1ff19
--- /dev/null
@@ -0,0 +1,177 @@
+/* This file has local changes by MOTOROLA
+Thu Sep  9 09:06:29 CDT 1993 Dale Rahn (drahn@pacific)
+       * (gstdarg.h, gvarargs.h) C-Front requires all builtins to
+       be defined.  This is to insert these definitions if
+       __cplusplus is defined but not using the G++ compiler.
+ */
+/* stdarg.h for GNU.
+   Note that the type used in va_arg is supposed to match the
+   actual type **after default promotions**.
+   Thus, va_arg (..., short) is not valid.  */
+
+#ifndef _STDARG_H
+#ifndef _ANSI_STDARG_H_
+#ifndef __need___va_list
+#define _STDARG_H
+#define _ANSI_STDARG_H_
+#endif /* not __need___va_list */
+#undef __need___va_list
+
+#ifndef __GNUC__
+/* Use the system's macros with the system's compiler.
+   This is relevant only when building GCC with some other compiler.  */
+#include <stdarg.h>
+#else
+#ifdef __clipper__
+#include <va-clipper.h>
+#else
+#ifdef __m88k__
+#include <machine/va-m88k.h>
+#else
+#ifdef __i860__
+#include <va-i860.h>
+#else
+#ifdef __hppa__
+#include <va-pa.h>
+#else
+#ifdef __mips__
+#include <va-mips.h>
+#else
+#ifdef __sparc__
+#include <va-sparc.h>
+#else
+#ifdef __i960__
+#include <va-i960.h>
+#else
+#ifdef __alpha__
+#include <va-alpha.h>
+#else
+
+/* Define __gnuc_va_list.  */
+
+#ifndef __GNUC_VA_LIST
+#define __GNUC_VA_LIST
+#if defined(__svr4__) || defined(_AIX) || defined(_M_UNIX)
+typedef char *__gnuc_va_list;
+#else
+typedef void *__gnuc_va_list;
+#endif
+#endif
+
+/* Define the standard macros for the user,
+   if this invocation was from the user program.  */
+#ifdef _STDARG_H
+
+/* Amount of space required in an argument list for an arg of type TYPE.
+   TYPE may alternatively be an expression whose type is used.  */
+
+#define __va_rounded_size(TYPE)  \
+  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+
+#define va_start(AP, LASTARG)                                          \
+ (AP = ((__gnuc_va_list) __builtin_next_arg ()))
+
+#undef va_end
+void va_end (__gnuc_va_list);          /* Defined in libgcc.a */
+#define va_end(AP)
+
+/* We cast to void * and then to TYPE * because this avoids
+   a warning about increasing the alignment requirement.  */
+
+#if defined (__arm__) || defined (__i386__) || defined (__ns32000__) || defined (__vax__)
+/* This is for little-endian machines; small args are padded upward.  */
+#define va_arg(AP, TYPE)                                               \
+ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),    \
+  *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
+#else /* big-endian */
+/* This is for big-endian machines; small args are padded downward.  */
+#define va_arg(AP, TYPE)                                               \
+ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),    \
+  *((TYPE *) (void *) ((char *) (AP) - ((sizeof (TYPE) < 4             \
+                                        ? sizeof (TYPE)                \
+                                        : __va_rounded_size (TYPE))))))
+#endif /* big-endian */
+#endif /* _STDARG_H */
+
+#endif /* not alpha */
+#endif /* not i960 */
+#endif /* not sparc */
+#endif /* not mips */
+#endif /* not hppa */
+#endif /* not i860 */
+#endif /* not m88k */
+#endif /* not clipper */
+
+#ifdef _STDARG_H
+/* Define va_list, if desired, from __gnuc_va_list. */
+/* We deliberately do not define va_list when called from
+   stdio.h, because ANSI C says that stdio.h is not supposed to define
+   va_list.  stdio.h needs to have access to that data type, 
+   but must not use that name.  It should use the name __gnuc_va_list,
+   which is safe because it is reserved for the implementation.  */
+
+#ifdef _HIDDEN_VA_LIST  /* On OSF1, this means varargs.h is "half-loaded".  */
+#undef _VA_LIST
+#endif
+
+#ifdef _BSD_VA_LIST_
+#undef _BSD_VA_LIST_
+#define _BSD_VA_LIST_  __gnuc_va_list
+#endif /* _BSD_VA_LIST_ */
+
+#ifdef __svr4__
+/* SVR4.2 uses _VA_LIST for an internal alias for va_list,
+   so we must avoid testing it and setting it here.
+   SVR4 uses _VA_LIST as a flag in stdarg.h, but we should
+   have no conflict with that.  */
+#ifndef _VA_LIST_
+#define _VA_LIST_
+#ifdef __i860__
+#ifndef _VA_LIST
+#define _VA_LIST va_list
+#endif
+#endif /* __i860__ */
+typedef __gnuc_va_list va_list;
+#endif /* _VA_LIST_ */
+#else /* not __svr4__ */
+
+/* The macro _VA_LIST_ is the same thing used by this file in Ultrix.
+   But on BSD NET2 we must not test or define or undef it.
+   (Note that the comments in NET 2's ansi.h
+   are incorrect for _VA_LIST_--see stdio.h!)  */
+#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____)
+/* The macro _VA_LIST is used in SCO Unix 3.2.  */
+#ifndef _VA_LIST
+/* The macro _VA_LIST_T_H is used in the Bull dpx2  */
+#ifndef _VA_LIST_T_H
+#define _VA_LIST_T_H
+#if !(defined (__BSD_NET2__) || defined (____386BSD____))
+#define _VA_LIST_
+#endif
+#define _VA_LIST
+typedef __gnuc_va_list va_list;
+#endif /* not _VA_LIST_T_H */
+#endif /* not _VA_LIST */
+#endif /* not _VA_LIST_ */
+
+#endif /* not __svr4__ */
+
+#if defined(__cplusplus) && !defined(__GNUG__)
+
+/* This is added to work with AT&T C++. */
+extern "C" {
+      char            *__builtin_next_arg(void);
+      __gnuc_va_list  *__builtin_saveregs(void);
+      void            *__builtin_saveregs2(int);
+      int             *__builtin_argptr(void);
+      int             __builtin_argsize(void);
+      int             __builtin_classify_type(...);
+      int             __alignof__(...);
+}
+#endif
+
+#endif /* _STDARG_H */
+
+#endif /* __GNUC__ */
+#endif /* not _ANSI_STDARG_H_ */
+#endif /* not _STDARG_H */
diff --git a/sys/arch/mvme88k/include/trap.h b/sys/arch/mvme88k/include/trap.h
new file mode 100644 (file)
index 0000000..df565c0
--- /dev/null
@@ -0,0 +1,71 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * 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 ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS 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 Mellon 
+ * the rights to redistribute these changes.
+ */
+/*
+ * Trap codes 
+ */
+
+#ifndef _M88K_TRAP_H 
+#define _M88K_TRAP_H  1
+
+/*
+ * Trap type values
+ */
+
+#define T_RESADFLT     0               /* reserved addressing fault */
+#define T_PRIVINFLT    1               /* privileged instruction fault */
+#define T_RESOPFLT     2               /* reserved operand fault */
+
+/* End of known constants */
+
+#define T_INSTFLT      3               /* instruction access exception */
+#define T_DATAFLT      4               /* data access exception */
+#define T_MISALGNFLT   5               /* misaligned access exception */
+#define T_ILLFLT       6               /* unimplemented opcode exception */
+#define T_BNDFLT       7               /* bounds check violation exception */
+#define T_ZERODIV      8               /* illegal divide exception */
+#define T_OVFFLT       9               /* integer overflow exception */
+#define T_ERRORFLT     10              /* error exception */
+#define T_FPEPFLT      11              /* floating point precise exception */
+#define T_FPEIFLT      12              /* floating point imprecise exception */
+#define        T_ASTFLT        13              /* software trap */
+#if    DDB
+#define        T_KDB_ENTRY     14              /* force entry to kernel debugger */
+#define T_KDB_BREAK    15              /* break point hit */
+#define T_KDB_TRACE    16              /* trace */
+#endif /* DDB */
+#define T_UNKNOWNFLT   17              /* unknown exception */
+#define T_SIGTRAP      18              /* generate SIGTRAP */
+#define T_SIGSYS       19              /* generate SIGSYS */
+#define        T_STEPBPT       20              /* special breakpoint for single step */
+#define        T_USERBPT       21              /* user set breakpoint (for debugger) */
+#define        T_SYSCALL       22              /* Syscall */
+#define T_USER         23              /* user mode fault */
+#if    DDB
+#define        T_KDB_WATCH     24              /* watchpoint hit */
+#endif /* DDB */
+
+#endif  _M88K_TRAP_H 
+
diff --git a/sys/arch/mvme88k/include/types.h b/sys/arch/mvme88k/include/types.h
new file mode 100644 (file)
index 0000000..f8d63e9
--- /dev/null
@@ -0,0 +1,83 @@
+/*     $NetBSD: types.h,v 1.7 1995/07/05 17:46:11 pk Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)types.h     8.1 (Berkeley) 6/11/93
+ */
+
+#ifndef        _MACHTYPES_H_
+#define        _MACHTYPES_H_
+
+#include <sys/cdefs.h>
+
+#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
+typedef struct _physadr {
+       short r[1];
+} *physadr;
+
+typedef struct label_t {
+       int val[22];
+} label_t;
+#endif
+
+typedef        unsigned long   vm_offset_t;
+typedef        unsigned long   vm_size_t;
+
+/*
+ * Basic integral types.  Omit the typedef if
+ * not possible for a machine/compiler combination.
+ */
+#define        __BIT_TYPES_DEFINED__
+typedef        __signed char              int8_t;
+typedef        unsigned char            u_int8_t;
+typedef        short                     int16_t;
+typedef        unsigned short          u_int16_t;
+typedef        int                       int32_t;
+typedef        unsigned int            u_int32_t;
+typedef        long long                 int64_t;
+typedef        unsigned long long      u_int64_t;
+
+typedef int32_t                        register_t;
+
+#define        __BDEVSW_DUMP_OLD_TYPE
+
+#endif /* _MACHTYPES_H_ */
diff --git a/sys/arch/mvme88k/include/va-m88k.h b/sys/arch/mvme88k/include/va-m88k.h
new file mode 100644 (file)
index 0000000..caa77c3
--- /dev/null
@@ -0,0 +1,85 @@
+/* This file has local changes by MOTOROLA
+Thu Sep  9 09:06:29 CDT 1993 Dale Rahn (drahn@pacific)
+       * Due to C-Front's usage of __alignof__ builtin the
+       usage of it must be changed to have an object of that type
+       as the argument not just the type.
+ */
+/* GNU C varargs support for the Motorola 88100  */
+
+/* Define __gnuc_va_list.  */
+
+#ifndef __GNUC_VA_LIST
+#define __GNUC_VA_LIST
+
+typedef struct
+{
+  int  __va_arg;               /* argument number */
+  int *__va_stk;               /* start of args passed on stack */
+  int *__va_reg;               /* start of args passed in regs */
+} __gnuc_va_list;
+#endif /* not __GNUC_VA_LIST */
+
+/* If this is for internal libc use, don't define anything but
+   __gnuc_va_list.  */
+#if defined (_STDARG_H) || defined (_VARARGS_H)
+
+#ifdef _STDARG_H /* stdarg.h support */
+
+#if __GNUC__ > 1 /* GCC 2.0 and beyond */
+#define va_start(AP,LASTARG) ((AP) = *(__gnuc_va_list *)__builtin_saveregs())
+#else
+#define va_start(AP,LASTARG) \
+  ( (AP).__va_reg = (int *) __builtin_saveregs2(0), \
+    (AP).__va_stk = (int *) __builtin_argptr(), \
+    (AP).__va_arg = (int) (__builtin_argsize() + 3) / 4 )
+#endif
+
+#else /* varargs.h support */
+
+#if __GNUC__ > 1 /* GCC 2.0 and beyond */
+#define va_start(AP) ((AP) = *(__gnuc_va_list *)__builtin_saveregs())
+#else
+#define va_start(AP) \
+  ( (AP).__va_reg = (int *) __builtin_saveregs2(1), \
+    (AP).__va_stk = (int *) __builtin_argptr(), \
+    (AP).__va_arg = (int) (__builtin_argsize() - 4 + 3) / 4 )
+#endif
+#define va_alist __va_1st_arg
+#define va_dcl register int va_alist;
+
+#endif /* _STDARG_H */
+
+/* Avoid trouble between this file and _int_varargs.h under DG/UX.  This file
+   can be included by <stdio.h> and others and provides definitions of
+   __va_size and __va_reg_p and  a va_list typedef.  Avoid defining va_list
+   again with _VA_LIST.  */
+#ifdef __INT_VARARGS_H
+#undef __va_size
+#undef __va_reg_p
+#define __gnuc_va_list va_list
+#define _VA_LIST
+#else
+/* Similarly, if this gets included first, do nothing in _int_varargs.h.  */
+#define __INT_VARARGS_H
+#endif
+
+#define __va_reg_p(TYPE) \
+  (__builtin_classify_type(*(TYPE *)0) < 12 \
+   ? sizeof(TYPE) <= 8 : sizeof(TYPE) == 4 && __alignof__(*(TYPE *)0) == 4)
+
+#define        __va_size(TYPE) ((sizeof(TYPE) + 3) >> 2)
+
+/* We cast to void * and then to TYPE * because this avoids
+   a warning about increasing the alignment requirement.  */
+#define va_arg(AP,TYPE)                                                           \
+  ( (AP).__va_arg = (((AP).__va_arg + (1 << (__alignof__(*(TYPE *)0) >> 3)) - 1) \
+                    & ~((1 << (__alignof__(*(TYPE *)0) >> 3)) - 1))       \
+    + __va_size(TYPE),                                                    \
+    *((TYPE *) (void *) ((__va_reg_p(TYPE)                                \
+                         && (AP).__va_arg < 8 + __va_size(TYPE)           \
+                         ? (AP).__va_reg : (AP).__va_stk)                 \
+                        + ((AP).__va_arg - __va_size(TYPE)))))
+
+#define va_end(AP)
+
+#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/sys/arch/mvme88k/include/varargs.h b/sys/arch/mvme88k/include/varargs.h
new file mode 100644 (file)
index 0000000..aeef84f
--- /dev/null
@@ -0,0 +1,191 @@
+/* This file has local changes by MOTOROLA
+Thu Sep  9 09:06:29 CDT 1993 Dale Rahn (drahn@pacific)
+       * (gstdarg.h, gvarargs.h) C-Front requires all builtins to
+       be defined.  This is to insert these definitions if
+       __cplusplus is defined but not using the G++ compiler.
+ */
+#ifndef __GNUC__
+/* Use the system's macros with the system's compiler.  */
+#include <varargs.h>
+#else
+/* Record that this is varargs.h; this turns off stdarg.h.  */
+
+#ifndef _VARARGS_H
+#define _VARARGS_H
+
+#ifdef __sparc__
+#include <va-sparc.h>
+#else
+#ifdef __spur__
+#include <va-spur.h>
+#else
+#ifdef __mips__
+#include <va-mips.h>
+#else
+#ifdef __i860__
+#include <va-i860.h>
+#else
+#ifdef __pyr__
+#include <va-pyr.h>
+#else
+#ifdef __clipper__
+#include <va-clipper.h>
+#else
+#ifdef __m88k__
+#include <machine/va-m88k.h>
+#else
+#if defined(__hppa__) || defined(hp800)
+#include <va-pa.h>
+#else
+#ifdef __i960__
+#include <va-i960.h>
+#else
+#ifdef __alpha__
+#include <va-alpha.h>
+#else
+
+#ifdef __NeXT__
+
+/* On Next, erase any vestiges of stdarg.h.  */
+
+#ifdef _ANSI_STDARG_H_
+#define _VA_LIST_
+#endif
+#define _ANSI_STDARG_H_ 
+
+#undef va_alist
+#undef va_dcl
+#undef va_list
+#undef va_start
+#undef va_end
+#undef __va_rounded_size
+#undef va_arg
+#endif  /* __NeXT__ */
+
+/* In GCC version 2, we want an ellipsis at the end of the declaration
+   of the argument list.  GCC version 1 can't parse it.  */
+
+#if __GNUC__ > 1
+#define __va_ellipsis ...
+#else
+#define __va_ellipsis
+#endif
+
+/* These macros implement traditional (non-ANSI) varargs
+   for GNU C.  */
+
+#define va_alist  __builtin_va_alist
+/* The ... causes current_function_varargs to be set in cc1.  */
+#define va_dcl    int __builtin_va_alist; __va_ellipsis
+
+/* Define __gnuc_va_list, just as in gstdarg.h.  */
+
+#ifndef __GNUC_VA_LIST
+#define __GNUC_VA_LIST
+#if defined(__svr4__) || defined(_AIX) || defined(_M_UNIX)
+typedef char *__gnuc_va_list;
+#else
+typedef void *__gnuc_va_list;
+#endif
+#endif
+
+#define va_start(AP)  AP=(char *) &__builtin_va_alist
+
+#define va_end(AP)
+
+#define __va_rounded_size(TYPE)  \
+  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+
+#if defined (__arm__) || defined (__i386__) || defined (__ns32000__) || defined (__vax__)
+/* This is for little-endian machines; small args are padded upward.  */
+#define va_arg(AP, TYPE)                                               \
+ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),    \
+  *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
+#else /* big-endian */
+/* This is for big-endian machines; small args are padded downward.  */
+#define va_arg(AP, TYPE)                                               \
+ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),    \
+  *((TYPE *) (void *) ((char *) (AP) - ((sizeof (TYPE) < 4             \
+                                        ? sizeof (TYPE)                \
+                                        : __va_rounded_size (TYPE))))))
+#endif /* big-endian */
+
+#endif /* not alpha */
+#endif /* not i960 */
+#endif /* not hppa */
+#endif /* not m88k */
+#endif /* not clipper */
+#endif /* not pyr */
+#endif /* not i860 */
+#endif /* not mips */
+#endif /* not spur */
+#endif /* not sparc */
+#endif /* not _VARARGS_H */
+
+/* Define va_list from __gnuc_va_list.  */
+
+#ifdef _HIDDEN_VA_LIST  /* On OSF1, this means varargs.h is "half-loaded".  */
+#undef _VA_LIST
+#endif
+
+#ifdef __svr4__
+/* SVR4.2 uses _VA_LIST for an internal alias for va_list,
+   so we must avoid testing it and setting it here.
+   SVR4 uses _VA_LIST as a flag in stdarg.h, but we should
+   have no conflict with that.  */
+#ifndef _VA_LIST_
+#define _VA_LIST_
+#ifdef __i860__
+#ifndef _VA_LIST
+#define _VA_LIST va_list
+#endif
+#endif /* __i860__ */
+typedef __gnuc_va_list va_list;
+#endif /* _VA_LIST_ */
+
+#else /* not __svr4__ */
+
+/* The macro _VA_LIST_ is the same thing used by this file in Ultrix.
+   But on BSD NET2 we must not test or define or undef it.
+   (Note that the comments in NET 2's ansi.h
+   are incorrect for _VA_LIST_--see stdio.h!)  */
+#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____)
+/* The macro _VA_LIST is used in SCO Unix 3.2.  */
+#ifndef _VA_LIST
+/* The macro _VA_LIST_T_H is used in the Bull dpx2  */
+#ifndef _VA_LIST_T_H
+#define _VA_LIST_T_H
+#if !(defined (__BSD_NET2__) || defined (____386BSD____))
+#define _VA_LIST_
+#endif
+#define _VA_LIST
+typedef __gnuc_va_list va_list;
+#endif /* not _VA_LIST_T_H */
+#endif /* not _VA_LIST */
+#endif /* not _VA_LIST_ */
+
+#endif /* not __svr4__ */
+
+/* took this one out Nivas */
+/* The next BSD release (if there is one) wants this symbol to be
+   undefined instead of _VA_LIST_.  */
+#ifdef _BSD_VA_LIST_
+#undef _BSD_VA_LIST_
+#define _BSD_VA_LIST_  __gnuc_va_list
+#endif /* _BSD_VA_LIST_ */
+#if defined(__cplusplus) && !defined(__GNUG__)
+
+/* This is added to work with AT&T C++. */
+extern "C" {
+      char            *__builtin_next_arg(void);
+      __gnuc_va_list  *__builtin_saveregs(void);
+      void            *__builtin_saveregs2(int);
+      int             *__builtin_argptr(void);
+      int             __builtin_argsize(void);
+      int             __builtin_classify_type(...);
+      int             __alignof__(...);
+}
+#endif
+
+
+#endif /* __GNUC__ */
diff --git a/sys/arch/mvme88k/include/vid.h b/sys/arch/mvme88k/include/vid.h
new file mode 100644 (file)
index 0000000..acaa280
--- /dev/null
@@ -0,0 +1,56 @@
+#define START_BLOCK 1
+#define LOADER_SIZE 2
+#define LOADER_ADDRESS 0x1F0000
+
+#ifndef __ASSEMBLER__
+struct vid {
+       unsigned char   vid_id[4];
+       unsigned char   vid_0[16];
+       unsigned int    vid_oss;
+       unsigned short  vid_osl;
+       unsigned char   vid_1[4];
+       unsigned short  vid_osa_u;
+       unsigned short  vid_osa_l;
+       unsigned char   vid_2[4];
+       unsigned char   vid_vd[20];
+       unsigned char   vid_3[86];
+       unsigned int    vid_cas;
+       unsigned char   vid_cal;
+       unsigned char   vid_4[99];
+       unsigned char   vid_mot[8];
+};
+struct cfg {
+
+       unsigned char   cfg_0[4];
+       unsigned short  cfg_atm;
+       unsigned short  cfg_prm;
+       unsigned short  cfg_atw;
+       unsigned short  cfg_rec;
+       unsigned char   cfg_1[12];
+       unsigned char   cfg_spt;
+       unsigned char   cfg_hds;
+       unsigned short  cfg_trk;
+       unsigned char   cfg_ilv;
+       unsigned char   cfg_sof;
+       unsigned short  cfg_psm;
+       unsigned short  cfg_shd;
+       unsigned char   cfg_2[2];
+       unsigned short  cfg_pcom;
+       unsigned char   cfg_3;
+       unsigned char   cfg_ssr;
+       unsigned short  cfg_rwcc;
+       unsigned short  cfg_ecc;
+       unsigned short  cfg_eatm;
+       unsigned short  cfg_eprm;
+       unsigned short  cfg_eatw;
+       unsigned char   cfg_gpb1;
+       unsigned char   cfg_gpb2;
+       unsigned char   cfg_gpb3;
+       unsigned char   cfg_gpb4;
+       unsigned char   cfg_ssc;
+       unsigned char   cfg_runit;
+       unsigned short  cfg_rsvc1;
+       unsigned short  cfg_rsvc2;
+       unsigned char   cfg_4[196];
+};
+#endif
diff --git a/sys/arch/mvme88k/include/vmparam.h b/sys/arch/mvme88k/include/vmparam.h
new file mode 100644 (file)
index 0000000..586fb83
--- /dev/null
@@ -0,0 +1,219 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * 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 ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS 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 Mellon 
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * HISTORY
+ */
+/*
+ *     File:   vm_param.h
+ *
+ *     machine dependent virtual memory parameters.
+ *     Most of the declarations are preceeded by M88K_ (or m88k_)
+ *     which is OK because only M88K specific code will be using
+ *     them.
+ */
+
+
+#ifndef        _MACHINE_VM_PARAM_
+#define _MACHINE_VM_PARAM_
+
+/*
+ * USRTEXT is the start of the user text/data space, while USRSTACK
+ * is the top (end) of the user stack.
+ */
+#define        USRTEXT         0x1000                  /* Start of user text */
+#define        USRSTACK        0x80000000              /* Start of user stack */
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#ifndef MAXTSIZ
+#define        MAXTSIZ         (8*1024*1024)           /* max text size */
+#endif
+#ifndef DFLDSIZ
+#define        DFLDSIZ         (16*1024*1024)          /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define        MAXDSIZ         (64*1024*1024)          /* max data size */
+#endif
+#ifndef        DFLSSIZ
+#define        DFLSSIZ         (512*1024)              /* initial stack size limit */
+#endif
+#ifndef        MAXSSIZ
+#define        MAXSSIZ         MAXDSIZ                 /* max stack size */
+#endif
+
+/*
+ * Default sizes of swap allocation chunks (see dmap.h).
+ * The actual values may be changed in vminit() based on MAXDSIZ.
+ * With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024.
+ * DMMIN should be at least ctod(1) so that vtod() works.
+ * vminit() insures this.
+ */
+#define        DMMIN   32                      /* smallest swap allocation */
+#define        DMMAX   4096                    /* largest potential swap allocation */
+#define        DMTEXT  1024                    /* swap allocation for text */
+
+/*
+ * Size of shared memory map
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS      1024
+#endif
+
+/*
+ * The time for a process to be blocked before being very swappable.
+ * This is a number of seconds which the system takes as being a non-trivial
+ * amount of real time.  You probably shouldn't change this;
+ * it is used in subtle ways (fractions and multiples of it are, that is, like
+ * half of a ``long time'', almost a long time, etc.)
+ * It is related to human patience and other factors which don't really
+ * change over time.
+ */
+#define        MAXSLP          20
+
+/*
+ * A swapped in process is given a small amount of core without being bothered
+ * by the page replacement algorithm.  Basically this says that if you are
+ * swapped in you deserve some resources.  We protect the last SAFERSS
+ * pages against paging and will just swap you out rather than paging you.
+ * Note that each process has at least UPAGES+CLSIZE pages which are not
+ * paged anyways (this is currently 8+2=10 pages or 5k bytes), so this
+ * number just means a swapped in process is given around 25k bytes.
+ * Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81),
+ * so we loan each swapped in process memory worth 100$, or just admit
+ * that we don't consider it worthwhile and swap it out to disk which costs
+ * $30/mb or about $0.75.
+ */
+#define        SAFERSS         4               /* nominal ``small'' resident set size
+                                          protected against replacement */
+
+#define        VM_MINUSER_ADDRESS      ((vm_offset_t) 0)
+#define        VM_MAXUSER_ADDRESS      ((vm_offset_t) 0xffc00000U)
+
+#define VM_MINKERNEL_ADDRESS   ((vm_offset_t) 0)
+#define VM_MAXKERNEL_ADDRESS   ((vm_offset_t) 0x1fffffff)
+
+/*
+ * Mach derived constants
+ */
+#define BYTE_SIZE      8       /* byte size in bits */
+
+#define M88K_PGBYTES   (1<<12) /* bytes per m88k page */
+#define M88K_PGSHIFT   12      /* number of bits to shift for pages */
+
+/*
+ *     Convert bytes to pages and convert pages to bytes.
+ *     No rounding is used.
+ */
+
+#define        m88k_btop(x)            (((unsigned)(x)) >> M88K_PGSHIFT)
+#define        m88k_ptob(x)            (((unsigned)(x)) << M88K_PGSHIFT)
+
+/*
+ *     Round off or truncate to the nearest page.  These will work
+ *     for either addresses or counts.  (i.e. 1 byte rounds to 1 page
+ *     bytes.
+ */
+
+#define m88k_round_page(x)     ((((unsigned)(x)) + M88K_PGBYTES - 1) & \
+                                       ~(M88K_PGBYTES-1))
+#define m88k_trunc_page(x)     (((unsigned)(x)) & ~(M88K_PGBYTES-1))
+
+#define        VM_MIN_ADDRESS  ((vm_offset_t) 0)
+#define        VM_MAX_ADDRESS  ((vm_offset_t) 0xffc00000U)
+
+#define        VM_MIN_USER_ADDRESS     ((vm_offset_t) 0)
+#define        VM_MAX_USER_ADDRESS     ((vm_offset_t) 0xffc00000U)
+
+/* on vme188, max = 0xf0000000 */
+
+#define VM_MIN_KERNEL_ADDRESS  ((vm_offset_t) 0)
+#define VM_MAX_KERNEL_ADDRESS  ((vm_offset_t) 0x1fffffff)
+
+#define KERNEL_STACK_SIZE      (3*4096)        /* kernel stack size */
+#define INTSTACK_SIZE          (3*4096)        /* interrupt stack size */
+
+/* virtual sizes (bytes) for various kernel submaps */
+#define VM_MBUF_SIZE           (NMBCLUSTERS*MCLBYTES)
+#define VM_KMEM_SIZE           (NKMEMCLUSTERS*CLBYTES)
+
+/*
+ *     Conversion between MACHINE pages and VM pages
+ */
+
+#define trunc_m88k_to_vm(p)    (atop(trunc_page(m88k_ptob(p))))
+#define round_m88k_to_vm(p)    (atop(round_page(m88k_ptob(p))))
+#define vm_to_m88k(p)          (m88k_btop(ptoa(p)))
+
+#if    1       /*Do we really need all this stuff*/
+#if    1       /*Do we really need all this stuff*/
+#if    1       /*Do we really need all this stuff*/
+#define        M88K_SGPAGES    (1<<10) /* pages per m88k segment */
+#define        M88K_SGPGSHIFT  10      /* number of bits to shift for segment-page */
+#define        M88K_ALSEGMS    (1<<10) /* segments per m88k all space */
+#define        M88K_ALSGSHIFT  10      /* number of bits to shift for all-segment */
+
+#define        M88K_SGBYTES    (1<<22) /* bytes per m88k segments */
+#define        M88K_SGSHIFT    22      /* number of bits to shift for segment */
+#define        M88K_ALPAGES    (1<<20) /* pages per m88k all space */
+#define        M88K_ALPGSHIFT  20      /* number of bits to shift for all-page */
+
+/*
+ *     Convert bytes to pages and convert pages to bytes.
+ *     No rounding is used.
+ */
+
+#define        m88k_btopr(x)           (((unsigned)(x) + (M88K_PGBYTES - 1)) >> M88K_PGSHIFT)
+#define        m88k_btosr(x)           (((unsigned)(x) + (M88K_SGBYTES - 1)) >> M88K_SGSHIFT)
+#define        m88k_btos(x)            (((unsigned)(x)) >> M88K_SGSHIFT)
+#define        m88k_stob(x)            (((unsigned)(x)) << M88K_SGSHIFT)
+#define        m88k_ptosr(x)           (((unsigned)(x) + (M88K_SGPAGES - 1)) >> M88K_SGPGSHIFT)
+#define        m88k_ptos(x)            (((unsigned)(x)) >> M88K_SGPGSHIFT)
+#define        m88k_stop(x)            (((unsigned)(x)) << M88K_SGPGSHIFT)
+
+/*
+ *     Round off or truncate to the nearest page.  These will work
+ *     for either addresses or counts.  (i.e. 1 byte rounds to 1 page
+ *     bytes.
+ */
+
+#define m88k_round_segm(x)     ((((unsigned)(x)) + M88K_SGBYTES - 1) & \
+                                       ~(M88K_SGBYTES-1))
+#define m88k_next_segm(x)      ((((unsigned)(x)) & ~(M88K_SGBYTES-1)) + \
+                                       M88K_SGBYTES)
+#define m88k_trunc_segm(x)     (((unsigned)(x)) & ~(M88K_SGBYTES-1))
+
+#define m88k_round_seg(x)      ((((unsigned)(x)) + M88K_SGBYTES - 1) & \
+                                       ~(M88K_SGBYTES-1))
+#define m88k_trunc_seg(x)      (((unsigned)(x)) & ~(M88K_SGBYTES-1))
+
+#define        VEQR_ADDR       0x20000000      /* kernel virtual eq phy mapping */
+#endif /*  Do we really need all this stuff */
+#endif /*  Do we really need all this stuf  */
+#endif /*  Do we really need all this stuff */
+
+#endif _MACHINE_VM_PARAM_
diff --git a/sys/arch/mvme88k/mvme88k/TODO b/sys/arch/mvme88k/mvme88k/TODO
new file mode 100644 (file)
index 0000000..a6151eb
--- /dev/null
@@ -0,0 +1,4 @@
+1. It appears that trap() assumes instruction access or data access
+   faults can only be caused by page faults. Could do better by
+   checking PFSR in the CMMU and handling parity errors, page faults,
+   segmentation faults and protection faults appropriately.
diff --git a/sys/arch/mvme88k/mvme88k/autoconf.c b/sys/arch/mvme88k/mvme88k/autoconf.c
new file mode 100644 (file)
index 0000000..596bef1
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 1996 Nivas Madhur
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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.
+ *
+ *     $Id: autoconf.c,v 1.3 1997/03/03 20:21:28 rahnds Exp $
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <machine/cpu.h>
+
+void configure __P((void));
+void setroot __P((void));
+void swapconf __P((void));
+
+int cold;      /* 1 if still booting */
+#include <sys/kernel.h>
+
+/*
+ * called at boot time, configure all devices on the system.
+ */
+void
+configure()
+{
+       if (config_rootfound("mainbus", "mainbus") == 0)
+               panic("no mainbus found");
+
+       /*
+        * Turn external interrupts on. We have all the drivers in
+        * place now!
+        */
+       enable_interrupt();
+       spl0();
+       
+#if 0
+#ifdef GENERIC
+       if ((boothowto & RB_ASKNAME) == 0)
+               setroot();
+       setconf();
+#else
+       setroot();
+#endif
+#endif /* 0 */
+       setroot();
+       swapconf();
+
+       /*
+        * Done with autoconfig!
+        */
+       cold = 0;
+}
+
+/*ARGSUSED*/
+int
+simple_devprint(auxp, pnp)
+       void *auxp;
+       char *pnp;
+{
+       return(QUIET);
+}
+
+int
+matchname(fp, sp)
+       char *fp, *sp;
+{
+       int len;
+
+       len = strlen(fp);
+       if (strlen(sp) != len)
+               return(0);
+       if (bcmp(fp, sp, len) == 0)
+               return(1);
+       return(0);
+}
+
+void
+swapconf()
+{
+       struct swdevt *swp;
+       u_int maj;
+       int nb;
+
+       for (swp = swdevt; swp->sw_dev > 0; swp++) {
+               maj = major(swp->sw_dev);
+
+               if (maj > nblkdev)
+                       break;
+
+               if (bdevsw[maj].d_psize) {
+                       nb = bdevsw[maj].d_psize(swp->sw_dev);
+                       if (nb > 0 && 
+                           (swp->sw_nblks == 0 || swp->sw_nblks > nb))
+                               swp->sw_nblks = nb;
+                       else
+                               swp->sw_nblks = 0;
+               }
+               swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
+       }
+       if (dumplo == 0 && dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize)
+       /*dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem;*/
+               dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) -
+                       ctob(physmem)/DEV_BSIZE;
+       if (dumplo < 0)
+               dumplo = 0;
+
+       dumpconf();
+}
+
+#define        DOSWAP                  /* change swdevt and dumpdev */
+u_long bootdev = 0;            /* should be dev_t, but not until 32 bits */
+
+static char devname[][2] = {
+       0,0,
+       0,0,
+       0,0,
+       0,0,
+       's','d',        /* 4 = sd -- new SCSI system */
+};
+
+void
+setroot()
+{
+       int majdev, mindev, unit, part, adaptor;
+       dev_t temp, orootdev;
+       struct swdevt *swp;
+
+       printf("setroot boothowto %x bootdev %x\n", boothowto, bootdev);
+       if (boothowto & RB_DFLTROOT ||
+           (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
+               return;
+       majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
+       if (majdev > sizeof(devname) / sizeof(devname[0]))
+               return;
+       adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
+       part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
+       unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
+       orootdev = rootdev;
+       rootdev = MAKEDISKDEV(majdev, unit, part);
+       /*
+        * If the original rootdev is the same as the one
+        * just calculated, don't need to adjust the swap configuration.
+        */
+       if (rootdev == orootdev)
+               return;
+       printf("changing root device to %c%c%d%c\n",
+               devname[majdev][0], devname[majdev][1],
+               unit, part + 'a');
+#ifdef DOSWAP
+       mindev = DISKUNIT(rootdev);
+       for (swp = swdevt; swp->sw_dev; swp++) {
+               printf("DOSWAP swap %x dev %x\n", swp, swp->sw_dev);
+               if (majdev == major(swp->sw_dev) &&
+                   mindev == DISKUNIT(swp->sw_dev)) {
+                       temp = swdevt[0].sw_dev;
+                       swdevt[0].sw_dev = swp->sw_dev;
+                       swp->sw_dev = temp;
+                       break;
+               }
+       }
+       if (swp->sw_dev == 0)
+               return;
+       /*
+        * If dumpdev was the same as the old primary swap
+        * device, move it to the new primary swap device.
+        */
+       if (temp == dumpdev)
+               dumpdev = swdevt[0].sw_dev;
+#endif
+}
diff --git a/sys/arch/mvme88k/mvme88k/cmmu.c b/sys/arch/mvme88k/mvme88k/cmmu.c
new file mode 100644 (file)
index 0000000..9499324
--- /dev/null
@@ -0,0 +1,1354 @@
+/*
+ * 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.
+ *
+ *     $Id: cmmu.c,v 1.3 1997/03/03 20:21:30 rahnds Exp $
+ */
+/*
+ * 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 <machine/board.h>
+#include <machine/cpus.h>
+#include <machine/m882xx.h>
+
+/* On some versions of 88200, page size flushes don't work. I am using
+ * sledge hammer approach till I find for sure which ones are bad XXX nivas */
+#define BROKEN_MMU_MASK        
+#if defined(MVME187)
+#undef SNOOP_ENABLE
+#else
+#define        SNOOP_ENABLE
+#endif /* defined(MVME187)
+
+#undef SHADOW_BATC             /* don't use BATCs for now XXX nivas */
+
+struct cmmu_regs
+{
+    /* base + $000 */ volatile unsigned idr;
+    /* base + $004 */ volatile unsigned scr;
+    /* base + $008 */ volatile unsigned ssr;
+    /* base + $00C */ volatile unsigned sar;
+    /*             */ unsigned padding1[0x3D];
+    /* base + $104 */ volatile unsigned sctr;
+    /* base + $108 */ volatile unsigned pfSTATUSr;
+    /* base + $10C */ volatile unsigned pfADDRr;
+    /*             */ unsigned padding2[0x3C];
+    /* base + $200 */ volatile unsigned sapr;
+    /* base + $204 */ volatile unsigned uapr;
+    /*             */ unsigned padding3[0x7E];
+    /* base + $400 */ volatile unsigned bwp[8];
+    /*             */ unsigned padding4[0xF8];
+    /* base + $800 */ volatile unsigned cdp[4];
+    /*             */ unsigned padding5[0x0C];
+    /* base + $840 */ volatile unsigned ctp[4];
+    /*             */ unsigned padding6[0x0C];
+    /* base + $880 */ volatile unsigned cssp;
+
+    /* The rest for the 88204 */
+    #define cssp0 cssp
+    /*             */ unsigned padding7[0x03];
+    /* base + $890 */ volatile unsigned cssp1;
+    /*             */ unsigned padding8[0x03];
+    /* base + $8A0 */ volatile unsigned cssp2;
+    /*             */ unsigned padding9[0x03];
+    /* base + $8B0 */ volatile unsigned cssp3;
+};
+
+static struct cmmu {
+       struct cmmu_regs *cmmu_regs;    /* CMMU "base" area */
+       unsigned char  cmmu_cpu;        /* cpu number it is attached to */
+       unsigned char  which;           /* either INST_CMMU || DATA_CMMU */
+       unsigned char  cmmu_alive;
+#define CMMU_DEAD      0               /* This cmmu not there */
+#define CMMU_AVAILABLE 1               /* It's there, but which cpu's? */
+#define CMMU_MARRIED   2               /* Know which cpu it belongs to. */
+#if SHADOW_BATC
+       unsigned batc[8];
+#endif
+       unsigned char  pad;
+} cmmu[MAX_CMMUS] = {
+    {(void *)CMMU_I, 0, 0, 0, 0},
+    {(void *)CMMU_D, 0, 1, 0, 0},
+};
+
+/*
+ * We rely upon and use INST_CMMU == 0 and DATA_CMMU == 1
+ */
+#if INST_CMMU != 0 || DATA_CMMU != 1
+       error("ack gag barf!");
+#endif
+struct cpu_cmmu {
+    struct cmmu *pair[2];
+} cpu_cmmu[1];
+
+/*
+ * CMMU(cpu,data) Is the cmmu struct for the named cpu's indicated cmmu.
+ * REGS(cpu,data) is the actual register structure.
+ */
+#define CMMU(cpu, data) cpu_cmmu[(cpu)].pair[(data)?DATA_CMMU:INST_CMMU]
+#define REGS(cpu, data) (*CMMU(cpu, data)->cmmu_regs)
+
+unsigned cache_policy = /*CACHE_INH*/ 0;
+
+#ifdef CMMU_DEBUG
+void
+show_apr(unsigned value)
+{
+       union apr_template apr_template;
+       apr_template.bits = value;
+
+       _printf("table @ 0x%x000", apr_template.field.st_base);
+       if (apr_template.field.wt) printf(", writethrough");
+       if (apr_template.field.g)  printf(", global");
+       if (apr_template.field.ci) printf(", cache inhibit");
+       if (apr_template.field.te) printf(", valid");
+       else                       printf(", not valid");
+       printf("]\n");
+}
+
+void
+show_sctr(unsigned value)
+{
+    union {
+       unsigned bits;
+       struct {
+          unsigned :16,
+                 pe: 1,
+                 se: 1,
+                 pr: 1,
+                   :13;
+       } fields;
+    } sctr; 
+    sctr.bits = value;
+    printf("%spe, %sse %spr]\n",
+       sctr.fields.pe ? "" : "!",
+       sctr.fields.se ? "" : "!",
+       sctr.fields.pr ? "" : "!");
+}
+#endif
+
+/*
+ * CMMU initialization routine
+ */
+void
+cmmu_init(void)
+{
+       unsigned tmp, cmmu_num;
+       union cpupid id;
+       int cpu;
+
+       cpu_cmmu[0].pair[INST_CMMU] = cpu_cmmu[0].pair[DATA_CMMU] = 0;
+
+       for (cmmu_num = 0; cmmu_num < MAX_CMMUS; cmmu_num++) {
+               if (!badwordaddr((vm_offset_t)cmmu[cmmu_num].cmmu_regs)) {
+                       id.cpupid = cmmu[cmmu_num].cmmu_regs->idr;
+                       if (id.m88200.type != M88200 && id.m88200.type !=M88204)
+                               continue;
+                       cmmu[cmmu_num].cmmu_alive = CMMU_AVAILABLE;
+
+                       cpu_cmmu[cmmu[cmmu_num].cmmu_cpu].pair[cmmu[cmmu_num].which] =
+                               &cmmu[cmmu_num];
+
+                       /*
+                        * Reset cache data....
+                        * as per M88200 Manual (2nd Ed.) section 3.11.
+                        */
+                       for (tmp = 0; tmp < 255; tmp++) {
+                               cmmu[cmmu_num].cmmu_regs->sar = tmp << 4;
+                               cmmu[cmmu_num].cmmu_regs->cssp = 0x3f0ff000;
+                       }
+
+                       /* 88204 has additional cache to clear */
+                       if(id.m88200.type == M88204)
+                       {
+                               for (tmp = 0; tmp < 255; tmp++) {
+                                       cmmu[cmmu_num].cmmu_regs->sar =
+                                                               tmp<<4;
+                                       cmmu[cmmu_num].cmmu_regs->cssp1 =
+                                                               0x3f0ff000;
+                               }
+                               for (tmp = 0; tmp < 255; tmp++) {
+                                       cmmu[cmmu_num].cmmu_regs->sar =
+                                                               tmp<<4;
+                                       cmmu[cmmu_num].cmmu_regs->cssp2 =
+                                                               0x3f0ff000;
+                               }
+                               for (tmp = 0; tmp < 255; tmp++) {
+                                       cmmu[cmmu_num].cmmu_regs->sar =
+                                                               tmp<<4;
+                                       cmmu[cmmu_num].cmmu_regs->cssp3 =                                                                        0x3f0ff000;
+                               }
+                       }
+
+                       /*
+                        * Set the SCTR, SAPR, and UAPR to some known state
+                        * (I don't trust the reset to do it).
+                        */
+                       tmp =
+                               ! CMMU_SCTR_PE |   /* not parity enable */
+                               ! CMMU_SCTR_SE |   /* not snoop enable */
+                               ! CMMU_SCTR_PR ;   /*not priority arbitration */
+                       cmmu[cmmu_num].cmmu_regs->sctr = tmp;
+
+                       tmp =
+                               (0x00000 << 12) |/*segment table base address */
+                               AREA_D_WT |     /* write through */
+                               AREA_D_G  |     /* global */
+                               AREA_D_CI |     /* cache inhibit */
+                               ! AREA_D_TE ;   /* not translation enable */
+
+                       cmmu[cmmu_num].cmmu_regs->sapr =
+                       cmmu[cmmu_num].cmmu_regs->uapr = tmp;
+               
+#if SHADOW_BATC
+                       cmmu[cmmu_num].batc[0] =
+                       cmmu[cmmu_num].batc[1] =
+                       cmmu[cmmu_num].batc[2] =
+                       cmmu[cmmu_num].batc[3] =
+                       cmmu[cmmu_num].batc[4] =
+                       cmmu[cmmu_num].batc[5] =
+                       cmmu[cmmu_num].batc[6] =
+                       cmmu[cmmu_num].batc[7] = 0;
+#endif
+                       cmmu[cmmu_num].cmmu_regs->bwp[0] = 
+                       cmmu[cmmu_num].cmmu_regs->bwp[1] = 
+                       cmmu[cmmu_num].cmmu_regs->bwp[2] = 
+                       cmmu[cmmu_num].cmmu_regs->bwp[3] = 
+                       cmmu[cmmu_num].cmmu_regs->bwp[4] = 
+                       cmmu[cmmu_num].cmmu_regs->bwp[5] = 
+                       cmmu[cmmu_num].cmmu_regs->bwp[6] = 
+                       cmmu[cmmu_num].cmmu_regs->bwp[7] = 0;
+
+                       cmmu[cmmu_num].cmmu_regs->scr =CMMU_FLUSH_CACHE_INV_ALL;
+                       cmmu[cmmu_num].cmmu_regs->scr = CMMU_FLUSH_SUPER_ALL;
+                       cmmu[cmmu_num].cmmu_regs->scr = CMMU_FLUSH_USER_ALL;
+               }
+       }
+
+       /*
+        * Now that we know which CMMUs are there, let's report on which
+        * CPU/CMMU sets seem complete (hopefully all)
+        */
+       for (cpu = 0; cpu < MAX_CPUS; cpu++)
+       {
+               if (cpu_cmmu[cpu].pair[INST_CMMU] && cpu_cmmu[cpu].pair[DATA_CMMU])
+               {
+                       if(id.m88200.type == M88204)
+                               printf("CPU%d is attached with MC88204 CMMU\n",
+                                                                       cpu);
+                       else
+                               printf("CPU%d is attached with MC88200 CMMU\n",
+                                                                       cpu);
+               }
+               else if (cpu_cmmu[cpu].pair[INST_CMMU])
+               {
+                       printf("CPU%d data CMMU is not working.\n", cpu);
+                       panic("cmmu-data");
+               }
+               else if (cpu_cmmu[cpu].pair[DATA_CMMU])
+               {
+                       printf("CPU%d instruction CMMU is not working.\n", cpu);
+                       panic("cmmu");
+               }
+       }
+
+#if SNOOP_ENABLE
+       /*
+        * Enable snooping... MVME187 doesn't support snooping. The
+        * processor will, but the processor is not going to see the cache
+        * accesses going on the 040 local bus. XXX nivas
+        */
+       for (cpu = 0; cpu < MAX_CPUS; cpu++)
+       {
+               /*
+                * Enable snooping.
+                * We enable it for instruction cmmus as well so that we can
+                * have breakpoints, etc, and modify code.
+                */
+               tmp =
+                   ! CMMU_SCTR_PE |   /* not parity enable */
+                     CMMU_SCTR_SE |   /* snoop enable */
+                   ! CMMU_SCTR_PR ;   /* not priority arbitration */
+
+               REGS(cpu, DATA_CMMU).sctr = tmp;
+               REGS(cpu, INST_CMMU).sctr = tmp;
+               REGS(cpu, DATA_CMMU).scr  = CMMU_FLUSH_SUPER_ALL;
+               REGS(cpu, INST_CMMU).scr  = CMMU_FLUSH_SUPER_ALL;
+       }
+
+#endif /* SNOOP_ENABLE */
+
+       /*
+        * Turn on some cache.
+        */
+       for (cpu = 0; cpu < MAX_CPUS; cpu++)
+       {
+               /*
+                * Enable some caching for the instruction stream.
+                * Can't cache data yet 'cause device addresses can never
+                * be cached, and we don't have those no-caching zones
+                * set up yet....
+                */
+               tmp =
+                   (0x00000 << 12) |   /* segment table base address */
+                         AREA_D_WT |   /* write through */
+                         AREA_D_G  |   /* global */
+                         AREA_D_CI |   /* cache inhibit */
+                       ! AREA_D_TE ;   /* not translation enable */
+               REGS(cpu, INST_CMMU).sapr = tmp;
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_SUPER_ALL;
+       }
+}
+
+/*
+ * Just before poweroff or reset....
+ */
+void
+cmmu_shutdown_now(void)
+{
+       unsigned tmp;
+       unsigned cmmu_num;
+
+       /*
+        * Now set some state as we like...
+        */
+       for (cmmu_num = 0; cmmu_num < MAX_CMMUS; cmmu_num++)
+       {
+               tmp =
+               ! CMMU_SCTR_PE |   /* parity enable */
+#if SNOOP_ENABLE
+               ! CMMU_SCTR_SE |   /* snoop enable */
+#endif /* SNOOP_ENABLE */
+               ! CMMU_SCTR_PR ;   /* priority arbitration */
+
+               cmmu[cmmu_num].cmmu_regs->sctr = tmp;
+
+               tmp = 
+                       (0x00000 << 12) |  /* segment table base address */
+                       ! AREA_D_WT |      /* write through */
+                       ! AREA_D_G  |      /* global */
+                         AREA_D_CI |      /* cache inhibit */
+                       ! AREA_D_TE ;      /* translation disable */
+               
+               cmmu[cmmu_num].cmmu_regs->sapr = tmp;
+               cmmu[cmmu_num].cmmu_regs->uapr = tmp;
+       }
+}
+
+/**
+ **    Funcitons that actually modify CMMU registers.
+ **/
+
+#if !DDB
+static
+#endif
+void
+cmmu_remote_set(unsigned cpu, unsigned r, unsigned data, unsigned x)
+{
+       *(volatile unsigned *)(r + (char*)&REGS(cpu,data)) = x;
+}
+
+/*
+ * cmmu_cpu_lock should be held when called if read
+ * the CMMU_SCR or CMMU_SAR.
+**/
+#if !DDB
+static
+#endif
+unsigned
+cmmu_remote_get(unsigned cpu, unsigned r, unsigned data)
+{
+       return (*(volatile unsigned *)(r + (char*)&REGS(cpu,data)));
+}
+
+/* Needs no locking - read only registers */
+unsigned
+cmmu_get_idr(unsigned data)
+{
+       return REGS(0,data).idr;
+}
+
+void
+cmmu_set_sapr(unsigned ap)
+{
+       int cpu = 0;
+
+       if (cache_policy & CACHE_INH)
+               ap |= AREA_D_CI;
+
+       REGS(cpu, INST_CMMU).sapr = ap;
+       REGS(cpu, DATA_CMMU).sapr = ap;
+}
+
+void
+cmmu_remote_set_sapr(unsigned cpu, unsigned ap)
+{
+       if (cache_policy & CACHE_INH)
+               ap |= AREA_D_CI;
+
+       REGS(cpu, INST_CMMU).sapr = ap;
+       REGS(cpu, DATA_CMMU).sapr = ap;
+}
+
+void
+cmmu_set_uapr(unsigned ap)
+{
+       int cpu = 0;
+
+       /* this functionality also mimiced in cmmu_pmap_activate() */
+       REGS(cpu, INST_CMMU).uapr = ap;
+       REGS(cpu, DATA_CMMU).uapr = ap;
+}
+
+/*
+ * Set batc entry number entry_no to value in 
+ * the data or instruction cache depending on data.
+ *
+ * Except for the cmmu_init, this function, cmmu_set_pair_batc_entry,
+ * and cmmu_pmap_activate are the only functions which may set the
+ * batc values.
+ */
+void
+cmmu_set_batc_entry(
+     unsigned cpu,
+     unsigned entry_no,
+     unsigned data,   /* 1 = data, 0 = instruction */
+     unsigned value)  /* the value to stuff into the batc */
+{
+
+       REGS(cpu,data).bwp[entry_no] = value;
+#if SHADOW_BATC
+       CMMU(cpu,data)->batc[entry_no] = value;
+#endif
+#if 0 /* was for debugging piece (peace?) of mind */
+       REGS(cpu,data).scr = CMMU_FLUSH_SUPER_ALL;
+       REGS(cpu,data).scr = CMMU_FLUSH_USER_ALL;
+#endif
+}
+
+/*
+ * Set batc entry number entry_no to value in 
+ * the data and instruction cache for the named CPU.
+ */
+void
+cmmu_set_pair_batc_entry(
+     unsigned cpu,
+     unsigned entry_no,
+     unsigned value)  /* the value to stuff into the batc */
+{
+
+       REGS(cpu,DATA_CMMU).bwp[entry_no] = value;
+#if SHADOW_BATC
+       CMMU(cpu,DATA_CMMU)->batc[entry_no] = value;
+#endif
+       REGS(cpu,INST_CMMU).bwp[entry_no] = value;
+#if SHADOW_BATC
+       CMMU(cpu,INST_CMMU)->batc[entry_no] = value;
+#endif
+
+#if 0  /* was for debugging piece (peace?) of mind */
+       REGS(cpu,INST_CMMU).scr = CMMU_FLUSH_SUPER_ALL;
+       REGS(cpu,INST_CMMU).scr = CMMU_FLUSH_USER_ALL;
+       REGS(cpu,DATA_CMMU).scr = CMMU_FLUSH_SUPER_ALL;
+       REGS(cpu,DATA_CMMU).scr = CMMU_FLUSH_USER_ALL;
+#endif
+}
+
+/**
+ **    Functions that invalidate TLB entries.
+ **/
+
+/*
+ *     flush any tlb
+ *     Some functionality mimiced in cmmu_pmap_activate.
+ */
+void
+cmmu_flush_remote_tlb(unsigned cpu, unsigned kernel, vm_offset_t vaddr, int size)
+{
+       register s = splhigh();
+    
+       if ((unsigned)size > M88K_PGBYTES) 
+       {
+               REGS(cpu, INST_CMMU).scr =
+               REGS(cpu, DATA_CMMU).scr =
+                       kernel ? CMMU_FLUSH_SUPER_ALL : CMMU_FLUSH_USER_ALL;
+       }
+       else /* a page or smaller */
+       {
+               REGS(cpu, INST_CMMU).sar = (unsigned)vaddr;
+               REGS(cpu, DATA_CMMU).sar = (unsigned)vaddr;
+               REGS(cpu, INST_CMMU).scr =
+               REGS(cpu, DATA_CMMU).scr =
+                       kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE;
+       }
+       splx(s);
+}
+
+/*
+ *     flush my personal tlb
+ */
+void
+cmmu_flush_tlb(unsigned kernel, vm_offset_t vaddr, int size)
+{
+       cmmu_flush_remote_tlb(0, kernel, vaddr, size);
+}
+
+/*
+ * New fast stuff for pmap_activate.
+ * Does what a few calls used to do.
+ * Only called from pmap.c's _pmap_activate().
+ */
+void
+cmmu_pmap_activate(
+    unsigned cpu,
+    unsigned uapr,
+    batc_template_t i_batc[BATC_MAX],
+    batc_template_t d_batc[BATC_MAX])
+{
+       int entry_no;
+
+       /* the following is from cmmu_set_uapr */
+       REGS(cpu, INST_CMMU).uapr = uapr;
+       REGS(cpu, DATA_CMMU).uapr = uapr;
+
+       for (entry_no = 0; entry_no < BATC_MAX; entry_no++) {
+               REGS(cpu,INST_CMMU).bwp[entry_no] = i_batc[entry_no].bits;
+               REGS(cpu,DATA_CMMU).bwp[entry_no] = d_batc[entry_no].bits;
+#if SHADOW_BATC
+               CMMU(cpu,INST_CMMU)->batc[entry_no] = i_batc[entry_no].bits;
+               CMMU(cpu,DATA_CMMU)->batc[entry_no] = d_batc[entry_no].bits;
+#endif
+       }
+
+       /*
+        * Flush the user TLB.
+        * IF THE KERNEL WILL EVER CARE ABOUT THE BATC ENTRIES,
+        * THE SUPERVISOR TLBs SHOULB EE FLUSHED AS WELL.
+        */
+       REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_USER_ALL;
+       REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_USER_ALL;
+}
+
+/**
+ **    Functions that invalidate caches.
+ **
+ ** Cache invalidates require physical addresses.  Care must be exercised when
+ ** using segment invalidates.  This implies that the starting physical address
+ ** plus the segment length should be invalidated.  A typical mistake is to
+ ** extract the first physical page of a segment from a virtual address, and
+ ** then expecting to invalidate when the pages are not physically contiguous.
+ **
+ ** We don't push Instruction Caches prior to invalidate because they are not
+ ** snooped and never modified (I guess it doesn't matter then which form
+ ** of the command we use then).
+ **/
+/*
+ *     flush both Instruction and Data caches
+ */
+void
+cmmu_flush_remote_cache(int cpu, vm_offset_t physaddr, int size)
+{
+       register s = splhigh();
+
+#if !defined(BROKEN_MMU_MASK)
+
+       if (size < 0 || size > NBSG ) {
+               REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+       }
+       else if (size <= 16) {
+               REGS(cpu, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_LINE;
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_LINE;
+       }
+       else if (size <= NBPG) {
+               REGS(cpu, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_PAGE;
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_PAGE;
+       }
+       else {
+               REGS(cpu, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_SEGMENT;
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_SEGMENT;
+       }
+
+#else
+       REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+       REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+#endif /* !BROKEN_MMU_MASK */
+       splx(s);
+}
+
+/*
+ *     flush both Instruction and Data caches
+ */
+void
+cmmu_flush_cache(vm_offset_t physaddr, int size)
+{
+       cmmu_flush_remote_cache(0, physaddr, size);
+}
+
+/*
+ *     flush Instruction caches
+ */
+void
+cmmu_flush_remote_inst_cache(int cpu, vm_offset_t physaddr, int size)
+{
+       register s = splhigh();
+
+#if !defined(BROKEN_MMU_MASK)
+       if (size < 0 || size > NBSG ) {
+               REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+       }
+       else if (size <= 16) {
+               REGS(cpu, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_LINE;
+       }
+       else if (size <= NBPG) {
+               REGS(cpu, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_PAGE;
+       }
+       else {
+               REGS(cpu, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_SEGMENT;
+       }
+#else
+       REGS(cpu, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+#endif /* !BROKEN_MMU_MASK */
+
+       splx(s);
+}
+
+/*
+ *     flush Instruction caches
+ */
+void
+cmmu_flush_inst_cache(vm_offset_t physaddr, int size)
+{
+       cmmu_flush_remote_inst_cache(0, physaddr, size);
+}
+
+void
+cmmu_flush_remote_data_cache(int cpu, vm_offset_t physaddr, int size)
+{ 
+       register s = splhigh();
+
+#if !defined(BROKEN_MMU_MASK)
+       if (size < 0 || size > NBSG ) {
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+       }
+       else if (size <= 16) {
+               REGS(cpu, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_LINE;
+       }
+       else if (size <= NBPG) {
+               REGS(cpu, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_PAGE;
+       }
+       else {
+               REGS(cpu, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_SEGMENT;
+       }
+#else
+       REGS(cpu, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+#endif /* !BROKEN_MMU_MASK */
+    
+    splx(s);
+}
+
+/*
+ * flush data cache
+ */ 
+void
+cmmu_flush_data_cache(vm_offset_t physaddr, int size)
+{ 
+       cmmu_flush_remote_data_cache(0, physaddr, size);
+}
+
+/*
+ * sync dcache (and icache too)
+ */
+static void
+cmmu_sync_cache(vm_offset_t physaddr, int size)
+{
+       register s = splhigh();
+
+#if !defined(BROKEN_MMU_MASK)
+       if (size < 0 || size > NBSG ) {
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CB_ALL;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CB_ALL;
+       }
+       else if (size <= 16) {
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CB_LINE;
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CB_LINE;
+       }
+       else if (size <= NBPG) {
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CB_PAGE;
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CB_PAGE;
+       }
+       else {
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CB_SEGMENT;
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CB_SEGMENT;
+       }
+#else
+       REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CB_ALL;
+       REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CB_ALL;
+#endif /* !BROKEN_MMU_MASK */
+       splx(s);
+}
+
+static void
+cmmu_sync_inval_cache(vm_offset_t physaddr, int size)
+{
+       register s = splhigh();
+
+#if !defined(BROKEN_MMU_MASK)
+       if (size < 0 || size > NBSG ) {
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+       }
+       else if (size <= 16) {
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_LINE;
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_LINE;
+       }
+       else if (size <= NBPG) {
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_PAGE;
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_PAGE;
+       }
+       else {
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_SEGMENT;
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_SEGMENT;
+       }
+
+#else
+       REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+       REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_CBI_ALL;
+#endif /* !BROKEN_MMU_MASK */
+       splx(s);
+}
+
+static void
+cmmu_inval_cache(vm_offset_t physaddr, int size)
+{
+       register s = splhigh();
+
+#if !defined(BROKEN_MMU_MASK)
+       if (size < 0 || size > NBSG ) {
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_INV_ALL;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_INV_ALL;
+       }
+       else if (size <= 16) {
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_INV_LINE;
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_INV_LINE;
+       }
+       else if (size <= NBPG) {
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_INV_PAGE;
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_INV_PAGE;
+       }
+       else {
+               REGS(0, DATA_CMMU).sar = (unsigned)physaddr;
+               REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_INV_SEGMENT;
+               REGS(0, INST_CMMU).sar = (unsigned)physaddr;
+               REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_INV_SEGMENT;
+       }
+#else
+       REGS(0, DATA_CMMU).scr = CMMU_FLUSH_CACHE_INV_ALL;
+       REGS(0, INST_CMMU).scr = CMMU_FLUSH_CACHE_INV_ALL;
+#endif /* !BROKEN_MMU_MASK */
+
+       splx(s);
+}
+
+void
+dma_cachectl(vm_offset_t va, int size, int op)
+{
+       int count;
+       
+#if !defined(BROKEN_MMU_MASK)
+       while (size) {
+
+               count = NBPG - ((int)va & PGOFSET);
+
+               if (size < count)
+                       count = size;
+
+               if (op == DMA_CACHE_SYNC)
+                       cmmu_sync_cache(kvtop(va), count);
+               else if (op == DMA_CACHE_SYNC_INVAL)
+                       cmmu_sync_inval_cache(kvtop(va), count);
+               else
+                       cmmu_inval_cache(kvtop(va), count);
+
+               va = (vm_offset_t)((int)va + count);
+               size -= count;
+       }
+#else
+
+       if (op == DMA_CACHE_SYNC)
+               cmmu_sync_cache(kvtop(va), size);
+       else if (op == DMA_CACHE_SYNC_INVAL)
+               cmmu_sync_inval_cache(kvtop(va), size);
+       else
+               cmmu_inval_cache(kvtop(va), size);
+#endif /* !BROKEN_MMU_MASK */
+}
+
+#if DDB
+union ssr {
+    unsigned bits;
+    struct {
+       unsigned  :16,
+               ce:1,
+               be:1,
+                 :4,
+               wt:1,
+               sp:1,
+                g:1,
+               ci:1,
+                 :1,
+                m:1,
+                u:1,
+               wp:1,
+               bh:1,
+                v:1;
+    } field;
+};
+
+union cssp {
+    unsigned bits;
+    struct {
+       unsigned   : 2,
+                 l: 6,
+                d3: 1,
+                d2: 1,
+                d1: 1,
+                d0: 1,
+               vv3: 2,
+               vv2: 2,
+               vv1: 2,
+               vv0: 2,
+                  :12;
+    } field;
+};
+
+union batcu {
+    unsigned bits;
+    struct {              /* block address translation register */
+       unsigned int
+           lba:13,            /* logical block address */
+           pba:13,            /* physical block address */
+           s:1,               /* supervisor */
+           wt:4,              /* write through */
+           g:1,               /* global */
+           ci:1,              /* cache inhibit */
+           wp:1,              /* write protect */
+           v:1;               /* valid */
+    } field;
+};
+
+#define VV_EX_UNMOD            0
+#define VV_EX_MOD              1
+#define VV_SHARED_UNMOD                2
+#define VV_INVALID             3
+
+#define D(UNION, LINE) \
+       ((LINE) == 3 ? (UNION).field.d3 : \
+        ((LINE) == 2 ? (UNION).field.d2 : \
+         ((LINE) == 1 ? (UNION).field.d1 : \
+          ((LINE) == 0 ? (UNION).field.d0 : ~0))))
+#define VV(UNION, LINE) \
+       ((LINE) == 3 ? (UNION).field.vv3 : \
+        ((LINE) == 2 ? (UNION).field.vv2 : \
+         ((LINE) == 1 ? (UNION).field.vv1 : \
+          ((LINE) == 0 ? (UNION).field.vv0 : ~0))))
+       
+
+#undef VEQR_ADDR
+#define  VEQR_ADDR 0
+
+/*
+ * Show (for debugging) how the given CMMU translates the given ADDRESS.
+ * If cmmu == -1, the data cmmu for the current cpu is used.
+ */
+void
+cmmu_show_translation(
+    unsigned address,
+    unsigned supervisor_flag,
+    unsigned verbose_flag,
+    int cmmu_num)
+{
+    /*
+     * A virtual address is split into three fields. Two are used as
+     * indicies into tables (segment and page), and one is an offset into
+     * a page of memory.
+     */
+    union {
+       unsigned bits;
+       struct {
+           unsigned segment_table_index:10,
+                    page_table_index:10,
+                    page_offset:12;
+       } field;
+    } virtual_address;
+    unsigned value;
+
+    if (verbose_flag)
+        db_printf("-------------------------------------------\n");
+
+
+    /****** ACCESS PROPER CMMU or THREAD ***********/
+#if 0 /* no thread */
+    if (thread != 0)
+    {
+       /* the following tidbit from _pmap_activate in m88k/pmap.c */
+       register apr_template_t apr_data;
+       supervisor_flag = 0;    /* thread implies user */
+
+       if (thread->task == 0) {
+           db_printf("[thread %x has empty task pointer]\n", thread);
+           return;
+       } else if (thread->task->map == 0) {
+           db_printf("[thread/task %x/%x has empty map pointer]\n",
+               thread, thread->task);
+           return;
+       } else if (thread->task->map->pmap == 0) {
+           db_printf("[thread/task/map %x/%x/%x has empty pmap pointer]\n",
+               thread, thread->task, thread->task->map);
+           return;
+       }
+       if (thread->task->map->pmap->lock.lock_data) {
+           db_printf("[Warning: thread %x's task %x's map %x's "
+             "pmap %x is locked]\n", thread, thread->task,
+               thread->task->map, thread->task->map->pmap);
+       }
+        apr_data.bits = 0;
+        apr_data.field.st_base = M88K_BTOP(thread->task->map->pmap->sdt_paddr);
+        apr_data.field.wt = 0;
+        apr_data.field.g  = 1;
+        apr_data.field.ci = 0;
+        apr_data.field.te = 1;
+       value = apr_data.bits;
+        if (verbose_flag) {
+           db_printf("[thread %x task %x map %x pmap %x UAPR is %x]\n",
+               thread, thread->task, thread->task->map,
+               thread->task->map->pmap, value);
+       }
+    }
+    else
+#endif /* 0 */
+    {
+       if (cmmu_num == -1)
+       {
+           if (cpu_cmmu[0].pair[DATA_CMMU] == 0)
+           {
+               db_printf("ack! can't figure my own data cmmu number.\n");
+               return;
+           }
+           cmmu_num = cpu_cmmu[0].pair[DATA_CMMU] - cmmu;
+           if (verbose_flag)
+               db_printf("The data cmmu for cpu#%d is cmmu#%d.\n",
+                  0, cmmu_num);
+       }
+       else if (cmmu_num < 0 || cmmu_num >= MAX_CMMUS)
+       {
+           db_printf("invalid cpu number [%d]... must be in range [0..%d]\n",
+                   cmmu_num, MAX_CMMUS - 1);
+           return;
+       }
+
+       if (cmmu[cmmu_num].cmmu_alive == 0)
+       {
+           db_printf("warning: cmmu %d is not alive.\n", cmmu_num);
+           #if 0
+           return;
+           #endif
+       }
+
+       if (!verbose_flag)
+       {
+           if (!(cmmu[cmmu_num].cmmu_regs->sctr & CMMU_SCTR_SE))
+               db_printf("WARNING: snooping not enabled for CMMU#%d.\n",
+                   cmmu_num);
+       }
+       else
+       {
+           int i;
+           for (i=0; i<MAX_CMMUS; i++)
+               if ((i == cmmu_num || cmmu[i].cmmu_alive) &&
+                   (verbose_flag>1 || !(cmmu[i].cmmu_regs->sctr&CMMU_SCTR_SE)))
+               {
+                   db_printf("CMMU#%d (cpu %d %s) snooping %s\n", i,
+                       cmmu[i].cmmu_cpu, cmmu[i].which ? "data" : "inst",
+                       (cmmu[i].cmmu_regs->sctr & CMMU_SCTR_SE) ? "on":"OFF");
+               }
+       }
+
+       if (supervisor_flag)
+           value = cmmu[cmmu_num].cmmu_regs->sapr;
+       else
+           value = cmmu[cmmu_num].cmmu_regs->uapr;
+
+    }
+
+    /******* LOOK AT THE BATC ** (if not a thread) **************/
+#if 0
+#if SHADOW_BATC
+    if (thread == 0)
+    {
+       int i;
+       union batcu batc;
+       for (i = 0; i < 8; i++) {
+           batc.bits = cmmu[cmmu_num].batc[i];
+           if (batc.field.v == 0) {
+               if (verbose_flag>1)
+                   db_printf("cmmu #%d batc[%d] invalid.\n", cmmu_num, i);
+           } else {
+               db_printf("cmmu#%d batc[%d] v%08x p%08x", cmmu_num, i,
+                       batc.field.lba << 18, batc.field.pba);
+               if (batc.field.s)  db_printf(", supervisor");
+               if (batc.field.wt) db_printf(", wt.th");
+               if (batc.field.g)  db_printf(", global");
+               if (batc.field.ci) db_printf(", cache inhibit");
+               if (batc.field.wp) db_printf(", write protect");
+           }
+       }
+    }
+#endif
+#endif /* 0 */
+
+    /******* SEE WHAT A PROBE SAYS (if not a thread) ***********/ 
+#if 0
+    if (thread == 0)
+#endif /* 0 */
+    {
+       union ssr ssr;
+       struct cmmu_regs *cmmu_regs = cmmu[cmmu_num].cmmu_regs;
+       cmmu_regs->sar = address;
+       cmmu_regs->scr = supervisor_flag ? CMMU_PROBE_SUPER : CMMU_PROBE_USER;
+       ssr.bits = cmmu_regs->ssr;
+        if (verbose_flag > 1)
+           db_printf("probe of 0x%08x returns ssr=0x%08x\n",
+               address, ssr.bits);
+       if (ssr.field.v)
+           db_printf("PROBE of 0x%08x returns phys=0x%x",
+               address, cmmu_regs->sar);
+       else
+           db_printf("PROBE fault at 0x%x", cmmu_regs->pfADDRr);
+       if (ssr.field.ce) db_printf(", copyback err");
+       if (ssr.field.be) db_printf(", bus err");
+       if (ssr.field.wt) db_printf(", writethrough");
+       if (ssr.field.sp) db_printf(", sup prot");
+       if (ssr.field.g)  db_printf(", global");
+       if (ssr.field.ci) db_printf(", cache inhibit");
+       if (ssr.field.m)  db_printf(", modified");
+       if (ssr.field.u)  db_printf(", used");
+       if (ssr.field.wp) db_printf(", write prot");
+       if (ssr.field.bh) db_printf(", BATC");
+       db_printf(".\n");
+    }
+
+    /******* INTERPRET AREA DESCRIPTOR *********/
+    {
+       union apr_template apr_template;
+       apr_template.bits = value;
+        if (verbose_flag > 1) {
+               db_printf("CMMU#%d", cmmu_num);
+#if 0
+           if (thread == 0)
+               db_printf("CMMU#%d", cmmu_num);
+           else
+               db_printf("THREAD %x", thread);
+#endif /* 0 */
+           db_printf(" %cAPR is 0x%08x\n",
+               supervisor_flag ? 'S' : 'U', apr_template.bits);
+       }
+       db_printf("CMMU#%d", cmmu_num);
+#if 0
+       if (thread == 0)
+           db_printf("CMMU#%d", cmmu_num);
+       else
+           db_printf("THREAD %x", thread);
+#endif /* 0 /
+       db_printf(" %cAPR: SegTbl: 0x%x000p",
+           supervisor_flag ? 'S' : 'U', apr_template.field.st_base);
+       if (apr_template.field.wt) db_printf(", WTHRU");
+       else                       db_printf(", !wthru");
+       if (apr_template.field.g)  db_printf(", GLOBAL");
+       else                       db_printf(", !global");
+       if (apr_template.field.ci) db_printf(", $INHIBIT");
+       else                       db_printf(", $ok");
+       if (apr_template.field.te) db_printf(", VALID");
+       else                       db_printf(", !valid");
+       db_printf(".\n");
+
+       /* if not valid, done now */
+       if (apr_template.field.te == 0) {
+           db_printf("<would report an error, valid bit not set>\n");
+           return;
+       }
+
+       value = apr_template.field.st_base << 12; /* now point to seg page */
+    }
+
+    /* translate value from physical to virtual */
+    if (verbose_flag)
+       db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR);
+    value += VEQR_ADDR;
+
+    virtual_address.bits = address;
+    /****** ACCESS SEGMENT TABLE AND INTERPRET SEGMENT DESCRIPTOR  *******/
+    {
+       union sdt_entry_template std_template;
+       if (verbose_flag)
+           db_printf("will follow to entry %d of page at 0x%x...\n",
+               virtual_address.field.segment_table_index, value);
+       value |= virtual_address.field.segment_table_index *
+                sizeof(struct sdt_entry);
+
+       if (badwordaddr(value)) {
+           db_printf("ERROR: unable to access page at 0x%08x.\n", value);
+           return;
+       }
+
+       std_template.bits = *(unsigned *)value;
+        if (verbose_flag > 1)
+           db_printf("SEG DESC @0x%x is 0x%08x\n", value, std_template.bits);
+       db_printf("SEG DESC @0x%x: PgTbl: 0x%x000",
+           value, std_template.sdt_desc.table_addr);
+       if (std_template.sdt_desc.wt)       db_printf(", WTHRU");
+       else                                db_printf(", !wthru");
+       if (std_template.sdt_desc.sup)      db_printf(", S-PROT");
+       else                                db_printf(", UserOk");
+       if (std_template.sdt_desc.g)        db_printf(", GLOBAL");
+       else                                db_printf(", !global");
+       if (std_template.sdt_desc.no_cache) db_printf(", $INHIBIT");
+       else                                db_printf(", $ok");
+       if (std_template.sdt_desc.prot)     db_printf(", W-PROT");
+       else                                db_printf(", WriteOk");
+       if (std_template.sdt_desc.dtype)    db_printf(", VALID");
+       else                                db_printf(", !valid");
+       db_printf(".\n");
+
+       /* if not valid, done now */
+       if (std_template.sdt_desc.dtype == 0) {
+           db_printf("<would report an error, STD entry not valid>\n");
+           return;
+       }
+
+       value = std_template.sdt_desc.table_addr << 12;
+    }
+
+    /* translate value from physical to virtual */
+    if (verbose_flag)
+       db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR);
+    value += VEQR_ADDR;
+
+    /******* PAGE TABLE *********/
+    {
+       union pte_template pte_template;
+       if (verbose_flag)
+           db_printf("will follow to entry %d of page at 0x%x...\n",
+               virtual_address.field.page_table_index, value);
+       value |= virtual_address.field.page_table_index *
+               sizeof(struct pt_entry);
+
+       if (badwordaddr(value)) {
+           db_printf("error: unable to access page at 0x%08x.\n", value);
+           return;
+       }
+
+       pte_template.bits = *(unsigned *)value;
+       if (verbose_flag > 1)
+           db_printf("PAGE DESC @0x%x is 0x%08x.\n", value, pte_template.bits);
+       db_printf("PAGE DESC @0x%x: page @%x000",
+               value, pte_template.pte.pfn);
+       if (pte_template.pte.wired)    db_printf(", WIRE");
+       else                           db_printf(", !wire");
+       if (pte_template.pte.wt)       db_printf(", WTHRU");
+       else                           db_printf(", !wthru");
+       if (pte_template.pte.sup)      db_printf(", S-PROT");
+       else                           db_printf(", UserOk");
+       if (pte_template.pte.g)        db_printf(", GLOBAL");
+       else                           db_printf(", !global");
+       if (pte_template.pte.ci)       db_printf(", $INHIBIT");
+       else                           db_printf(", $ok");
+       if (pte_template.pte.modified) db_printf(", MOD");
+       else                           db_printf(", !mod");
+       if (pte_template.pte.pg_used)  db_printf(", USED");
+       else                           db_printf(", !used");
+       if (pte_template.pte.prot)     db_printf(", W-PROT");
+       else                           db_printf(", WriteOk");
+       if (pte_template.pte.dtype)    db_printf(", VALID");
+       else                           db_printf(", !valid");
+       db_printf(".\n");
+
+       /* if not valid, done now */
+       if (pte_template.pte.dtype == 0) {
+           db_printf("<would report an error, PTE entry not valid>\n");
+           return;
+       }
+       
+       value = pte_template.pte.pfn << 12;
+       if (verbose_flag)
+           db_printf("will follow to byte %d of page at 0x%x...\n",
+               virtual_address.field.page_offset, value);
+       value |= virtual_address.field.page_offset;
+
+       if (badwordaddr(value)) {
+           db_printf("error: unable to access page at 0x%08x.\n", value);
+           return;
+       }
+    }
+
+    /* translate value from physical to virtual */
+    if (verbose_flag)
+       db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR);
+    value += VEQR_ADDR;
+
+    db_printf("WORD at 0x%x is 0x%08x.\n", value, *(unsigned *)value);
+}
+
+
+void
+cmmu_cache_state(unsigned addr, unsigned supervisor_flag)
+{
+    static char *vv_name[4] =
+       {"exclu-unmod", "exclu-mod", "shared-unmod", "invalid"};
+    int cmmu_num;
+    for (cmmu_num = 0; cmmu_num < MAX_CMMUS; cmmu_num++)
+    {
+       union ssr ssr;
+       union cssp cssp;
+       struct cmmu_regs *R;
+       unsigned tag, line;
+       if (!cmmu[cmmu_num].cmmu_alive)
+           continue;
+       R = cmmu[cmmu_num].cmmu_regs;
+       db_printf("cmmu #%d %s cmmu for cpu %d.\n", cmmu_num,
+           cmmu[cmmu_num].which ? "data" : "inst", 
+           cmmu[cmmu_num].cmmu_cpu);
+       R->sar = addr;
+       R->scr = supervisor_flag ? CMMU_PROBE_SUPER : CMMU_PROBE_USER;
+
+       ssr.bits = R->ssr;
+       if (!ssr.field.v) {
+           db_printf("PROBE of 0x%08x faults.\n",addr);
+           continue;
+       }
+       db_printf("PROBE of 0x%08x returns phys=0x%x", addr, R->sar);
+
+       tag = R->sar & ~0xfff;
+       cssp.bits = R->cssp;
+
+       /* check to see if any of the tags for the set match the address */
+       for (line = 0; line < 4; line++)
+       {
+           if (VV(cssp, line) == VV_INVALID)
+           {
+               db_printf("line %d invalid.\n", line);
+               continue; /* line is invalid */
+           }
+           if (D(cssp, line))
+           {
+               db_printf("line %d disabled.\n", line);
+               continue; /* line is disabled */
+           }
+
+           if ((R->ctp[line] & ~0xfff) != tag)
+           {
+               db_printf("line %d address tag is %x.\n", line,
+                       (R->ctp[line] & ~0xfff));
+               continue;
+           }
+           db_printf("found in line %d as %08x (%s).\n",
+               line, R->cdp[line], vv_name[VV(cssp, line)]);
+        }
+    }
+}
+
+void
+show_cmmu_info(unsigned addr)
+{
+    int cmmu_num;
+    cmmu_cache_state(addr, 1);
+
+    for (cmmu_num = 0; cmmu_num < MAX_CMMUS; cmmu_num++)
+       if (cmmu[cmmu_num].cmmu_alive) {
+           db_printf("cmmu #%d %s cmmu for cpu %d: ", cmmu_num,
+               cmmu[cmmu_num].which ? "data" : "inst", 
+               cmmu[cmmu_num].cmmu_cpu);
+           cmmu_show_translation(addr, 1, 0, cmmu_num);
+       }
+}
+#endif /* end if DDB */
diff --git a/sys/arch/mvme88k/mvme88k/conf.c b/sys/arch/mvme88k/mvme88k/conf.c
new file mode 100644 (file)
index 0000000..2e4f06a
--- /dev/null
@@ -0,0 +1,378 @@
+/*     $NetBSD: conf.c,v 1.28 1995/04/19 22:37:27 mycroft Exp $        */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)conf.c     7.9 (Berkeley) 5/28/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+#include <sys/vnode.h>
+
+int    ttselect        __P((dev_t, int, struct proc *));
+
+bdev_decl(sw);
+#include "st.h"
+bdev_decl(st);
+#include "sd.h"
+bdev_decl(sd);
+#include "cd.h"
+bdev_decl(cd);
+
+#if notyet
+#include "ch.h"
+bdev_decl(ch);
+#include "xd.h"
+bdev_decl(xd);
+#endif /* notyet */
+
+#include "vnd.h"
+bdev_decl(vnd);
+
+#ifdef LKM
+int    lkmenodev();
+#else
+#define        lkmenodev       enodev
+#endif
+
+struct bdevsw  bdevsw[] =
+{
+       bdev_notdef(),                  /* 0 */
+       bdev_notdef(),                  /* 1 */
+       bdev_notdef(),                  /* 2 */
+       bdev_swap_init(1,sw),           /* 3: swap pseudo-device */
+       bdev_disk_init(NSD,sd),         /* 4: SCSI disk */
+       bdev_tape_init(NST,st),         /* 5: SCSI tape */
+       bdev_disk_init(NCD,cd),         /* 6: SCSI CD-ROM */
+       bdev_notdef(),                  /* 7 */
+       bdev_disk_init(NVND,vnd),       /* 8: vnode disk driver */
+       bdev_notdef(),                  /* 9 */
+#if notyet
+       bdev_disk_init(NXD,xd),         /* 10: XD disk */
+#endif /* notyet */
+       bdev_notdef(),                  /* 11 */
+       bdev_notdef(),                  /* 12 */
+       bdev_lkm_dummy(),               /* 13 */
+       bdev_lkm_dummy(),               /* 14 */
+       bdev_lkm_dummy(),               /* 15 */
+       bdev_lkm_dummy(),               /* 16 */
+       bdev_lkm_dummy(),               /* 17 */
+       bdev_lkm_dummy(),               /* 18 */
+};
+int    nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
+
+cdev_decl(cn);
+cdev_decl(ctty);
+#define mmread  mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+cdev_decl(sw);
+
+#if notyet
+#include "sram.h"
+cdev_decl(sram);
+
+#include "vmel.h"
+cdev_decl(vmel);
+
+#include "vmes.h"
+cdev_decl(vmes);
+
+#include "nvram.h"
+cdev_decl(nvram);
+
+#include "flash.h"
+cdev_decl(flash);
+#endif /* notyet */
+
+#include "pty.h"
+#define ptstty         ptytty
+#define        ptsioctl        ptyioctl
+cdev_decl(pts);
+#define ptctty         ptytty
+#define        ptcioctl        ptyioctl
+cdev_decl(ptc);
+cdev_decl(log);
+cdev_decl(fd);
+
+#if notyet
+#include "zs.h"
+cdev_decl(zs);
+#endif /* notyet */
+#include "cl.h"
+cdev_decl(cl);
+
+#include "bugtty.h"
+cdev_decl(bugtty);
+
+/* open, close, write, ioctl */
+#define        cdev_lp_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+       dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+       0, seltrue, (dev_type_mmap((*))) enodev }
+
+/* open, close, ioctl, mmap, ioctl */
+#define        cdev_mdev_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       dev_init(c,n,write), dev_init(c,n,ioctl), \
+       (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \
+       dev_init(c,n,mmap) }
+
+#if notyet
+#include "lp.h"
+cdev_decl(lp);
+#include "lptwo.h"
+cdev_decl(lptwo);
+#endif /* notyet */
+
+cdev_decl(st);
+cdev_decl(sd);
+cdev_decl(cd);
+cdev_decl(xd);
+cdev_decl(vnd);
+
+dev_decl(filedesc,open);
+
+#include "bpfilter.h"
+cdev_decl(bpf);
+
+#include "tun.h"
+cdev_decl(tun);
+
+#ifdef LKM
+#define NLKM 1
+#else
+#define NLKM 0
+#endif
+
+cdev_decl(lkm);
+
+struct cdevsw  cdevsw[] =
+{
+       cdev_cn_init(1,cn),             /* 0: virtual console */
+       cdev_ctty_init(1,ctty),         /* 1: controlling terminal */
+       cdev_mm_init(1,mm),             /* 2: /dev/{null,mem,kmem,...} */
+       cdev_swap_init(1,sw),           /* 3: /dev/drum (swap pseudo-device) */
+       cdev_tty_init(NPTY,pts),        /* 4: pseudo-tty slave */
+       cdev_ptc_init(NPTY,ptc),        /* 5: pseudo-tty master */
+       cdev_log_init(1,log),           /* 6: /dev/klog */
+#if notyet
+       cdev_mdev_init(NSRAM,sram),     /* 7: /dev/sramX */
+#else /* notyet */
+       cdev_notdef(),                  /* 7: /dev/sramX */
+#endif /* notyet */
+       cdev_disk_init(NSD,sd),         /* 8: SCSI disk */
+       cdev_disk_init(NCD,cd),         /* 9: SCSI CD-ROM */
+#if notyet
+       cdev_mdev_init(NNVRAM,nvram),   /* 10: /dev/nvramX */
+       cdev_mdev_init(NFLASH,flash),   /* 11: /dev/flashX */
+       cdev_tty_init(NZS,zs),          /* 12: SCC serial (tty[a-d]) */
+#else
+       cdev_notdef(),                  /* 10 */
+       cdev_notdef(),                  /* 11 */
+       cdev_notdef(),                  /* 12: SCC serial (tty[a-d]) */
+#endif /* notyet */
+       cdev_tty_init(NCL,cl),          /* 13: CL-CD1400 serial (tty0[0-3]) */
+       cdev_tty_init(NBUGTTY,bugtty),  /* 14: BUGtty (ttyB) */
+       cdev_notdef(),                  /* 15 */
+       cdev_notdef(),                  /* 16 */
+       cdev_notdef(),                  /* 17: concatenated disk */
+       cdev_notdef(),                  /* 18 */
+       cdev_disk_init(NVND,vnd),       /* 19: vnode disk */
+       cdev_tape_init(NST,st),         /* 20: SCSI tape */
+       cdev_fd_init(1,filedesc),       /* 21: file descriptor pseudo-dev */
+       cdev_bpftun_init(NBPFILTER,bpf),/* 22: berkeley packet filter */
+       cdev_bpftun_init(NTUN,tun),     /* 23: network tunnel */
+       cdev_lkm_init(NLKM,lkm),        /* 24: loadable module driver */
+       cdev_notdef(),                  /* 25 */
+#if notyet
+       cdev_disk_init(NXD,xd),         /* 26: XD disk */
+#else
+       cdev_notdef(),                  /* 26: XD disk */
+#endif /* notyet */
+       cdev_notdef(),                  /* 27 */
+#if notyet
+       cdev_lp_init(NLP,lp),           /* 28: lp */
+       cdev_lp_init(NLPTWO,lptwo),     /* 29: lptwo */
+#else
+       cdev_notdef(),                  /* 28: lp */
+       cdev_notdef(),                  /* 29: lptwo */
+#endif /* notyet */
+       cdev_notdef(),                  /* 30 */
+#if notyet
+       cdev_mdev_init(NVMEL,vmel),     /* 31: /dev/vmelX */
+       cdev_mdev_init(NVMES,vmes),     /* 32: /dev/vmesX */
+#else /* notyet */
+       cdev_notdef(),                  /* 31: /dev/vmelX */
+       cdev_notdef(),                  /* 32: /dev/vmesX */
+#endif /* notyet */
+       cdev_lkm_dummy(),               /* 33 */
+       cdev_lkm_dummy(),               /* 34 */
+       cdev_lkm_dummy(),               /* 35 */
+       cdev_lkm_dummy(),               /* 36 */
+       cdev_lkm_dummy(),               /* 37 */
+       cdev_lkm_dummy(),               /* 38 */
+};
+int    nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
+
+int    mem_no = 2;     /* major device number of memory special file */
+
+/*
+ * Swapdev is a fake device implemented
+ * in sw.c used only internally to get to swstrategy.
+ * It cannot be provided to the users, because the
+ * swstrategy routine munches the b_dev and b_blkno entries
+ * before calling the appropriate driver.  This would horribly
+ * confuse, e.g. the hashing routines. Instead, /dev/drum is
+ * provided as a character (raw) device.
+ */
+dev_t  swapdev = makedev(3, 0);
+
+/*
+ * Returns true if dev is /dev/mem or /dev/kmem.
+ */
+iskmemdev(dev)
+       dev_t dev;
+{
+
+       return (major(dev) == mem_no && minor(dev) < 2);
+}
+
+/*
+ * Returns true if dev is /dev/zero.
+ */
+iszerodev(dev)
+       dev_t dev;
+{
+
+       return (major(dev) == mem_no && minor(dev) == 12);
+}
+
+static int chrtoblktbl[] = {
+       /* XXXX This needs to be dynamic for LKMs. */
+       /*VCHR*/        /*VBLK*/
+       /*  0 */        NODEV,
+       /*  1 */        NODEV,
+       /*  2 */        NODEV,
+       /*  3 */        NODEV,
+       /*  4 */        NODEV,
+       /*  5 */        NODEV,
+       /*  6 */        NODEV,
+       /*  7 */        NODEV,
+       /*  8 */        4,              /* SCSI disk */
+       /*  9 */        6,              /* SCSI CD-ROM */
+       /* 10 */        NODEV,
+       /* 11 */        NODEV,
+       /* 12 */        NODEV,
+       /* 13 */        NODEV,
+       /* 14 */        NODEV,
+       /* 15 */        NODEV,
+       /* 16 */        NODEV,
+       /* 17 */        NODEV,
+       /* 18 */        NODEV,
+       /* 19 */        8,              /* vnode disk */
+       /* 20 */        NODEV,
+       /* 21 */        NODEV,
+       /* 22 */        NODEV,
+       /* 23 */        NODEV,
+       /* 24 */        NODEV,
+       /* 25 */        NODEV,
+       /* 26 */        10,             /* XD disk */
+};
+
+/*
+ * Convert a character device number to a block device number.
+ */
+chrtoblk(dev)
+       dev_t dev;
+{
+       int blkmaj;
+
+       if (major(dev) >= nchrdev ||
+           major(dev) >= sizeof(chrtoblktbl)/sizeof(chrtoblktbl[0]))
+               return (NODEV);
+       blkmaj = chrtoblktbl[major(dev)];
+       if (blkmaj == NODEV)
+               return (NODEV);
+       return (makedev(blkmaj, minor(dev)));
+}
+
+/*
+ * Convert a character device number to a block device number.
+ */
+dev_t
+blktochr(dev)
+       dev_t dev;
+{
+       int blkmaj = major(dev);
+       int i;
+
+       if (blkmaj >= nblkdev)
+               return (NODEV);
+       for (i = 0; i < sizeof(chrtoblktbl)/sizeof(chrtoblktbl[0]); i++)
+               if (blkmaj == chrtoblktbl[i])
+                       return (makedev(i, minor(dev)));
+       return (NODEV);
+}
+
+/*
+ * This entire table could be autoconfig()ed but that would mean that
+ * the kernel's idea of the console would be out of sync with that of
+ * the standalone boot.  I think it best that they both use the same
+ * known algorithm unless we see a pressing need otherwise.
+ */
+#include <dev/cons.h>
+
+#define zscnpollc      nullcnpollc
+cons_decl(zs);
+#define clcnpollc      nullcnpollc
+cons_decl(cl);
+#define bugttycnpollc      nullcnpollc
+cons_decl(bugtty);
+
+struct consdev constab[] = {
+#if NZS > 0
+       cons_init(zs),
+#endif
+#if NCL > 0
+       cons_init(cl),
+#endif
+#if NBUGTTY > 0
+       cons_init(bugtty),
+#endif
+       { 0 },
+};
diff --git a/sys/arch/mvme88k/mvme88k/eh.S b/sys/arch/mvme88k/mvme88k/eh.S
new file mode 100644 (file)
index 0000000..c16d524
--- /dev/null
@@ -0,0 +1,1798 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1991 Carnegie Mellon University
+ * Copyright (c) 1991 OMRON Corporation
+ * Copyright (c) 1996 Nivas Madhur
+ * 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.
+ */
+/*
+ * HISTORY
+ * 1. Should get rid of SR0 reference for thread stuff.
+ * 2. Make up my mind what is _kstack. I think it
+ *             should be p->p_addr+UPAGES. (p_addr
+ *                     is pointing to user struct and swapin is
+ *                     making sure it is updated)
+ *     Whatever is _kstack, its usage in this file should be
+ *     revisited.
+ */
+ /*
+ **************************************************************RCS******
+ *
+ *  -------------------------------------------------------------------
+ * ;  In the following discussion, references are made to:             ;
+ * ;          MC88100 - RISC MICROPROCESSOR USER'S MANUAL              ;
+ * ;  (second edition). Reference in []s refer to section numbers.     ;
+ * ;                                                                   ;
+ * ;  This discussion assumes that you are at least vaguely familiar   ;
+ * ;  with 88100 exception handling (chapter 6), the MACH kernel, and  ;
+ * ;  that you have a brain (and use it while reading this).           ;
+ * ;                                                                   ;
+ * ;  I also assume (and hope) that you're not offended by             ;
+ * ;  frequent misspellings.                                           ;
+ * ;                                                                   ;
+ * ;                       Jeffrey Friedl                              ;
+ * ;                      jfriedl@rna.ncl.omron.co.jp                 ;
+ * ;                       December, 1989                              ;
+ *  -------------------------------------------------------------------
+ *
+ * EXCEPTIONS, INTERRUPTS, and TRAPS
+ * ---------------------------------
+ * This is the machine exception handler.
+ * In the MC88100, various "conditions" cause an exception, where
+ * processing momentarily jumps here to "service" the exception,
+ * and then continues where it left off.
+ *
+ * There are a number of different types of exceptions.
+ * For example, exception #6 is the privilege violation exception which
+ * is raised when the user tries to execute a supervisor-only instruction.
+ *
+ * Exception #1 is the interrupt exception, and is raised when an
+ * outside device raises the INT line on the CPU.  This happens,
+ * for example, when the clock signals that it is time for a context
+ * switch, or perhaps the disk drive signaling that some operation
+ * is complete.
+ *
+ * Traps are also exceptions.  Traps are ways for user programs to request
+ * kernel operations.  For example, "tcnd eq0, r0, 128" will raise
+ * exception 128, the system call exception.
+ *
+ *
+ * SERVICING AN EXCEPTION
+ * -----------------------
+ * When an exception occurs, each control register is saved in its
+ * respective shadow register and execution continues from the
+ * appropriate exception handler.  The exception handler must
+ *      - save the context from the time of the exception
+ *      - service the exception
+ *      - restore the context (registers, etc)
+ *      - pick up from where the exception occurred.
+ *
+ * The context is saved on a stack. Actually, in the user_state area
+ * in the PCB if the exception happens in user mode.
+ *
+ * Servicing the exception is usually straightforward and in fact not dealt
+ * with very much here.  Usually a C routine is called to handle it.
+ * For example, when a privilege exception is raised, the routine that sends
+ * an "illegal instruction" signal to the offending process is called.
+ *
+ * When the exception has been serviced, the context is restored from the
+ * stack and execution resumes from where it left off.
+ *
+ * In more detail:
+ *
+ * Saving the exception-time context.
+ * ---------------------------------
+ *     In saving the exception-time context, we copy the shadow and general
+ * purpose registers to memory.  Since one exception may occur while
+ * servicing another, the memory used to save the exception-time context may
+ * not be static (i.e. the same every time).  Thus, memory on a stack is set
+ * aside for the exception frame (area where the exception-time context is
+ * saved). The same stack is also used when C routines are called (to
+ * service the exception).
+ *
+ *     Each process has a stack in kernel space (called the "kernel stack",
+ * short for "process's kernel stack) as well as the user space stack.  When
+ * entering the kernel from user space, the kernel stack is unused.  On this
+ * stack we save the exception state and (most likely call a C routine to)
+ * service the exception.
+ *
+ * Before servicing an exception, several issues must be addressed.
+ *
+ * 1) When an interrupt is recognized by the hardware, the data pipeline is
+ *    allowed to clear.  However, if one of these data accesses faults (bad
+ *    reference, or a reference to a page which needs to be swapped in), that
+ *    reference, as well as any others in the pipeline at the time (at most
+ *    three total) are left there, to be taken care of by the exception
+ *    handler [6.4.1].  This involves swapping in the proper page and
+ *    manually doing the appropriate load or store.
+ *
+ *    The other (at most, two other) data accesses that might have been in
+ *    the pipeline must also be manually completed (even though they may not
+ *    be at fault [yes, that's a bad pun, thank you]).
+ *
+ * 2) If any of the (at most three) uncompleted data access in the pipeline
+ *    are loads (from memory to a register), then the bit for the destination
+ *    register is set in the SSBR.  Since the hardware will never complete
+ *    that load (since we do it manually), the hardware will never clear that
+ *    SSBR bit.  Thus, we must clear it manually.  If this isn't done, the
+ *    system will hang waiting for a bit to clear that will never.
+ *
+ * 3) If the exception is the privilege violation exception, the bounds
+ *    violation exception, or the misaligned access exception, the
+ *    destination register bit in the SSBR may need to be cleared.
+ *
+ * 4) If the exception is one of the floating exceptions, then the
+ *    destination register for that floating process won't be written,
+ *    and the SSBR must be cleared explicitly.
+ *
+ * 5) The FPU must be enabled (as it is disabled by the exception processing
+ *    hardware) and allowed to complete actions in progress. This is so
+ *    so that it may be used in the servicing of any instruction.
+ *    When the FPU is being restarted, operations attempting to complete
+ *    may themselves fault (raising another exception).
+ *
+ * More on Restarting the FPU
+ * --------------------------
+ *     The manual [section 6.4.3.4] gives only minor mention to this
+ * rather complex task.  Before the FPU is restarted all SSBR bits are
+ * cleared for actions that the exception handler completes (as mentioned
+ * above) so that the SSBR is clear unless there are FPU operations that
+ * have not actually been completed (and hence not written to the registers).
+ * Also, all control registers (at least all those that we care about) are
+ * saved to the stack exception frame before the FPU is restarted (this
+ * is important... the reason comes later).
+ *
+ * The FPU is restarted by doing an rte to a trap-not-taken (the rte
+ * actually enables the fpu because we ensure that the EPSR has the
+ * FPU-enable bit on; the trap-not-taken ensures anything in the FPU
+ * completes by waiting until scoreboard register is clear).
+ *
+ * At the time the FPU is restarted (the rte to the trap-not-taken) the FPU
+ * can write to ANY of the general registers.  Thus, we must make sure that
+ * all general registers (r1..r31) are in their pre-exception state so that
+ * when saved to the exception frame after the FPU is enabled, they properly
+ * reflect any changes made by the FPU in being restarted.
+ *
+ * Because we can't save the pointer to the exception frame in a general
+ * register during the FPU restart (it could get overwritten by the FPU!),
+ * we save it in a control register, SR3, during the restart.
+ *
+ *
+ * HOWEVER .....
+ *
+ * Because other uncompleted actions in the FPU may fault when the FPU is
+ * restarted, a new exception may be raised during the restart. This may
+ * happen recursively a number of times. Thus, during a restart, ANY register
+ * whatsoever may be modified, including control registers.  Because of this
+ * we must make sure that the exception handler preserves SR3 throughout
+ * servicing an exception so that, if the exception had been raised during
+ * an FPU restart, it is returned unmolested when control returns to the FPU
+ * restart.
+ *
+ * Thus: if an exception is from kernel space, we MUST preserve SR3.
+ * (if it from user space, no FPU-enable can be in progress and SR3 is
+ *  unimportant).
+ *
+ * Now is a good time to recap SR0..SR3 usage:
+ *   SR0 - 
+ *   SR1 - CPU flags (exception handler flags)
+ *   SR2 - generally free
+ *   SR3 - free only if the exception is from user mode
+ *
+ * Once the FPU has been restarted, the general registers are saved to the
+ * exception frame.  If the exception is not the interrupt exception,
+ * interrupts are enabled and any faulted data accesses (see above) are
+ * serviced.  In either case, the exception is then serviced (usually by
+ * calling a C routine).  After servicing, any faulted data accesses are
+ * serviced (if it had been the interrupt exception).  The context is then
+ * restored and control returns to where the exception occurred.
+ *
+ */
+
+#ifndef ASSEMBLER
+#define ASSEMBLER
+#endif
+
+#include <machine/trap.h>              /* for T_ defines */
+#include <machine/asm.h>
+
+/*
+ * The exception frame as defined in "machine/pcb.h" (among other places) is
+ * a bit outdated and needs to be changed. Until then, we'll define some
+ * pseudo-fields there for our needs.
+ *
+ * EF_SR3    A place to save the exception-time SR3 from just after the
+ *          time when an exception is raised until just after the FPU
+ *          has been restarted.  This does not necessarly conflict with
+ *          the general registers (though it can if you're not careful)
+ *          and so we can use a spot later used to save a general register.
+ *
+ * EF_FLAGS  This is just the old EF_MODE. "EF_MODE" isn't a very good name.
+ */
+#define EF_SR3                 (EF_R0 + 5)
+#define EF_FLAGS               EF_MODE
+
+#define FLAG_FROM_KERNEL       8       /* this should be in locore.h */
+
+       text
+       align 8
+
+/***************************************************************************
+ ***************************************************************************
+ **
+ ** #define PREP(NAME, NUM, BIT, SSBR_STUFF, FLAG_CHECK)
+ **
+ ** This is the "exception processing preparaton" common to all exception
+ ** processing.  It is used in the following manor:
+ **
+ **    LABEL(foo_handler)
+ **           PREP("foo", 11, DEBUG_FOO_BIT, No_SSBR_Stuff, No_Precheck)
+ **           CALL(_trap, T_FOO_FAULT, r31)
+ **           DONE(DEBUG_FOO_BIT)
+ **
+ ** This defines the exception handler for the "foo" exception.
+ ** The arguments ro PREP():
+ **    NAME -  String for debugging (more info later)
+ **    NUM  -  The exception number [see the manual, Table 6-1]
+ **    BIT  -  Bit to check in eh_debug for debugging (more info later)
+ **    SSBR_STUFF -
+ **            If the exception might leave some bits in the SSBR set,
+ **            this should indicate how they are cleared.
+ **    FLAG_PRECHECK -
+ **            This is for the data access exception only. See it for
+ **            more info.
+ **
+ **
+ ** What's in between PREP() and DONE() (usually a CALL) is the actual
+ ** servicing of the interrupt.  During this time, any register may
+ ** be used freely as they've all been saved in the exception frame
+ ** (which is pointed-to by r31).
+ **/
+#define PREP(NAME, NUM, BIT, SSBR_STUFF, FLAG_PRECHECK)                ; \
+               xcr     FLAGS, FLAGS, SR1                       ; \
+               FLAG_PRECHECK                                   ; \
+                                                               ; \
+               /* the bsr later clobbers r1, so save now */    ; \
+               stcr    r1, SR2 /* r1 now free */               ; \
+                                                               ; \
+               /* set or clear the FLAG_FROM_KERNEL bit */     ; \
+               ldcr    r1, EPSR                                ; \
+               bb0.n   PSR_SUPERVISOR_MODE_BIT, r1, 1f         ; \
+               clr     FLAGS, FLAGS, 1<FLAG_FROM_KERNEL>       ; \
+               set     FLAGS, FLAGS, 1<FLAG_FROM_KERNEL>       ; \
+                                                               ; \
+               /* get a stack (exception frame) */             ; \
+       1:      bsr     setup_phase_one                 ; \
+                                                               ; \
+               /* TMP2 now free -- use to set EF_VECTOR */     ; \
+               or      TMP2, r0, NUM                           ; \
+               st      TMP2, r31, REG_OFF(EF_VECTOR)           ; \
+                                                               ; \
+               /* Clear any bits in the SSBR (held in TMP) */  ; \
+               /* SSBR_STUFF may be empty, though.         */  ; \
+               SSBR_STUFF                                      ; \
+                                                               ; \
+               /* call setup_phase_two to restart the FPU  */  ; \
+               /* and to save all general registers.       */  ; \
+               bsr     setup_phase_two                         ; \
+                                                               ; \
+               /* All general regs free -- do any debugging */ ; \
+               PREP_DEBUG(BIT, NAME)
+
+#undef  EH_DEBUG
+#define EH_DEBUG 1
+
+/* Some defines for use with PREP() */
+#define No_SSBR_Stuff          /* empty */
+#define Clear_SSBR_Dest                bsr clear_dest_ssbr_bit
+#define No_Precheck            /* empty */
+#define Data_Precheck \
+       bb1.n   FLAG_IGNORE_DATA_EXCEPTION, FLAGS, ignore_data_exception
+
+#if EH_DEBUG
+       /*
+        * If we allow debugging, there is a variable "eh_debug"
+        * in which there is a bit for each exception.  If the bit
+        * is set for an exception, debugging information is printed
+        * about that exception whenever it occurs.
+        *
+        * The bits are defined in "locore.h"
+        */
+       LABEL(_eh_debug)        word 0x00000000
+
+       /*
+        * additional pre-servicing preparation to be done when
+        * debugging... check eh_debug and make the call if
+        * need be.
+        */
+       #define PREP_DEBUG(DebugNumber, Name)  \
+               or.u    r2, r0, hi16(_eh_debug)         ; \
+               ld      r3, r2, lo16(_eh_debug)         ; \
+               bb0     DebugNumber, r3, 4f             ; \
+               /* call MY_info(ef,thread,flags,kind)*/ ; \
+               or      r2, r30, r0                     ; \
+               ldcr    r3, SR0                         ; \
+               ldcr    r4, SR1                         ; \
+               or.u    r5, r0, hi16(2f)                ; \
+               or      r5, r5, lo16(2f)                ; \
+               bsr.n   _MY_info                        ; \
+               subu    r31, r31, 40                    ; \
+               br.n    4f                              ; \
+               addu    r31, r31, 40                    ; \
+               data                                    ; \
+            2: string Name                             ; \
+               byte 0                                  ; \
+               align 4                                 ; \
+               text                                    ; \
+            4:
+
+
+       /*
+        * Post-servicing work to be done.
+        * When debugging, check "eh_debug" and call the
+        * debug routined if neeed be.
+        *
+        * Then, return from the interrupt handler.
+        */
+       #define DONE(DebugNumber)  \
+               or.u    r2, r0, hi16(_eh_debug)         ; \
+               ld      r3, r2, lo16(_eh_debug)         ; \
+               bb0     DebugNumber, r3, 2f             ; \
+               ldcr    r4, SR1                         ; \
+               CALL(_MY_info_done, r31, r4)            ; \
+               2: br   return_from_exception_handler
+#else
+       /*
+        * If not debugging, then no debug-prep to do.
+        * Also, when you're done, you're done! (no debug check).
+        */
+       #define PREP_DEBUG(bit, name)
+       #define DONE(num)               br return_from_exception_handler
+#endif
+
+
+/*#########################################################################*/
+/*#### THE ACTUAL EXCEPTION HANDLER ENTRY POINTS ##########################*/
+/*#########################################################################*/
+
+/* unknown exception handler */
+LABEL(unknown_handler)
+       PREP("unknown", 0, DEBUG_UNKNOWN_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_UNKNOWNFLT, r30)
+       DONE(DEBUG_UNKNOWN_BIT)
+
+/* interrupt exception handler */
+LABEL(interrupt_handler)
+       PREP("interrupt", 1, DEBUG_INTERRUPT_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_ext_int, 1, r30)
+       DONE(DEBUG_INTERRUPT_BIT)
+
+/* instruction access exception handler */
+LABEL(instruction_access_handler)
+       PREP("inst", 2, DEBUG_INSTRUCTION_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_INSTFLT, r30)
+#if 0
+       /* done in trap now */
+       /*
+        * Now, to retry the instruction.
+        * Copy the SNIP to the SFIP, clearing the E bit.
+        * Copy the SXIP to the SNIP, clearing the E bit.
+        */
+       ld      r1, r30, REG_OFF(EF_SNIP)
+       ld      r2, r30, REG_OFF(EF_SXIP)
+       clr     r1, r1, 1<RTE_ERROR_BIT>
+       clr     r2, r2, 1<RTE_ERROR_BIT>
+       st      r1, r30, REG_OFF(EF_SFIP)
+       st      r2, r30, REG_OFF(EF_SNIP)
+#endif /* 0 */
+       DONE(DEBUG_INSTRUCTION_BIT)
+
+/*
+ * data access exception handler --
+ *  See badaddr() below for info about Data_Precheck.
+ */
+LABEL(data_exception_handler)
+       PREP("data", 3, DEBUG_DATA_BIT, No_SSBR_Stuff, Data_Precheck)
+       DONE(DEBUG_DATA_BIT)
+
+/* misaligned access exception handler */
+LABEL(misaligned_handler)
+       PREP("misalign", 4, DEBUG_MISALIGN_BIT, Clear_SSBR_Dest, No_Precheck)
+       CALL(_trap, T_MISALGNFLT, r30)
+       DONE(DEBUG_MISALIGN_BIT)
+
+/* unimplemented opcode exception handler */
+LABEL(unimplemented_handler)
+       PREP("unimp", 5, DEBUG_UNIMPLEMENTED_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_ILLFLT, r30)
+       DONE(DEBUG_UNIMPLEMENTED_BIT)
+
+/*
+ * Some versions of the chip have * a bug whereby false privilege
+ * violation exceptions are raised. If the valid bit in the SXIP is clear,
+ * it is false.  If so, just return.  The code before PREP handles this....
+ */
+LABEL(privilege_handler)
+       stcr    r1, SR2         /* hold r1 for a moment */
+       ldcr    r1, SXIP        /* look at the sxip... valid bit set? */
+       bb1.n   RTE_VALID_BIT, r1, 1f /*skip over return if a valid exception*/
+       ldcr    r1, SR2         /* restore r1 */
+       RTE
+    1:  PREP("privilege", 6, DEBUG_PRIVILEGE_BIT, Clear_SSBR_Dest, No_Precheck)
+       CALL(_trap, T_PRIVINFLT, r30)
+       DONE(DEBUG_PRIVILEGE_BIT)
+
+/*
+ * I'm not sure what the trap(T_BNDFLT,...) does, but it doesn't send
+ * a signal to the process...
+ */
+LABEL(bounds_handler)
+       PREP("bounds", 7, DEBUG_BOUNDS_BIT, Clear_SSBR_Dest, No_Precheck)
+       CALL(_trap, T_BNDFLT, r30)
+       DONE(DEBUG_BOUNDS_BIT)
+
+/* integer divide-by-zero exception handler */
+LABEL(divide_handler)
+       PREP("divide", 8, DEBUG_DIVIDE_BIT, Clear_SSBR_Dest, No_Precheck)
+       CALL(_trap, T_ZERODIV, r30)
+       DONE(DEBUG_DIVIDE_BIT)
+
+/* integer overflow exception handelr */
+LABEL(overflow_handler)
+       PREP("overflow", 9, DEBUG_OVERFLOW_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_OVFFLT, r30)
+       DONE(DEBUG_OVERFLOW_BIT)
+
+/* Floating-point precise handler */
+#define FPp_SSBR_STUFF bsr clear_FPp_ssbr_bit
+LABEL(fp_precise_handler)
+       PREP("FPU precise", 114, DEBUG_FPp_BIT, FPp_SSBR_STUFF, No_Precheck)
+       CALL(_Xfp_precise, r0, r30) /* call fp_precise(??, exception_frame)*/
+       DONE(DEBUG_FPp_BIT)
+
+/* Floating-point imprecise handler */
+#define FPi_SSBR_STUFF  bsr clear_FPi_ssbr_bit
+LABEL(fp_imprecise_handler)
+       PREP("FPU imprecise", 115, DEBUG_FPi_BIT, FPi_SSBR_STUFF, No_Precheck)
+       CALL(_Xfp_imprecise, r0, r30) /*call fp_imprecise(??,exception_frame)*/
+       DONE(DEBUG_FPi_BIT)
+
+/* All standard system calls.  */
+LABEL(_syscall_handler)
+       PREP("syscall", 128, DEBUG_SYSCALL_BIT, No_SSBR_Stuff, No_Precheck)
+       ld      r13, r30, GENREG_OFF(13)
+       CALL(_syscall, r13, r30) /* system call no. is in r13 */
+       DONE(DEBUG_SYSCALL_BIT)
+
+/* trap 496 comes here */
+LABEL(_bugtrap)
+       PREP("bugsyscall", 496, DEBUG_BUGCALL_BIT, No_SSBR_Stuff, No_Precheck)
+       ld      r9,  r30, GENREG_OFF(9)
+       CALL(_bugsyscall, r9, r30)      /* system call no. is in r9 */
+       DONE(DEBUG_SYSCALL_BIT)
+
+LABEL(_sigsys)
+       PREP("sigsys", 0, DEBUG_SIGSYS_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_SIGSYS, r30)
+       DONE(DEBUG_SIGSYS_BIT)
+
+LABEL(_sigtrap)
+       PREP("sigtrap", 0, DEBUG_SIGTRAP_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_SIGTRAP, r30)
+       DONE(DEBUG_SIGTRAP_BIT)
+
+LABEL(_stepbpt)
+       PREP("sigtrap", 0, DEBUG_SIGTRAP_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_STEPBPT, r30)
+       DONE(DEBUG_SIGTRAP_BIT)
+
+LABEL(_userbpt)
+       PREP("sigtrap", 0, DEBUG_SIGTRAP_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_USERBPT, r30)
+       DONE(DEBUG_SIGTRAP_BIT)
+
+#if DDB
+   LABEL(break)
+       PREP("break", 130, DEBUG_BREAK_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_KDB_BREAK, r30)
+       DONE(DEBUG_BREAK_BIT)
+   LABEL(trace)
+       PREP("trace", 131, DEBUG_TRACE_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_KDB_TRACE, r30)
+       DONE(DEBUG_TRACE_BIT)
+   LABEL(entry)
+       PREP("kdb", 132, DEBUG_KDB_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_KDB_ENTRY, r30)
+       DONE(DEBUG_KDB_BIT)
+#else /* else not DDB */
+   LABEL(break)
+       PREP("break", 130, DEBUG_BREAK_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_UNKNOWNFLT, r30)
+       DONE(DEBUG_BREAK_BIT)
+   LABEL(trace)
+       PREP("trace", 131, DEBUG_TRACE_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_UNKNOWNFLT, r30)
+       DONE(DEBUG_TRACE_BIT)
+   LABEL(entry)
+       PREP("unknown", 132, DEBUG_UNKNOWN_BIT, No_SSBR_Stuff, No_Precheck)
+       CALL(_trap, T_UNKNOWNFLT, r30)
+       DONE(DEBUG_KDB_BIT)
+#endif /* DDB */
+
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * The error exception handler.
+ * The error exception is raised when any other non-trap exception is raised
+ * while shadowing is off. This is Bad News.
+ *
+ * The shadow registers are not valid in this case (shadowing was off, ne).
+ * R1-R31 may be interesting though, so we'll save them.
+ *
+ * We'll not worry about trashing r26-29 here,
+ * since they aren't generally used.
+ */
+LABEL(error_handler)
+        /* pick up the slavestack */
+       or      r26, r0, r31           /* save old stack */
+        or.u   r31, r0,  hi16(_intstack_end)
+        or     r31, r31, lo16(_intstack_end)
+
+       /* zero the stack, so we'll know what we're lookin' at */
+        or.u   r27, r0,  hi16(_intstack)
+        or     r27, r27, lo16(_intstack)
+   1:  cmp     r28, r27, r31
+       bb1      ge, r28,  2f   /* branch if at the end of the stack */
+       st       r0,  r0, r27
+       br.n     1b
+       addu    r27, r27,   4   /* bump up */
+   2:   /* stack has been cleared */
+
+       /* ensure that stack is 8-byte aligned */
+        clr     r31, r31, 3<0>  /* round down to 8-byte boundary */
+
+       /* create exception frame on stack */
+        subu    r31, r31, SIZEOF_EF             /* r31 now our E.F. */
+
+       /* save old R31 and other R registers */
+        st.d    r0 , r31, GENREG_OFF(0)
+        st.d    r2 , r31, GENREG_OFF(2)
+        st.d    r4 , r31, GENREG_OFF(4)
+        st.d    r6 , r31, GENREG_OFF(6)
+        st.d    r8 , r31, GENREG_OFF(8)
+        st.d    r10, r31, GENREG_OFF(10)
+        st.d    r12, r31, GENREG_OFF(12)
+        st.d    r14, r31, GENREG_OFF(14)
+        st.d    r16, r31, GENREG_OFF(16)
+        st.d    r18, r31, GENREG_OFF(18)
+        st.d    r20, r31, GENREG_OFF(20)
+        st.d    r22, r31, GENREG_OFF(22)
+        st.d    r24, r31, GENREG_OFF(24)
+        st      r30, r31, GENREG_OFF(30)
+       st      r26, r31, GENREG_OFF(31)
+
+       /* save shadow registers (are OLD, though) */
+       ldcr    r10, SXIP
+       st      r10, r31, REG_OFF(EF_SXIP)
+       ldcr    r10, SFIP
+       st      r10, r31, REG_OFF(EF_SFIP)
+       ldcr    r10, SNIP
+       st      r10, r31, REG_OFF(EF_SNIP)
+       ldcr    r10, SSBR
+       st      r10, r31, REG_OFF(EF_SSBR)
+       ldcr    r10, EPSR
+       st      r10, r31, REG_OFF(EF_EPSR)
+
+       ldcr    r10, DMT0
+       st      r10, r31, REG_OFF(EF_DMT0)
+       ldcr    r11, DMD0
+       st      r11, r31, REG_OFF(EF_DMD0)
+       ldcr    r12, DMA0
+       st      r12, r31, REG_OFF(EF_DMA0)
+
+       ldcr    r10, DMT1
+       st      r10, r31, REG_OFF(EF_DMT1)
+       tb1     0, r0, 0
+       ldcr    r11, DMD1
+       st      r11, r31, REG_OFF(EF_DMD1)
+       ldcr    r12, DMA1
+       st      r12, r31, REG_OFF(EF_DMA1)
+
+       ldcr    r10, DMT2
+       st      r10, r31, REG_OFF(EF_DMT2)
+       ldcr    r11, DMD2
+       st      r11, r31, REG_OFF(EF_DMD2)
+       ldcr    r12, DMA2
+       st      r12, r31, REG_OFF(EF_DMA2)
+
+       ldcr    r10, SR1
+       st      r10, r31, REG_OFF(EF_MODE)
+
+       /* shove sr2 into EF_FPLS1 */
+       ldcr    r10, SR2
+       st      r10, r31, REG_OFF(EF_FPLS1)
+
+       /* shove sr3 into EF_FPHS2 */
+       ldcr    r10, SR3
+       st      r10, r31, REG_OFF(EF_FPHS2)
+
+       /* error vector is zippo numero el'zeroooo */
+       st      r0,  r31, REG_OFF(EF_VECTOR)
+
+       stcr    r0,  SSBR  /* won't want shadow bits bothering us later */
+
+       /*
+        * Cheap way to enable FPU and start shadowing again.
+        */
+        ldcr    r10, PSR
+        clr     r10, r10, 1<PSR_FPU_DISABLE_BIT>    /* enable the FPU */
+        clr     r10, r10, 1<PSR_SHADOW_FREEZE_BIT>  /* also enable shadowing */
+       
+        stcr    r10, PSR  /* bang */
+       FLUSH_PIPELINE
+
+       /* put pointer to regs into r30... r31 will become a simple stack */
+       or      r30, r31, r0
+
+        subu    r31, r31, 0x10 /* make some breathing space */
+        st      r30, r31, 0x0c /* store frame pointer on the st */
+        st      r30, r31, 0x08 /* store again for the debugger to recognize */
+       or.u    r20,  r0, hi16(0x87654321)
+       or      r20, r20, lo16(0x87654321)
+       st      r20, r31, 0x04
+       st      r20, r31, 0x00
+
+        CALL(_error_fault, r30, r30)
+
+        /* TURN INTERUPTS back on */
+        ldcr r1, PSR
+       clr  r1, r1, 1<PSR_INTERRUPT_DISABLE_BIT>
+        stcr r1, PSR
+        FLUSH_PIPELINE
+LABEL(_error_loop) bsr _error_loop
+       /* never returns*/
+
+/*
+ *----------------------------------------------------------------------------
+ *----------------------------------------------------------------------------
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ * This is part of baddadr (below).
+ */
+_LABEL(ignore_data_exception)
+       /******************************************************\
+       *  SR0: pointer to the current thread structure        *
+       *  SR1: previous FLAGS reg                             *
+       *  SR2: free                                           *
+       *  SR3: must presere                                   *
+       *  FLAGS:  CPU status flags                            *
+       \******************************************************/
+       xcr     FLAGS, FLAGS, SR1       /* replace SR1, FLAGS */
+
+       /*
+        * For more info, see badaddr() below.
+        *
+        * We just want to jump to "badaddr__return_nonzero" below.
+        *
+        * We don't worry about trashing R2 here because we're
+        * jumping back to the function badaddr() where we're allowd
+        * to blast r2..r9 as we see fit.
+        */
+
+       /* the "+2" below is to set the VALID bit. */
+       or.u    r2, r0, hi16(badaddr__return_nonzero + 2)
+       or      r2, r2, lo16(badaddr__return_nonzero + 2)
+       stcr    r2, SNIP        /* Make it the next instruction to execute */
+       addu    r2, r2, 4
+       stcr    r2, SFIP        /* and the next one after that, too. */
+       stcr    r0, SSBR        /* make the scoreboard happy. */
+
+       /* the following jumps to "badaddr__return_nonzero" in below */
+       RTE
+
+/*
+ * extern boolean_t badaddr(unsigned addr, unsigned len)
+ *
+ * Returns true (non-zero) if the given LEN bytes starting at ADDR are
+ * not all currently accessable by the kernel.
+ *
+ * If all LEN bytes starting at ADDR are accessable, zero is returned.
+ *
+ * Len may be be 1, 2, or 4.
+ *
+ * This is implementd by setting a special flag in SR1 before trying to access
+ * the given address. If a data access exception is raised, the address
+ * is inaccessable. The exception handler will notice the special CPU flag
+ * and not try to swap the address in. Rather, it will return to
+ * "badaddr__return_nonzero" in this routine so that we may return non-zero
+ * to the calling routine.
+ *
+ * If no fault is raised, we continue to where we return zero to the calling
+ * routine (after removing the special CPU flag).
+ */
+
+LABEL(_badaddr)
+       /*
+        * Disable interrupts ... don't want a context switch while we're
+        * doing this! Also, save the old PSR in R8 to restore later.
+        */
+       ldcr    r8, PSR
+       set     r4, r8, 1<PSR_INTERRUPT_DISABLE_BIT>
+       FLUSH_PIPELINE
+       stcr    r4, PSR
+
+       ldcr    r5, SR1
+       set     r5, r5, 1<FLAG_IGNORE_DATA_EXCEPTION>
+       /* resetting r5 to SR1 done in the delay slot below. */
+
+       /*
+        * If it's a word we're doing, do that here. Otherwise,
+        * see if it's a halfword.....
+        */
+       sub     r6, r3, 4
+       bcnd.n  ne0, r6, badaddr__maybe_halfword
+       stcr    r5, SR1
+       FLUSH_PIPELINE
+
+       /*
+        * It's a bad address if it's misaligned.
+        */
+       bb1     0, r2, badaddr__return_nonzero
+       bb1     1, r2, badaddr__return_nonzero
+       /*
+        * The next line will either fault or not. If it faults, execution
+        * will go to:  data_access_handler (see above)
+        * and then to: ignore_data_exception (see above)
+        * and then to: badaddr__return_nonzero (see below)
+        * which will return to the calling function.
+        *
+        * If there is no fault, execution just continues as normal.
+        */
+       ld      r5, r2, 0
+       FLUSH_PIPELINE
+       br.n    badaddr__return
+       or      r2, r0, r0      /* indicate a zero (address not bad) return.*/
+
+    badaddr__maybe_halfword:
+       /* More or less like the code for checking a word above */
+       sub     r6, r3, 2
+       bcnd    ne0, r6, badaddr__maybe_byte
+
+       /* it's bad if it's misaligned */
+       bb1     0, r2, badaddr__return_nonzero
+
+       FLUSH_PIPELINE
+       ld.h    r5, r2, 0
+       FLUSH_PIPELINE
+       br.n    badaddr__return
+       or      r2, r0, r0
+
+    badaddr__maybe_byte:
+       /* More or less like the code for checking a word above */
+       sub     r6, r3, 1
+       bcnd    ne0, r6, badaddr__unknown_size
+       FLUSH_PIPELINE
+       ld.b    r5, r2, 0
+       FLUSH_PIPELINE
+       br.n    badaddr__return
+       or      r2, r0, r0
+    badaddr__unknown_size:
+#ifndef NDEBUG
+       data
+         1: string "bad length (%d) to badaddr() from 0x%x\n\000"
+       text
+       or.u    r2, r0, hi16(1b)
+       or      r2, r2, lo16(1b)
+       or      r4, r0, r1
+       bsr     _printf
+       or.u    r2, r0, hi16(1b)
+       or      r2, r2, lo16(1b)
+       bsr     _panic
+       /*NOTREACHED*/
+#endif
+
+_LABEL(badaddr__return_nonzero)
+       or      r2, r0, 1
+       /* fall through to badaddr__return */
+
+_LABEL(badaddr__return)
+       ldcr    r4, SR1
+       clr     r4, r4, 1<FLAG_IGNORE_DATA_EXCEPTION>
+       stcr    r4, SR1
+
+       /*
+        * Restore the PSR to what it was before.
+        * The only difference is that we might be enabling interrupts
+        * (which we turned off above).  If interrupts were already off,
+        * we do not want to turn them on now, so we just restore from
+        * where we saved it.
+        */
+       FLUSH_PIPELINE
+       stcr    r8, PSR
+       jmp     r1
+
+
+/*
+******************************************************************************
+******************************************************************************
+******************************************************************************
+*/
+
+
+LABEL(setup_phase_one)
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread (if any, null if not)                     *
+       * SR1: saved copy of exception-time register now holding FLAGS  *
+       * SR2: saved copy of exception-time r1                          *
+       * SR3: must be preserved .. may be the exception-time stack     *
+       * r1: return address to calling exception handler               *
+       * FLAGS: CPU status flags                                       *
+       ***************************************************             *
+       * immediate goal:                                               *
+       *       Decide where we're going to put the exception frame.    *
+       *       Might be at the end of R31, SR3, or the thread's        *
+       *       pcb.                                                    *
+       \***************************************************************/
+
+        /* Check if we are coming in from a FPU restart exception.
+           If so, the pcb will be in SR3 */
+       bb1.n   FLAG_ENABLING_FPU, FLAGS, use_SR3_pcb
+       xcr     r1, r1, SR2
+        /* are we coming in from user mode? If so, pick up thread pcb */
+       bb0     FLAG_FROM_KERNEL, FLAGS, pickup_stack
+
+        /* Interrupt in kernel mode, not FPU restart */
+    _LABEL(already_on_kernel_stack)
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread (if any, null if not)                     *
+       * SR1: saved copy of exception-time register now holding FLAGS  *
+       * SR2: return address to the calling exception handler          *
+       * SR3: must be preserved; may be important for other exceptions *
+       * FLAGS: CPU status flags                                       *
+       ***************************************************             *
+       * immediate goal:                                               *
+       *       We're already on the kernel stack, but not having       *
+       *       needed to use SR3. We can just make room on the         *
+       *       stack (r31) for our exception frame.                    *
+       \***************************************************************/
+       subu    r31, r31, SIZEOF_EF           /* r31 now our E.F. */
+       st      FLAGS, r31, REG_OFF(EF_FLAGS) /* save flags */
+       st      r1, r31, GENREG_OFF(1)        /* save prev. r1 (now r1 free)*/
+
+       ldcr    r1, SR3                         /* save previous SR3 */
+       st      r1, r31, REG_OFF(EF_SR3)
+
+       addu    r1, r31, SIZEOF_EF              /* save previous r31 */
+       br.n    have_pcb
+       st      r1, r31, GENREG_OFF(31)
+
+
+    _LABEL(use_SR3_pcb)
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread (if any, null if not)                     *
+       * SR1: saved copy of exception-time register now holding FLAGS  *
+       * SR2: return address to the calling exception handler          *
+       * SR3: must be preserved; exception-time stack pointer          *
+       * FLAGS: CPU status flags                                       *
+       ***************************************************             *
+       * immediate goal:                                               *
+       *       An exception occured while enabling the FPU. Since r31  *
+       *       is the user's r31 while enabling the FPU, we had put    *
+       *       our pcb pointer into SR3, so make room from             *
+       *       there for our stack pointer.                            *
+       *       We need to check if SR3 is the old stack pointer or the *
+        *       pointer off to the user pcb. If it pointing to the user *
+        *       pcb, we need to pick up the kernel stack. Otherwise     *
+        *       we need to allocate a frame upon it.                    *
+        *       We look at the EPSR to see if it was from user mode     *
+        *       Unfortunately, we have no registers free at the moment  *
+        *       But we know register 0 in the pcb frame will always be  *
+        *       zero, so we can use it as scratch storage.              *
+        *                                                               *
+        *                                                               *
+       \***************************************************************/
+       xcr     r30, r30, SR3                   /* r30 = old exception frame */
+        st      r1,  r30, GENREG_OFF(0)         /* free up r1 */
+        ld      r1,  r30, REG_OFF(EF_EPSR)      /* get back the epsr */
+        bb0.n     PSR_SUPERVISOR_MODE_BIT, r1, 1f /* if user mode */
+        ld      r1,  r30, GENREG_OFF(0)         /* restore r1 */
+        /* we were in kernel mode - dump frame upon the stack */
+       st      r0,  r30, GENREG_OFF(0)         /* repair old frame */
+       subu    r30, r30, SIZEOF_EF             /* r30 now our E.F. */
+       st      FLAGS, r30, REG_OFF(EF_FLAGS)   /* save flags */
+       st      r1, r30, GENREG_OFF(1)      /* save prev. r1 (now r1 free) */
+
+       st      r31, r30, GENREG_OFF(31)        /* save previous r31 */
+       or      r31, r0, r30                    /* make r31 our pointer. */
+       addu    r30, r30, SIZEOF_EF             /* r30 now has previous SR3 */
+       st      r30, r31, REG_OFF(EF_SR3)       /* save previous SR3 */
+       br.n    have_pcb
+       xcr     r30, r30, SR3                   /* restore r30 */
+       1:
+         /* we took an exception while restarting the FPU from user space.
+            Consequently, we never picked up a stack. Do so now.
+           R1 is currently free (saved in the exception frame pointed at by
+           r30) */
+       or.u    r1, r0, hi16(_kstack)
+       ld      r1, r1, lo16(_kstack)
+        addu   r1, r1, USIZE-SIZEOF_EF
+       st      FLAGS, r1, REG_OFF(EF_FLAGS)    /* store flags */
+       st      r31, r1,   GENREG_OFF(31)       /* store r31 - now free */
+        st      r30, r1,   REG_OFF(EF_SR3)      /* store old SR3 (pcb) */
+       or      r31, r1, r0     /* make r31 our exception frame pointer */
+       ld      r1,  r30, GENREG_OFF(0)         /* restore old r1 */
+        st     r0,  r30, GENREG_OFF(0)         /* repair that frame */
+       st      r1,  r31, GENREG_OFF(1)    /* store r1 in its proper place */
+       br.n    have_pcb
+       xcr     r30, r30, SR3                   /* restore r30 */
+
+    _LABEL(pickup_stack)
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread                                           *
+       * SR1: saved copy of exception-time register now holding FLAGS  *
+       * SR2: return address to the calling exception handler          *
+       * SR3: free                                                     *
+       * FLAGS: CPU status flags                                       *
+       ***************************************************             *
+       * immediate goal:                                               *
+       *       Since we're servicing an exception from user mode, we   *
+       *       know that SR3 is free.  We use it to free up a temp.    *
+       *       register to be used in getting the thread's pcb         *
+       \***************************************************************/
+       stcr    r31, SR3                /* save previous r31 */
+
+       /* switch to the thread's kernel stack. */
+       or.u    r31, r0,  hi16(_curpcb)
+       ld      r31, r31, lo16(_curpcb)
+       addu    r31, r31, PCB_USER_STATE        /* point to user save area */
+       st      FLAGS, r31, REG_OFF(EF_FLAGS)   /* save flags */
+       st      r1, r31, GENREG_OFF(1)          /* save prev. r1 (now r1 free)*/
+       ldcr    r1, SR3                         /* save previous r31 */
+       st      r1, r31, GENREG_OFF(31)
+       /*FALLTHROUGH */
+
+    _LABEL(have_pcb)
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread                                           *
+       * SR1: saved copy of exception-time register now holding FLAGS  *
+       * SR2: return address to the calling exception handler          *
+       * SR3: free                                                     *
+       * r1:  free                                                     *
+       * FLAGS: CPU status flags                                       *
+       * r31: our exception frame                                      *
+       *    Valid in the exception frame:                              *
+       *       Exception-time r1, r31, FLAGS.                          *
+       *       Exception SR3, if appropriate.                          *
+       ***************************************************             *
+       * immediate goal:                                               *
+       *       Save the shadow registers that need to be saved to      *
+       *       the exception frame.                                    *
+       \***************************************************************/
+       stcr    TMP, SR3        /* free up TMP, TMP2, TMP3 */
+       SAVE_TMP2
+       SAVE_TMP3
+
+       /* save some exception-time registers to the exception frame */
+       ldcr    TMP, EPSR
+       ldcr    TMP2, SFIP
+       ldcr    TMP3, SNIP
+       st      TMP, r31, REG_OFF(EF_EPSR)
+       st      TMP2, r31, REG_OFF(EF_SFIP)
+       st      TMP3, r31, REG_OFF(EF_SNIP)
+
+       /*
+        * Save Pbus fault status register from data and inst CMMU.
+        */
+
+       or.u    TMP, r0, hi16(CMMU_I)
+       ld      TMP2, TMP, lo16(CMMU_I) + 0x108
+       st      TMP2, r31, REG_OFF(EF_IPFSR)
+       or.u    TMP, r0, hi16(CMMU_D)
+       ld      TMP2, TMP, lo16(CMMU_D) + 0x108
+       st      TMP2, r31, REG_OFF(EF_DPFSR)
+
+       ldcr    TMP, SSBR
+       ldcr    TMP2, SXIP
+       ldcr    TMP3, DMT0
+       st      TMP2, r31, REG_OFF(EF_SXIP)
+
+#if 0
+       /*
+        * The following is a kludge so that
+        * a core file will have a copy of
+        * DMT0 so that 'sim' can display it
+        * correctly.
+        * After a data fault has been noticed,
+        * the real EF_DTM0 is cleared, so I need
+        * to throw this somewhere.
+        * There's no special reason I chose this
+        * register (FPIT)... it's just one of many
+        * for which it causes no pain to do this.
+        */
+       st TMP3, r31, REG_OFF(EF_FPIT)
+#endif
+
+       /*
+        * The above shadow registers are obligatory for any and all
+        * exceptions.  Now, if the data access pipeline is not clear,
+        * we must save the DMx shadow registers, as well as clear
+        * the appropriate SSBR bits for the destination registers of
+        * loads or xmems.
+        */
+       bb0.n   DMT_VALID_BIT, TMP3, DMT_check_finished
+       st      TMP3, r31, REG_OFF(EF_DMT0)
+
+       ldcr    TMP2, DMT1
+       ldcr    TMP3, DMT2
+       st      TMP2, r31, REG_OFF(EF_DMT1)
+       st      TMP3, r31, REG_OFF(EF_DMT2)
+
+       ldcr    TMP2, DMA0
+       ldcr    TMP3, DMA1
+       st      TMP2, r31, REG_OFF(EF_DMA0)
+       st      TMP3, r31, REG_OFF(EF_DMA1)
+
+       ldcr    TMP2, DMA2
+       ldcr    TMP3, DMD0
+       st      TMP2, r31, REG_OFF(EF_DMA2)
+       st      TMP3, r31, REG_OFF(EF_DMD0)
+
+       tb1     0,r0,0
+       ldcr    TMP2, DMD1
+       ldcr    TMP3, DMD2
+       st      TMP2, r31, REG_OFF(EF_DMD1)
+       st      TMP3, r31, REG_OFF(EF_DMD2)
+
+       /*
+         *---------------------------------------------------------------
+        * need to clear "appropriate" bits in the SSBR before
+        * we restart the FPU
+        */
+
+
+    _LABEL(check_DMT0)
+       ldcr    TMP2, DMT0
+       bb0.n   DMT_VALID_BIT, TMP2, DMT_check_finished
+       stcr    r0, DMT0 /* so an exception at fpu_enable doesn't see our DMT0*/
+       bb1     DMT_LOCK_BIT,  TMP2, do_DMT0
+       bb1     DMT_WRITE_BIT, TMP2, check_DMT1
+        _LABEL(do_DMT0)
+       extu    TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET>
+       set     TMP2, TMP2, 1<5>
+       clr     TMP, TMP, TMP2
+
+    _LABEL(check_DMT1)
+       ldcr    TMP2, DMT1
+       bb0     DMT_VALID_BIT, TMP2, check_DMT2
+       bb1     DMT_LOCK_BIT,  TMP2, do_DMT1
+       bb1     DMT_WRITE_BIT, TMP2, check_DMT2
+        _LABEL(do_DMT1)
+       extu    TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET>
+       set     TMP2, TMP2, 1<5>
+       clr     TMP, TMP, TMP2
+
+    _LABEL(check_DMT2)
+       ldcr    TMP2, DMT2
+       bb0     DMT_VALID_BIT, TMP2, DMT_check_finished
+       bb1     DMT_LOCK_BIT,  TMP2, do_DMT2_single
+       bb1     DMT_WRITE_BIT, TMP2, DMT_check_finished
+       bb1     DMT_DOUBLE_BIT,TMP2, do_DMT2_double
+        _LABEL(do_DMT2_single)
+       extu    TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET>
+       br.n    1f
+       set     TMP2, TMP2, 1<5>
+       _LABEL(do_DMT2_double)
+       extu    TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET>
+       set     TMP2, TMP2, 1<6>
+1:     clr     TMP, TMP, TMP2
+
+    _LABEL(DMT_check_finished)
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread                                           *
+       * SR1: saved copy of exception-time register now holding FLAGS  *
+       * SR2: return address to the calling exception handler          *
+       * SR3: saved TMP                                                *
+       * r1:  free                                                     *
+       * TMP: possibly revised SSBR                                    *
+       * TMP2: free                                                    *
+       * TMP3: free                                                    *
+       * FLAGS: CPU status flags                                       *
+       * r31: exception frame                                          *
+       *    Valid in the exception frame:                              *
+       *       Exception-time r1, r31, FLAGS.                          *
+       *       Exception-time TMP2, TMP3.                              *
+       *       Exception-time espr, sfip, snip, sxip.                  *
+       *       Dmt0.                                                   *
+       *       Other data pipeline control registers, if appropriate.  *
+       *       Exception SR3, if appropriate.                          *
+       \***************************************************************/
+       ldcr    r1, SR2
+       jmp     r1 /* return to allow the handler to clear more SSBR bits */
+
+/************************************************************************/
+/************************************************************************/
+
+    _LABEL(clear_FPi_ssbr_bit)
+       /*
+        * Clear floatingpont-imprecise ssbr bits.
+        * Also, save appropriate FPU control registers to the E.F.
+        *
+        *  r1:  return address to calling exception handler
+         *  TMP : (possibly) revised ssbr
+         *  TMP2 : free
+         *  TMP3 : free
+        */
+       fldcr   TMP2, FPSR
+       fldcr   TMP3, FPCR
+       st      TMP2, r31, REG_OFF(EF_FPSR)
+       st      TMP3, r31, REG_OFF(EF_FPCR)
+
+       fldcr   TMP2, FPECR
+       fldcr   TMP3, FPRH
+       st      TMP2, r31, REG_OFF(EF_FPECR)
+       st      TMP3, r31, REG_OFF(EF_FPRH)
+
+       fldcr   TMP2, FPIT
+       fldcr   TMP3, FPRL
+       st      TMP2, r31, REG_OFF(EF_FPIT)
+       st      TMP3, r31, REG_OFF(EF_FPRL)
+
+       /*
+        * We only need clear the bit in the SSBR for the
+        * 2nd reg of a double result [see section 6.8.5]
+        */
+       #define FPIT_SIZE_BIT   10
+       bb0     FPIT_SIZE_BIT, TMP2, not_double_fpi
+       extu    TMP2, TMP2, 5<0>  /* get the reg. */
+       set     TMP2, TMP2, 1<6>  /* set width (width=2 will clear two bits) */
+       clr     TMP, TMP, TMP2
+
+       _LABEL(not_double_fpi)
+       jmp     r1
+
+
+/************************************************************************/
+/************************************************************************/
+
+
+    _LABEL(clear_FPp_ssbr_bit)
+       /*
+        * Clear floating pont precise ssbr bits.
+        * Also, save appropriate FPU control registers to the E.F.
+        *
+        *  r1:  return address to calling exception handler
+         *  TMP : (possibly) revised ssbr
+         *  TMP2 : free
+         *  TMP3 : free
+        */
+       fldcr   TMP2, FPSR
+       fldcr   TMP3, FPCR
+       st      TMP2, r31, REG_OFF(EF_FPSR)
+       st      TMP3, r31, REG_OFF(EF_FPCR)
+
+       fldcr   TMP2, FPHS1
+       fldcr   TMP3, FPHS2
+       st      TMP2, r31, REG_OFF(EF_FPHS1)
+       st      TMP3, r31, REG_OFF(EF_FPHS2)
+
+       fldcr   TMP2, FPLS1
+       fldcr   TMP3, FPLS2
+       st      TMP2, r31, REG_OFF(EF_FPLS1)
+       st      TMP3, r31, REG_OFF(EF_FPLS2)
+
+       fldcr   TMP2, FPPT
+       fldcr   TMP3, FPECR
+       st      TMP2, r31, REG_OFF(EF_FPPT)
+       st      TMP3, r31, REG_OFF(EF_FPECR)
+
+       #define         FPPT_SIZE_BIT   5
+       bb1.n   FPPT_SIZE_BIT, TMP2, 1f
+       extu    TMP3, TMP2, 5<0> /* get FP operation dest reg */
+       br.n    2f
+       set     TMP3, TMP3, 1<5> /* set size=1 -- clear one bit for "float" */
+     1: set    TMP3, TMP3, 1<6> /* set size=2 -- clear two bit for "double" */
+     2:
+       clr     TMP, TMP, TMP3  /* clear bit(s) in ssbr. */
+       jmp     r1
+
+
+/************************************************************************/
+/************************************************************************/
+
+
+    _LABEL(clear_dest_ssbr_bit)
+       /*
+        * There are various cases where an exception can leave the
+        * destination register's bit in the SB set.
+        * Examples:
+        *      misaligned or privilege exception on a LD or XMEM
+        *      DIV or DIVU by zero.
+        *
+        * I think that if the instruction is LD.D, then two bits must
+        * be cleared.
+        *
+        * Even though there are a number of instructions/exception
+        * combinations that could fire this code up, it's only required
+        * to be run for the above cases.  However, I don't think it'll
+        * ever be a problem to run this in other cases (ST instructions,
+        * for example), so I don't bother checking.  If we had to check
+        * for every possible instruction, this code would be much larger.
+        *
+        * The only checking, then, is to see if it's a LD.D or not.
+        *
+        * At the moment....
+        *  r1:  return address to calling exception handler
+         *  TMP : (possibly) revised ssbr
+         *  TMP2 : free
+         *  TMP3 : free
+        */
+       ldcr    TMP3, EPSR      /* going to check: user or system memory? */
+       ldcr    TMP2, SXIP      /* get the instruction's address */
+       bb1.n   PSR_SUPERVISOR_MODE_BIT, TMP3, 2f
+       clr     TMP2, TMP2, 2<0> /* get rid of valid and error bits. */
+
+    1:  /* user space load here */
+#if ERRATA__XXX_USR
+       NOP
+       ld.usr  TMP2, TMP2, r0          /* get the instruction itself */
+       NOP
+       NOP
+       NOP
+       br      3f
+#else
+       br.n    3f
+       ld.usr  TMP2, TMP2, r0          /* get the instruction itself */
+#endif
+
+    2:  /* system space load here */
+       ld      TMP2, TMP2, r0          /* get the instruction itself */
+
+    3:  /* now have the instruction..... */
+       /*
+        * Now see if it's a double load
+        * There are three forms of double load [IMM16, scaled, unscaled],
+        * which can be checked by matching against two templates:
+        *                       -- 77776666555544443333222211110000 --
+        *      if (((instruction & 11111100000000000000000000000000) ==
+        *                          00010000000000000000000000000000) ;;
+        *          ((instruction & 11111100000000001111110011100000) ==
+        *                          11110100000000000001000000000000))
+        *      {
+        *              It's a load double, so
+        *              clear two SSBR bits.
+        *      }
+        *      else
+        *      {
+        *              It's not a load double.
+        *              Must be a load single, xmem, or st
+        *              Thus, clear one SSBR bit.
+        *      }
+        */
+       /* check the first pattern for ld.d */
+       extu    TMP3, TMP2, 16<16>      /* get the upper 16 bits */
+       mask    TMP3, TMP3, 0xFC00      /* apply the mask */
+       cmp     TMP3, TMP3, 0x1000  /* if this is equal, it's a load double */
+       bb1     eq,   TMP3, misaligned_double
+
+       /* still could be -- check the second pattern for ld.d */
+       /* look at the upper 16 bits first */
+       extu    TMP3, TMP2, 16<16>  /* get the upper 16 bits */
+       mask    TMP3, TMP3, 0xFC00  /* apply the mask */
+       cmp     TMP3, TMP3, 0xF400  /* if equal, it might be a load double */
+       bb1     ne,   TMP3, misaligned_single /* not equal, so must be single */
+
+       /* now look at the lower 16 bits */
+       extu    TMP3, TMP2, 16<0>    /* get the lower 16 bits */
+       mask    TMP3, TMP3, 0xFCE0   /* apply the mask */
+       cmp     TMP3, TMP3, 0x1000   /* if this is equal, it's a load double */
+       bb1     eq,   TMP3, misaligned_double
+
+      _LABEL(misaligned_single)
+       extu    TMP2, TMP2, 5<21>       /* get the destination register */
+       br.n    1f
+        set    TMP2, TMP2, 1<5>        /* set size=1 */
+
+      _LABEL(misaligned_double)
+       extu    TMP2, TMP2, 5<21>  /* get the destination register */
+        set    TMP2, TMP2, 1<6>   /* set size=2 -- clear two bit for "ld.d" */
+
+     1: jmp.n  r1
+       clr     TMP, TMP, TMP2  /* clear bit(s) in ssbr. */
+
+/************************************************************************/
+/************************************************************************/
+
+
+
+  LABEL(setup_phase_two)
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread                                           *
+       * SR1: saved copy of exception-time register now holding FLAGS  *
+       * SR2: free                                                     *
+       * SR3: saved TMP                                                *
+       * r1:  return address to calling exception handler              *
+       * TMP: possibly revised SSBR                                    *
+       * TMP2: free                                                    *
+       * TMP3: free                                                    *
+       * FLAGS: CPU status flags                                       *
+       * r31: our exception frame                                      *
+       *    Valid in the exception frame:                              *
+       *       Exception-time r1, r31, FLAGS.                          *
+       *       Exception-time TMP2, TMP3.                              *
+       *       Exception-time espr, sfip, snip, sxip.                  *
+       *       Exception number (EF_VECTOR).                           *
+       *       Dmt0                                                    *
+       *       Other data pipeline control registers, if appropriate.  *
+       *       FPU control registers, if appropriate.                  *
+       *       Exception SR3, if appropriate.                          *
+       ***************************************************             *
+       * immediate goal:                                               *
+       *       restore the system to the exception-time state (except  *
+       * SR3 will be OUR stack pointer) so that we may resart the FPU. *
+       \***************************************************************/
+       stcr    TMP, SSBR       /* done with SSBR, TMP now free */
+       RESTORE_TMP2            /* done with extra temp regs */
+       RESTORE_TMP3            /* done with extra temp regs */
+
+       /* Get the current PSR and modify for the rte to enable the FPU */
+       ldcr    TMP, PSR
+       clr     TMP, TMP, 1<PSR_FPU_DISABLE_BIT>    /* enable the FPU */
+        clr    TMP, TMP, 1<PSR_SHADOW_FREEZE_BIT>  /* also enable shadowing */
+       stcr    TMP, EPSR
+
+       /* the "+2" below is to set the VALID_BIT */
+       or.u    TMP, r0, hi16(fpu_enable + 2)
+       or      TMP, TMP, lo16(fpu_enable + 2)
+       stcr    TMP, SNIP               /* jump to here fpu_enable */
+       addu    TMP, TMP, 4
+       stcr    TMP, SFIP               /* and then continue after that */
+
+       set     FLAGS, FLAGS, 1<FLAG_ENABLING_FPU> /* note what we're doing.*/
+       xcr     FLAGS, FLAGS, SR1
+       st      r1, r31, REG_OFF(EF_RET) /* save the return address */
+       ld      r1, r31, GENREG_OFF(1)   /* get original r1 */
+
+       xcr     TMP, r31, SR3   /* TMP now restored. R31 now saved in SR3 */
+       ld      r31, r31, GENREG_OFF(31) /* get original r31 */
+
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread                                           *
+       * SR1: CPU flags                                                *
+       * SR2: free                                                     *
+       * SR3: pointer to our exception frame (our stack pointer)       *
+       * r1 through r31: original exception-time values                *
+       *                                                               *
+       *    Valid in the exception frame:                              *
+       *       Exception-time FLAGS.                                   *
+       *       Exception-time espr, sfip, snip, sxip.                  *
+       *       Exception number (EF_VECTOR).                           *
+       *       Dmt0                                                    *
+       *       Other data pipeline control registers, if appropriate.  *
+       *       FPU control registers, if appropriate.                  *
+       *       Exception SR3, if appropriate.                          *
+       *   Held temporarly in the exception frame:                     *
+       *       Return address to the calling excption handler.         *
+       ***************************************************             *
+       * immediate goal:                                               *
+       *       Do an RTE to restart the fpu and jump to "fpu_enable"   *
+       *       Another exception (or exceptions) may be raised in      *
+       *       this, which is why FLAG_ENABLING_FPU is set in SR1.     *
+       \***************************************************************/
+       RTE     /* jumps to "fpu_enable" on the next line to enable the FPU. */
+
+  _LABEL(fpu_enable)
+       FLUSH_PIPELINE
+       xcr     TMP, TMP, SR3            /* get E.F. pointer */
+       st.d    r30, TMP, GENREG_OFF(30) /* save previous r30, r31 */
+       or      r31, TMP, r0             /* transfer E.F. pointer to r31 */
+       ld      TMP, r31, REG_OFF(EF_SR3)/* get previous SR3; maybe important*/
+
+       /* make sure that the FLAG_ENABLING_FPU bit is off */
+       xcr     FLAGS, FLAGS, SR1
+       clr     FLAGS, FLAGS, 1<FLAG_ENABLING_FPU>
+       xcr     FLAGS, FLAGS, SR1
+
+       xcr     TMP, TMP, SR3            /* replace TMP, SR3 */
+
+       /* now save all regs to the exception frame. */
+       st.d    r0 , r31, GENREG_OFF(0)
+       st.d    r2 , r31, GENREG_OFF(2)
+       st.d    r4 , r31, GENREG_OFF(4)
+       st.d    r6 , r31, GENREG_OFF(6)
+       st.d    r8 , r31, GENREG_OFF(8)
+       st.d    r10, r31, GENREG_OFF(10)
+       st.d    r12, r31, GENREG_OFF(12)
+       st.d    r14, r31, GENREG_OFF(14)
+       st.d    r16, r31, GENREG_OFF(16)
+       st.d    r18, r31, GENREG_OFF(18)
+       st.d    r20, r31, GENREG_OFF(20)
+       st.d    r22, r31, GENREG_OFF(22)
+       st.d    r24, r31, GENREG_OFF(24)
+       st.d    r26, r31, GENREG_OFF(26)
+       st.d    r28, r31, GENREG_OFF(28)
+#ifdef JEFF_DEBUG
+       /* mark beginning of frame with notable value */
+       or.u r20,  r0, hi16(0x12345678)
+       or   r20, r20, lo16(0x12345678)
+       st   r20, r31, GENREG_OFF(0)
+#endif
+
+       /***************** REGISTER STATUS BLOCK ***********************\
+       * SR0: current thread                                           *
+       * SR1: free                                                     *
+       * SR2: free                                                     *
+       * SR3: previous exception-time SR3                              *
+       * r1: return address to the calling exception handler           *
+       * r2 through r30: free                                          *
+       * r31: our exception frame                                      *
+       *                                                               *
+       *    Valid in the exception frame:                              *
+       *       Exception-time r0 through r31.                          *
+       *       Exception-time FLAGS.                                   *
+       *       Exception-time espr, sfip, snip, sxip.                  *
+       *       Exception number (EF_VECTOR).                           *
+       *       Dmt0                                                    *
+       *       Other data pipeline control registers, if appropriate.  *
+       *       FPU control registers, if appropriate.                  *
+       *       Exception SR3, if appropriate.                          *
+       ***************************************************             *
+       * immediate goal:                                               *
+        *      Pick up a stack if we came in from user mode. Put       *
+        *       A copy of the exception frame pointer into r30          *
+        *       bump the stack a doubleword and write the exception     *
+        *       frame pointer.                                          *
+       *       if not an interrupt exception,                          *
+       *           Turn on interrupts and service any outstanding      *
+       *           data access exceptions.                             *
+       *       Return to calling exception handler to                  *
+       *       service the exception.                                  *
+       \***************************************************************/
+
+       /*
+        * If it's not the interrupt exception, enable interrupts and
+        * take care of any data access exceptions......
+        *
+#if notyet
+        * If interrupt exception, switch to interrupt stack if not
+        * already there. Else, switch to kernel stack.
+#endif
+        */
+       or      r30, r0, r31              /* get a copy of the e.f. pointer */
+        ld     r2,  r31, REG_OFF(EF_EPSR)
+       bb1     PSR_SUPERVISOR_MODE_BIT, r2, 1f  /* If in kernel mode */
+
+#if notyet
+       ld      r3,  r31, REG_OFF(EF_VECTOR)
+       cmp     r3,  r3, 1              /* is interrupt ? */
+       bb0     eq,  r3, 2f
+       or.u    r31, r0,  hi16(_intstack_end)   /* swith to int stack */
+       or      r31, r31, lo16(_intstack_end)
+       br      3f
+  2:
+#endif
+       or.u    r31, r0,  hi16(_kstack)
+       ld      r31, r31, lo16(_kstack)
+       addu    r31, r31, USIZE        /* point at proper end */
+       br      3f
+  1:
+#if notyet
+       ld      r3,  r31, REG_OFF(EF_VECTOR)
+       cmp     r3,  r3, 1              /* is interrupt ? */
+       bb0     eq,  r3, 3f             /* no, we will stay on kern stack */
+       or.u    r31, r0,  hi16(_intstack_end)   /* swith to int stack */
+       or      r31, r31, lo16(_intstack_end)
+#endif /* notyet */
+ /* This label is here for debugging */
+ exception_handler_has_ksp:  global exception_handler_has_ksp
+  3:    /*
+           here - r30 holds a pointer to the exception frame.
+           r31 is a pointer to the kernel stack/interrupt stack.
+        */
+       subu    r31, r31, 8  /* make some breathing space */
+       st      r30, r31, 0  /* store frame pointer on the stack */
+#if DDB
+       st      r30, r31, 4  /* store it again for the debugger to recognize */
+#endif DDB
+
+       ld      r2, r30, REG_OFF(EF_VECTOR)
+        bcnd.n  eq0, r2, return_to_calling_exception_handler  /* is error */
+        ld     r14, r30, REG_OFF(EF_RET)
+       cmp     r3, r2, 1 /* interrupt is exception #1 ;Is an interrupt? */
+       bb1.n   eq, r3, return_to_calling_exception_handler /* skip if so */
+
+#if DDB
+       cmp     r3, r2, 130 /* DDB break exception */
+        bb1.n   eq, r3, return_to_calling_exception_handler
+
+        cmp     r3, r2, 132 /* DDB entry exception */
+        bb1.n   eq, r3, return_to_calling_exception_handler
+#endif
+
+       ldcr    r2, PSR
+       clr     r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>    /* enable interrupts */
+       stcr    r2, PSR
+#if     DDB
+       FLUSH_PIPELINE
+#endif
+
+       /* service any outstanding data pipeline stuff
+          - check dmt0 anything outstanding?*/
+
+       ld      r3, r30, REG_OFF(EF_DMT0)
+       bb0     DMT_VALID_BIT, r3, return_to_calling_exception_handler
+
+/*
+        r30 can be clobbered by calls. So stuff its value into a
+        preserved register, say r15. R14 is in use (see return_to_... below).
+ */
+       or      r15, r0, r30
+
+       CALL(_trap, T_DATAFLT, r15)
+       CALL(_data_access_emulation, r15, r0)
+
+/*     restore it... */
+       or      r30, r0, r15
+
+       /* clear the dmt0 word in the E.F */
+       st      r0, r30, REG_OFF(EF_DMT0)
+
+    _LABEL(return_to_calling_exception_handler)
+       jmp     r14 /* loaded above */
+
+
+/*
+ * proc_trampoline.
+ * When a process setup by cpu_set_kpc() resumes, it will find itself in
+ * proc_trampoline, with r31 pointing to a ksigframe. proc_trampoline will
+ * load func and proc values from ksigframe, call the function, and on return
+ * pop off the ksigframe. Then, it will load pc from the switchframe and
+ * jump there.
+ */
+
+ENTRY(proc_trampoline)
+       ld      r1,r31,0                /* load func */
+       ld      r2,r31,4                /* load proc pointer */
+       jsr.n   r1
+       subu    r31,r31,40              /* create stack space for function */
+       addu    r31,r31,48              /* stack space above + ksigframe */
+       ld      r1, r31,0               /* load pc */
+       ld      r2, r31,4               /* & proc pointer from switch frame */
+       jsr.n   r1
+       addu    r31,r31,8
+       bsr     _panic
+
+/*
+ * proc_do_uret 
+ * this is called as proc_do_uret(proc) from proc_trampoline(). This function
+ * loads r31 with a pointer to the trap frame for the given proc and calls
+ * return_from_exception_handler which loads all the registers and does an
+ * rte.
+ */
+
+ENTRY(proc_do_uret)
+       ld      r3,r2,P_ADDR                    /* p->p_addr */
+       addu    r3,r3,PCB_USER_STATE            /* p->p_addr.u_pcb.user_state */
+       st      r3,r31,0                        /* put it on the stack */
+       br      return_from_exception_handler
+       
+LABEL(return_from_exception_handler)
+LABEL(_return_from_main)
+       /*
+        * Regs r1-r30 are free. R31 is pointing at the word
+         * on the kernel stack where our pointer to the exception frame
+         * it stored. Reload it now.
+        *
+        * At this point, if EF_DMT0 is not zero, then
+        * this must have been an interrupt where the fault didn't
+        * get corrected above.  We'll do that now.
+        *
+        * We load it into r14 since it is preserved across function
+        * calls, and we may have to call some routines from within here.
+        *
+        * control is transfered here from obvious places in this file
+         * and thread_bootstrap in luna88k/locore.c.
+        *
+        */
+#define FPTR    r14
+       ld      FPTR, r31, 0                 /* grab exception frame pointer */
+       ld      r3, FPTR, REG_OFF(EF_DMT0)
+       bb0     DMT_VALID_BIT, r3, _check_ast /*[Oh well, nothing to do here] */
+
+#if 1
+           /*
+           * This might happen for non-interrupts  If the user sets DMT0
+           * in an exception handler.........
+           */
+           ld  r2, FPTR, REG_OFF(EF_VECTOR)
+           cmp r2, r2, 1 /* interrupt is exception #1 ; Is an interrupt? */
+           bb1 eq, r2, 1f
+           LABEL(oops)
+           or.u        r4, r0, hi16(2f)
+           or          r4, r4, lo16(2f)
+#if DDB
+           CALL(_db_printf, r4, r0)
+           tb0 0, r0, 132
+#endif
+            br 1f
+               data
+               2:  string "OOPS: DMT0 not zero and not interrupt.\n\000"
+                   align 8
+               text
+       1:
+#endif
+       /*
+        * If it's the interrupt exception, enable interrupt.
+        * Take care of any data access exception...... 90/8/15 add by yama
+        */
+
+       /*
+        * Is it ever possible to have interrupt exception while EPSR has
+        * it disabled? I don't think so.. XXX nivas
+        */
+       ld      r2, FPTR, REG_OFF(EF_VECTOR)
+       cmp     r2, r2, 1   /* interrupt is exception #1 ; Is an interrupt? */
+        bb1    ne, r2, 1f  /* If not so, skip */
+
+        /* if EPSR has interrupts disabled, skip also */
+       ld      r2, FPTR, REG_OFF(EF_EPSR)
+        bb1    PSR_INTERRUPT_DISABLE_BIT, r2, 1f        /* skip if disabled */
+       ldcr    r2, PSR
+       clr     r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>     /* enable interrupts */
+        FLUSH_PIPELINE
+        stcr   r2, PSR
+   1:
+       ld      r2, FPTR, REG_OFF(EF_DMT0)
+       bb0     DMT_VALID_BIT, r2, 2f
+
+       /*
+        * if there happens to be a data fault that hasn't been serviced yet,
+        * go off and service that...
+        */
+       CALL(_trap, T_DATAFLT, r30)
+       CALL(_data_access_emulation, r30, r0)     /* really only 2 args */
+
+       /* clear the dmt0 word in the E.F. */
+       st      r0 , FPTR, REG_OFF(EF_DMT0)
+   2:
+
+/*
+ *     If the saved ipl is 0, then call dosoftint() to process soft
+ *     interrupts.
+ *     If returning to user land, look for ASTs
+ */
+
+LABEL(_check_ast)
+
+       ld      r2, FPTR, REG_OFF(EF_EPSR)   /* get pre-exception PSR */
+        bb1    PSR_INTERRUPT_DISABLE_BIT, r2, 1f /* skip if ints off */
+       ld      r2, FPTR, REG_OFF(EF_MASK)   /* get pre-exception ipl */
+       bcnd    ne0, r2, 1f                  /* can't do softint's */
+       bsr.n   _setipl
+       or      r2,r0,1
+       bsr     _dosoftint
+       /* is this needed? we are going to restore the ipl below XXX nivas */
+       bsr.n   _setipl
+       or      r2,r0,0                      /* ints are enabled */
+                                            /* at ipl 0 now */
+      1:
+       ld      r2, FPTR, REG_OFF(EF_EPSR)   /* get pre-exception PSR */
+       bb1     PSR_SUPERVISOR_MODE_BIT, r2, no_ast /*skip if in system mode */
+
+       /* should assert here - not in user mode with ints off XXX nivas */
+       /* get and check want_ast */
+       or.u    r2, r0, hi16(_want_ast)
+       ld      r3, r2, lo16(_want_ast)
+       bcnd    eq0, r3, no_ast
+
+       /*
+        * trap(AST,...) will service ast's.
+        */
+
+        CALL(_trap, T_ASTFLT, FPTR)
+
+#if 0
+       /* assert that ipl is 0; if going back to user, it should be 0 */
+
+       bsr     _getipl
+       bcnd    eq0, r2, 2f
+       bsr     panic
+      2:
+#endif
+
+_LABEL(no_ast)
+
+       /* disable interrupts */
+
+       ldcr    r1, PSR                              
+       set     r1, r1, 1<PSR_INTERRUPT_DISABLE_BIT>
+        FLUSH_PIPELINE
+       stcr    r1, PSR
+
+        /* now ready to return....*/
+
+    /*
+     * Transfer the frame pointer to r31, since we no longer need a stack.
+     * No page faults here, and interrupts are disabled.
+     */
+
+       ld      r2, FPTR, REG_OFF(EF_MASK)   /* get pre-exception ipl */
+       bsr     _setipl
+
+        or     r31, r0,  FPTR
+       /* restore r1 later */
+       ld.d    r2 , r31, GENREG_OFF(2)
+       ld.d    r4 , r31, GENREG_OFF(4)
+       ld.d    r6 , r31, GENREG_OFF(6)
+       ld.d    r8 , r31, GENREG_OFF(8)
+       ld.d    r10, r31, GENREG_OFF(10)
+       ld.d    r12, r31, GENREG_OFF(12)
+       ld.d    r14, r31, GENREG_OFF(14)
+       ld.d    r16, r31, GENREG_OFF(16)
+       ld.d    r18, r31, GENREG_OFF(18)
+       ld.d    r20, r31, GENREG_OFF(20)
+       ld.d    r22, r31, GENREG_OFF(22)
+       ld.d    r24, r31, GENREG_OFF(24)
+       ld.d    r26, r31, GENREG_OFF(26)
+       ld.d    r28, r31, GENREG_OFF(28)
+       /* restore r1, r30, r31 later */
+
+       /* disable shadowing */
+       ldcr    r1, PSR
+       set     r1, r1, 1<PSR_SHADOW_FREEZE_BIT>
+       FLUSH_PIPELINE
+       stcr    r1, PSR
+
+       /* reload the control regs*/
+       st      r0,r31, REG_OFF(EF_IPFSR)
+       st      r0,r31, REG_OFF(EF_DPFSR)
+
+       /*
+        * Note: no need to restore the SXIP.
+        * When the "rte" causes execution to continue
+        * first with the instruction pointed to by the NIP
+        * and then the FIP.
+        *
+        * See MC88100 Risc Processor User's Manual, 2nd Edition,
+        * section 6.4.3.1.2-4
+        */
+       ld      r30, r31, REG_OFF(EF_SNIP)
+       ld      r1, r31, REG_OFF(EF_SFIP)
+       stcr    r0, SSBR
+       stcr    r30, SNIP
+       stcr    r1, SFIP
+
+       ld      r30, r31, REG_OFF(EF_EPSR)
+       ld      r1,  r31, REG_OFF(EF_MODE)
+       stcr    r30, EPSR
+
+       /* Now restore r1, r30, and r31 */
+       ld      r1,  r31, GENREG_OFF(1)
+       ld.d    r30, r31, GENREG_OFF(30)
+
+    _LABEL(return_from_exception)
+       RTE
diff --git a/sys/arch/mvme88k/mvme88k/genassym.c b/sys/arch/mvme88k/mvme88k/genassym.c
new file mode 100644 (file)
index 0000000..297b42b
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)genassym.c  7.8 (Berkeley) 5/7/91
+ *     $Id: genassym.c,v 1.3 1997/03/03 20:21:34 rahnds Exp $
+ */
+
+#ifndef KERNEL
+#define KERNEL
+#endif /* KERNEL */
+
+#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 <vm/vm.h>
+#include <sys/user.h>
+
+#define pair(TOKEN, ELEMENT) \
+    printf("#define " TOKEN " %u\n", (unsigned)(ELEMENT))
+
+#define int_offset_of_element(ELEMENT) (((unsigned)&(ELEMENT))/sizeof(int))
+
+main()
+{
+       register struct proc *p = (struct proc *)0;
+       struct m88100_saved_state *ss = (struct m88100_saved_state *) 0;
+       register struct vmmeter *vm = (struct vmmeter *)0;
+       register struct user *up = (struct user *)0;
+       register struct rusage *rup = (struct rusage *)0;
+       struct vmspace *vms = (struct vmspace *)0;
+       pmap_t pmap = (pmap_t)0;
+       struct pcb *pcb = (struct pcb *)0;
+       struct m88100_pcb *ks = (struct m88100_pcb *)0;
+
+       register unsigned i;
+
+       printf("#ifndef __GENASSYM_INCLUDED\n");
+       printf("#define __GENASSYM_INCLUDED 1\n\n");
+
+       printf("#define\tP_FORW %d\n", &p->p_forw);
+       printf("#define\tP_BACK %d\n", &p->p_back);
+       printf("#define\tP_VMSPACE %d\n", &p->p_vmspace);
+       printf("#define\tP_ADDR %d\n", &p->p_addr);
+       printf("#define\tP_PRIORITY %d\n", &p->p_priority);
+       printf("#define\tP_STAT %d\n", &p->p_stat);
+       printf("#define\tP_WCHAN %d\n", &p->p_wchan);
+       printf("#define\tSRUN %d\n", SRUN);
+       
+       printf("#define\tVM_PMAP %d\n", &vms->vm_pmap);
+       printf("#define\tV_INTR %d\n", &vm->v_intr);
+       
+       printf("#define\tUPAGES %d\n", UPAGES);
+       printf("#define\tPGSHIFT %d\n", PGSHIFT);
+       printf("#define\tUSIZE %d\n", USPACE);
+       printf("#define\tNBPG %d\n", NBPG);
+
+       printf("#define\tU_PROF %d\n", &up->u_stats.p_prof);
+       printf("#define\tU_PROFSCALE %d\n", &up->u_stats.p_prof.pr_scale);
+       printf("#define\tPCB_ONFAULT %d\n", &pcb->pcb_onfault);
+       printf("#define\tSIZEOF_PCB %d\n", sizeof(struct pcb));
+
+       printf("#define\tPCB_USER_STATE %d\n", &pcb->user_state);
+
+       printf("#define\tSYS_exit %d\n", SYS_exit);
+       printf("#define\tSYS_execve %d\n", SYS_execve);
+       printf("#define\tSYS_sigreturn %d\n", SYS_sigreturn);
+       
+       pair("EF_R0",   int_offset_of_element(ss->r[0]));
+       pair("EF_R31",  int_offset_of_element(ss->r[31]));
+       pair("EF_FPSR", int_offset_of_element(ss->fpsr));
+       pair("EF_FPCR", int_offset_of_element(ss->fpcr));
+       pair("EF_EPSR", int_offset_of_element(ss->epsr));
+       pair("EF_SXIP", int_offset_of_element(ss->sxip));
+       pair("EF_SFIP", int_offset_of_element(ss->sfip));
+       pair("EF_SNIP", int_offset_of_element(ss->snip));
+       pair("EF_SSBR", int_offset_of_element(ss->ssbr));
+       pair("EF_DMT0", int_offset_of_element(ss->dmt0));
+       pair("EF_DMD0", int_offset_of_element(ss->dmd0));
+       pair("EF_DMA0", int_offset_of_element(ss->dma0));
+       pair("EF_DMT1", int_offset_of_element(ss->dmt1));
+       pair("EF_DMD1", int_offset_of_element(ss->dmd1));
+       pair("EF_DMA1", int_offset_of_element(ss->dma1));
+       pair("EF_DMT2", int_offset_of_element(ss->dmt2));
+       pair("EF_DMD2", int_offset_of_element(ss->dmd2));
+       pair("EF_DMA2", int_offset_of_element(ss->dma2));
+       pair("EF_FPECR",        int_offset_of_element(ss->fpecr));
+       pair("EF_FPHS1",        int_offset_of_element(ss->fphs1));
+       pair("EF_FPLS1",        int_offset_of_element(ss->fpls1));
+       pair("EF_FPHS2",        int_offset_of_element(ss->fphs2));
+       pair("EF_FPLS2",        int_offset_of_element(ss->fpls2));
+       pair("EF_FPPT", int_offset_of_element(ss->fppt));
+       pair("EF_FPRH", int_offset_of_element(ss->fprh));
+       pair("EF_FPRL", int_offset_of_element(ss->fprl));
+       pair("EF_FPIT", int_offset_of_element(ss->fpit));
+       pair("EF_VECTOR",       int_offset_of_element(ss->vector));
+       pair("EF_MASK", int_offset_of_element(ss->mask));
+       pair("EF_MODE", int_offset_of_element(ss->mode));
+
+       pair("EF_RET",  int_offset_of_element(ss->scratch1));
+       pair("EF_IPFSR",int_offset_of_element(ss->ipfsr));
+       pair("EF_DPFSR",int_offset_of_element(ss->dpfsr));
+       pair("EF_NREGS",        sizeof(*ss)/sizeof(int));
+
+       /* make a sanity check */
+       if (sizeof(*ss) & 7)
+       {
+               /* 
+                * This contortion using write instead of fputs(stderr)
+                * is necessary because we can't include stdio.h in here.
+                */
+               static char buf[] = 
+         "Exception frame not a multiple of double words\n";
+               write(2 /* stderr */,buf,sizeof(buf));
+               exit(1);
+       }
+       pair("SIZEOF_EF", sizeof(*ss));
+
+       pair("PCB_PC", int_offset_of_element(ks->pcb_pc) * 4);
+       pair("PCB_IPL", int_offset_of_element(ks->pcb_ipl) * 4);
+       pair("PCB_R14", int_offset_of_element(ks->pcb_r14) * 4);
+       pair("PCB_R15", int_offset_of_element(ks->pcb_r15) * 4);
+       pair("PCB_R16", int_offset_of_element(ks->pcb_r16) * 4);
+       pair("PCB_R17", int_offset_of_element(ks->pcb_r17) * 4);
+       pair("PCB_R18", int_offset_of_element(ks->pcb_r18) * 4);
+       pair("PCB_R19", int_offset_of_element(ks->pcb_r19) * 4);
+       pair("PCB_R20", int_offset_of_element(ks->pcb_r20) * 4);
+       pair("PCB_R21", int_offset_of_element(ks->pcb_r21) * 4);
+       pair("PCB_R22", int_offset_of_element(ks->pcb_r22) * 4);
+       pair("PCB_R23", int_offset_of_element(ks->pcb_r23) * 4);
+       pair("PCB_R24", int_offset_of_element(ks->pcb_r24) * 4);
+       pair("PCB_R25", int_offset_of_element(ks->pcb_r25) * 4);
+       pair("PCB_R26", int_offset_of_element(ks->pcb_r26) * 4);
+       pair("PCB_R27", int_offset_of_element(ks->pcb_r27) * 4);
+       pair("PCB_R28", int_offset_of_element(ks->pcb_r28) * 4);
+       pair("PCB_R29", int_offset_of_element(ks->pcb_r29) * 4);
+       pair("PCB_R30", int_offset_of_element(ks->pcb_r30) * 4);
+       pair("PCB_SP",  int_offset_of_element(ks->pcb_sp) * 4);
+
+       printf("\n#endif /* __GENASSYM_INCLUDED */\n");
+       exit(0);
+}
diff --git a/sys/arch/mvme88k/mvme88k/locore.S b/sys/arch/mvme88k/mvme88k/locore.S
new file mode 100644 (file)
index 0000000..d247e39
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * 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.
+ */
+
+#ifndef ASSEMBLER
+#define ASSEMBLER
+#endif
+
+#include "machine/asm.h"
+#include "machine/m88100.h"
+#include "machine/trap.h"
+#include "machine/psl.h"
+#include "machine/vmparam.h"      /* INTSTACK_SIZE */
+
+/***********************************************************************/
+
+#ifndef UADDR
+#define        UADDR           0xEEE00000      /* address of u */
+#endif /* UADDR */
+
+/*
+ * The memory looks like:
+ *   0x00000 - 0x01000   : trap vectors
+ *   0x01000 - 0x10000  : first 64k used by BUG
+ *   0x10000 == start    : Boot loader jumps here. (for now, this can
+ *                                     handle only NMAGIC - screwy linker)
+ *
+ ***********************************************************************/
+       text
+
+LABEL(_kernelstart)
+LABEL(_start)
+LABEL(start)
+       br      _start_text
+#if 0
+       .align 4096               /* VBR points to page aligned list */
+    _LABEL(vector_list)          /* references memory BELOW this line */
+       #include "machine/exception_vectors.h"
+       word    END_OF_VECTOR_LIST
+
+    _LABEL(_msgsw)
+       word 0 /* Bits here turn on/off debugging somewhere. */
+#endif
+
+ENTRY(doboot)
+       /*
+        *      Try hitting the SRST bit in VMEchip2 to reset the system.
+        */
+       or.u    r3,r0, 0xfff4
+       ld      r4,r3, 0x0060           /* read offset (LCSR +0x60) */
+       set     r4,r4,1<23>             /* set SYSRST bit - bit 23 */   
+       st      r4,r3, 0x0060           /* and store it back  */
+
+       /*
+        *      We will be here if the reset above failed. In this case,
+        *      we will try to return to bug.
+        *
+        *      Switch to interrupt stack and call __doboot to take care
+        *      going to BUG. Need to do this since __doboot turns off the
+        *      the MMU and we need to be on a 1-to-1 mapped stack so that
+        *      further calls don't get data access exceptions.
+        */
+
+       /* Should we use idle_u instead? XXX nivas */
+       or.u    r31, r0,  hi16(_intstack_end)
+       or      r31, r31, lo16(_intstack_end)
+       clr     r31, r31, 3<0>  /* round down to 8-byte boundary */
+
+       bsr     __doboot
+       /*NOTREACHED*/
+
+/**************************************************************************/
+LABEL(_start_text)     /* This is the *real* start upon poweron or reset */
+#ifdef OLD_BOOT_LOADER
+       /*
+        * Args passed by boot loader
+        *      r2 howto
+        *      r3 first_addr (first available address)
+        *      r4 ((Clun << 8) ; Dlun & FF) -> bootdev
+        *      r5 esym
+        *      r6 miniroot
+        */
+       or.u    r13, r0,  hi16(_boothowto)
+       st      r2,  r13, lo16(_boothowto)
+       or.u    r13, r0,  hi16(_first_addr)
+       st      r3,  r13, lo16(_first_addr)
+#if 0
+       or.u    r13, r0,  hi16(_bootdev)
+       st      r4,  r13, lo16(_bootdev)
+#endif
+       or.u    r13, r0,  hi16(_esym)
+       st      r5,  r13, lo16(_esym)
+       or.u    r13, r0,  hi16(_miniroot)
+       st      r6,  r13, lo16(_miniroot)
+#else /* OLD_BOOT_LOADER */
+       /*
+        * Args passed by boot loader
+        *      r2 howto
+        *      r3 not used
+        *      r4 esym
+        *      r5 start of mini
+        *      r6 end miniroot
+        */
+       or.u    r13, r0,  hi16(_boothowto)
+       st      r2,  r13, lo16(_boothowto)
+#if 0
+       or.u    r13, r0,  hi16(_bootdev)
+       st      r3,  r13, lo16(_bootdev)
+#endif
+       or.u    r13, r0,  hi16(_first_addr)
+       st      r4,  r13, lo16(_first_addr)
+       or.u    r13, r0,  hi16(_esym)
+       st      r4,  r13, lo16(_esym)
+       or.u    r13, r0,  hi16(_miniroot)
+       st      r5,  r13, lo16(_miniroot)
+#endif /* OLD_BOOT_LOADER */
+       /*
+        * CPU Initialization
+        *
+        * Every CPU starts from here..
+        * (well, from 'start' above, which just jumps here).
+        *
+        * I use r11 and r22 here 'cause they're easy to not
+        * get mixed up -- r10, for example, looks too similar
+        * to r0 when not being careful....
+        *
+        * Ensure that the PSR is as we like:
+        *      supervisor mode
+        *      big-endian byte ordering
+        *      concurrent operation allowed
+        *      carry bit clear (I don't think we really care about this)
+        *      FPU enabled
+        *      misaligned access raises an exception
+        *      interrupts disabled
+        *      shadow registers frozen
+        *
+        * The manual says not to disable interrupts and freeze shadowing
+        * at the same time because interupts are not actually disabled
+        * until after the next instruction. Well, if an interrupt
+        * occurs now, we're in deep   anyway, so I'm going to do
+        * the two together.
+        *
+        * Upon a reset (or poweron, I guess), the PSR indicates:
+        *   supervisor mode
+        *   interrupts, shadowing, FPU, missaligned exception: all disabled
+        *
+        * We'll just construct our own turning on what we want.
+        *
+        *      jfriedl@omron.co.jp
+        */
+       stcr    r0, SSBR        /* clear this for later */
+
+       set     r11, r0,  1<PSR_SUPERVISOR_MODE_BIT>
+       set     r11, r11, 1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r11, PSR
+        FLUSH_PIPELINE
+       /* shadowing, FPU, misalgined access exception: all enabled now.*/
+#if 0
+       or.u    r11, r0,  hi16(_vector_list)
+       or      r11, r11, lo16(_vector_list)
+       stcr    r11, VBR
+#endif /* 0 */
+       stcr    r0, VBR
+
+       /*
+        * Switch to interrupt stack
+        * Use idle_u's stack instead?
+        */
+       or.u    r31, r0,  hi16(_intstack_end)
+       or      r31, r31, lo16(_intstack_end)
+       clr     r31, r31, 3<0>  /* round down to 8-byte boundary */
+
+       /*
+        * Want to make the call:
+        *      vector_init(VBR, vector_list)
+        */
+       or.u    r3, r0, hi16(_vector_list)
+       or      r3, r3, lo16(_vector_list)
+       bsr.n   _vector_init
+       ldcr    r2, VBR         
+       
+#if 0
+       /* clear BSS. Boot loader might have already done this... */
+       or.u    r2, r0, hi16(_edata)
+       or      r2, r2, lo16(_edata)
+       or.u    r4, r0, hi16(_end)
+       or      r4, r4, lo16(_end)
+       bsr.n   _bzero          /* bzero(edata, end-edata) */
+       subu    r3, r4, r2
+#endif
+
+       /* still on int stack */
+       bsr.n   _m187_bootstrap
+       subu    r31, r31, 40
+       addu    r31, r31, 40
+       
+       /* switch to proc0 uarea */
+       
+       or.u    r10, r0, hi16(UADDR)
+       or      r31, r10,lo16(UADDR)
+       addu    r31, r31, USIZE - 8
+
+       /*
+        * Block clock interrupts for now. There is a problem with
+        * clock interrupts when the first clock interrupt is received.
+        * Hardclock() sees the base priority to be 0 and drops IPL to
+        * splsofclock() before calling softclock(). This opens up other
+        * clock interrupts to be received before the first one is ever
+        * finished. Also, the first entry on calltodo list is stuck for
+        * ever. As a work around, I will set the IPL to softclock so
+        * that the CLKF_BASEPRI() check in hardclock() will return false.
+        * XXX nivas
+        */
+        
+#if XXXX
+       bsr.n   _setipl
+       or      r2, r0, IPL_SOFTCLOCK
+       bsr     _enable_interrupt
+       bsr.n   _setipl
+       or      r2, r0, IPL_HIGH
+#endif
+       /* make the call: main() */
+       bsr.n   _main
+       subu    r31, r31, 40
+       addu    r31, r31, 40
+       bsr     _panic
+
+/*****************************************************************************/
+
+       data
+       .align 4096               /* VBR points to page aligned list */
+       global _vector_list
+_vector_list:                    /* references memory BELOW this line */
+#include "machine/exception_vectors.h"
+       word    END_OF_VECTOR_LIST
+
+       global _msgsw
+_msgsw:
+       word 0                   /* Bits here turn on/off debugging somewhere */
+       .align 4096
+       global  _intstack
+       global  _intstack_end
+_intstack:
+       space   4 * NBPG        /* 16K */
+_intstack_end:
+
+/*
+ * When a process exits and its u. area goes away, we set curpcb to point
+ * to this `u.', leaving us with something to use for an interrupt stack,
+ * and letting all the register save code have a pcb_uw to examine.
+ * This is also carefully arranged (to come just before u0, so that
+ * process 0's kernel stack can quietly overrun into it during bootup, if
+ * we feel like doing that).
+ * Should be page aligned.
+ */
+       global  _idle_u
+_idle_u:
+       space   UPAGES * NBPG
+
+/*
+ * Process 0's u.
+ *
+ * This must be page aligned
+ */
+       global  _u0
+       align   4096
+_u0:   space   UPAGES * NBPG
+estack0:
+
+/*
+ * UPAGES get mapped to kstack
+ */
+
+       global  _kstack
+_kstack:
+       word    UADDR
+
+#ifdef DDB
+       global  _esym
+_esym:
+       word    0
+#endif /* DDB */
+
+       global  _proc0paddr     /* move to C code */
+_proc0paddr:
+       word    _u0             /*  KVA of proc0 uarea */
+
+/*
+ * _curpcb points to the current pcb (and hence u. area).
+ * Initially this is the special one.
+ */
+/*
+ * pcb is composed of kernel state + user state
+ * I may have to change curpcb to u0 + PCB_USER based on what
+ * other parts expect XXX nivas
+ */
+       global  _curpcb /* move to C code */
+_curpcb:       word    _u0     /* curpcb = &u0 */
+
+/*
+ * Trampoline code. Gets copied to the top of
+ * user stack in exec.
+ */
+       global  _sigcode
+_sigcode:
+                               /* r31 points to sigframe */
+       ld      r2, r31, 0      /* signo */
+       ld      r3, r31, 4      /* siginfo_t* */
+       ld      r4, r31, 8      /* sigcontext* */
+       ld      r5, r31, 12     /* handler */
+       jsr.n   r5
+       subu    r31, r31, 40    /* give some stack space */
+       addu    r31, r31, 40    /* restore old sp value  */
+       ld      r2,  r31, 8     /* sigcontext* */
+       or      r13,  r0, SYS_sigreturn
+       tb0     0, r0, 128      /* syscall trap, calling sigreturn */
+       or      r0, r0, 0
+       or      r0, r0, 0
+       /* sigreturn will not return unless it fails */
+       or      r13, r0, SYS_exit
+       tb0     0, r0, 128      /* syscall trap, exit */
+       or      r0, r0, 0
+       or      r0, r0, 0
+       global  _esigcode
+_esigcode:
diff --git a/sys/arch/mvme88k/mvme88k/locore_asm_routines.S b/sys/arch/mvme88k/mvme88k/locore_asm_routines.S
new file mode 100644 (file)
index 0000000..5735e79
--- /dev/null
@@ -0,0 +1,1736 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1992 Carnegie Mellon University
+ * Copyright (c) 1991 OMRON Corporation
+ * Copyright (c) 1996 Nivas Madhur
+ * 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.
+ */
+/* locore_asm_routines.c 
+ *
+ **********************************************************************
+ * This file created by Omron Corporation, 1990.
+ *
+ * HISTORY
+ *
+ **************************************************************RCS*****/
+
+#ifndef ASSEMBLER
+# define ASSEMBLER
+#endif
+
+#include <machine/trap.h>
+#include <machine/board.h>
+#include <machine/asm.h>
+#include <sys/errno.h>
+
+
+/*****************************************************************************
+ * DO_LOAD_ADDRESS
+ *
+ *     unsigned int do_load_word(address, supervisor_mode)
+ *     vm_offset_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
+#if  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
+#if  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
+#if  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
+#if  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
+#if  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
+#if  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
+#if  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
+#if  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
+
+/*************************************************************************
+ *************************************************************************
+ **
+ **    void enable_interrupt(void)
+ **
+ **    Enables processor interrupts (for the executing cpu).
+ **/
+#undef enable_interrupt
+ENTRY(enable_interrupt)
+       ldcr    r2, PSR
+       clr     r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r2, PSR
+        FLUSH_PIPELINE
+       jmp     r1
+
+#if DDB
+/* a version of enable_interrupt for the debugger; should never
+   have breakpoints set it in. Keep it consistent with enable
+   interrupt above */
+ENTRY(db_enable_interrupt)
+       ldcr    r2, PSR
+       clr     r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r2, PSR
+        FLUSH_PIPELINE
+       jmp     r1
+#endif /* DDB */
+
+/*************************************************************************
+ *************************************************************************
+ **
+ ** unsigned long disable_interrupt(void)
+ **
+ ** Disables processor interrupts (for the executing CPU) and returns
+ ** the *previous* PSR.
+ **
+ **     if ((oldPSR & 0x02) == 0)
+ **            interrupts_were_previously_on = 1;
+ **/
+#undef disable_interrupt
+ENTRY(disable_interrupt)
+       ldcr    r2, PSR
+       set     r3, r2, 1<PSR_INTERRUPT_DISABLE_BIT>     /* set disable bit*/
+       stcr    r3, PSR
+        FLUSH_PIPELINE
+       jmp     r1
+
+/* a version of disable_interrupt for the kernel debugger. Should never
+   have breakpoints set in it. Make sure it stays consistent with 
+   disable_interrupt */
+
+#if DDB
+ENTRY(db_disable_interrupt)
+       ldcr    r2, PSR
+       set     r3, r2, 1<PSR_INTERRUPT_DISABLE_BIT>     /* set disable bit*/
+       stcr    r3, PSR
+        FLUSH_PIPELINE
+       jmp     r1
+#endif /* DDB */
+
+/* version for the debugger */
+
+#if DDB
+
+ENTRY(db_are_interrupts_disabled)
+     ldcr      r2, PSR                   /* get the processor status word */
+     set       r3, r0, 1<PSR_INTERRUPT_DISABLE_BIT>   /* set mask */
+     jmp.n     r1                                     /* delayed return */
+     and       r2, r2, r3                            /* r2 = r3 & r2 */
+#endif /* DDB */
+
+LABEL(_FAULT_ERROR)
+       or      r2,r0,1         /* bad copy */
+       jmp     r1
+
+/* LABEL(_ALLOW_FAULT_START) */
+
+/*
+ * Fetch from user space
+ * r2 == address in user space
+ */
+
+ENTRY(fuword)
+ENTRY(fuiword)
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(fusu_fault)
+       or              r5,   r5,   lo16(fusu_fault)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = fusu_fault */
+#if  ERRATA__XXX_USR
+       NOP
+       ld.usr          r5,   r0,  r2
+       NOP
+       NOP
+       NOP
+#else
+       ld.usr          r5,   r0,  r2
+#endif
+       or              r2,   r0,  r5
+       br              fusu_ret
+fusu_fault:
+       subu            r2,   r0,  1    
+fusu_ret:
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       st              r0,   r6,   PCB_ONFAULT /* pcb_onfault = 0 */
+
+       jmp             r1
+               
+ENTRY(fusword)
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(fusu_fault)
+       or              r5,   r5,   lo16(fusu_fault)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = fusu_fault */
+#if  ERRATA__XXX_USR
+       NOP
+       ld.h.usr        r5,   r0,  r2
+       NOP
+       NOP
+       NOP
+#else
+       ld.h.usr        r5,   r0,  r2
+#endif
+       or              r2,   r0,  r5
+       br              fusu_ret
+       
+ENTRY(fubyte)
+ENTRY(fuibyte)
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(fusu_fault)
+       or              r5,   r5,   lo16(fusu_fault)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = fusu_fault */
+#if  ERRATA__XXX_USR
+       NOP
+       ld.b.usr        r5,   r0,  r2
+       NOP
+       NOP
+       NOP
+#else
+       ld.b.usr        r5,   r0,  r2
+#endif
+       or              r2,   r0,  r5
+       br              fusu_ret
+
+ENTRY(fuswintr)
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(_fubail)
+       or              r5,   r5,   lo16(_fubail)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = fubail */
+#if  ERRATA__XXX_USR
+       NOP
+       ld.h.usr        r5,   r2, r0
+       NOP
+       NOP
+       NOP
+#else
+       ld.h.usr        r5,   r2, r0
+#endif
+       or              r2,   r0, r5
+       br              fusu_ret
+
+ENTRY(fubail)
+       subu            r2,   r0, 1
+       br              fusu_ret
+
+/*
+ * store to user space.
+ * r2 == address in user space
+ * r3 == byte/short/word
+ */
+
+ENTRY(suword)
+ENTRY(suiword)
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(fusu_fault)
+       or              r5,   r5,   lo16(fusu_fault)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = fusu_fault */
+#if  ERRATA__XXX_USR
+       NOP
+       st.usr          r3,   r2, r0
+       NOP
+       NOP
+       NOP
+#else
+       st.usr          r3,   r2, r0
+#endif
+       or              r2,   r0, r0            /* return success */
+       br              fusu_ret
+
+ENTRY(susword)
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(fusu_fault)
+       or              r5,   r5,   lo16(fusu_fault)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = fusu_fault */
+#if  ERRATA__XXX_USR
+       NOP
+       st.h.usr        r3,   r2, r0
+       NOP
+       NOP
+       NOP
+#else
+       st.h.usr        r3,   r2, r0
+#endif
+       or              r2,   r0, r0            /* return success */
+       br              fusu_ret
+
+ENTRY(subyte)
+ENTRY(suibyte)
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(fusu_fault)
+       or              r5,   r5,   lo16(fusu_fault)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = fusu_fault */
+#if  ERRATA__XXX_USR
+       NOP
+       st.b.usr        r3,   r2, r0
+       NOP
+       NOP
+       NOP
+#else
+       st.b.usr        r3,   r2, r0
+#endif
+       or              r2,   r0, r0            /* return success */
+       br              fusu_ret
+
+ENTRY(suswintr)
+       or.u            r5,   r0,   hi16(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(_subail)
+       or              r5,   r5,   lo16(_subail)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = subail */
+#if  ERRATA__XXX_USR
+       NOP
+       st.h.usr        r3,   r2, r0
+       NOP
+       NOP
+       NOP
+#else
+       st.h.usr        r3,   r2, r0
+#endif
+       or              r2,   r0, r0            /* return success */
+       br              fusu_ret
+
+ENTRY(subail)
+       subu            r2,   r0, 1
+       br              fusu_ret
+
+#if 0
+/*
+ * copystr(fromaddr, toaddr, maxlength, &lencopied)
+ *
+ * Copy a null terminated string from one point to another in
+ * the kernel address space.
+ */
+ENTRY(copystr)
+       or      r6,r0,0
+       bcnd    lt0,r4,Lcsflt1          /* negative count, error */
+       bcnd    eq0,r4,Lcsdone          /* zero count, all done */
+Lcsloop:
+       ld      r8,r2,r6                /* copy a byte */
+       st      r8,r3,r6                
+       addu    r6,r6,1                 /* bump the index */
+       bcnd    eq0,r8,Lcsdone          /* if null, done */
+       subu    r4,r4,1                 /* decrement count to copy */
+       bcnd    ne0,r4,Lcsloop          /* if more to copy, loop */
+       br      Lcsflt2                 /* ran out of room, error */
+Lcsdone:
+       bcnd    eq0, r5, Lcsret         /* if return len not desired, return */
+       st      r6,r5,0                 /* stash it */
+Lcsret:
+       or      r2,r0,0                 /* good status */
+       jmp     r1
+Lcsflt1:
+       or      r2,r0,EFAULT            /* return fault */
+       br      Lcsdone
+Lcsflt2:
+       or      r2,r0,ENAMETOOLONG      /* ran out of space */
+       br      Lcsdone 
+Lcsdone:
+       jmp     r1
+#endif /* 0 */
+/*
+ * 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(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(.Lciflt)
+       or              r5,   r5,   lo16(.Lciflt)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = .Lciflt */
+       
+       /*bcnd          ne0,  LEN,  1f ; XXX optimize len = 0 case */
+       /*;or           r2,   r0,   0 */
+       /*;br           .Lcidone */
+    /*;1: ;bcnd                lt0,  LEN,  .Lciflt ; EFAULT if len < 0  */
+        
+       /* If it's a small length (less than 8), then do byte-by-byte */
+       cmp             r9,   LEN,  8
+       bb1             lt,   r9,   copyin_byte_only
+
+       /* If they're not aligned similiarly, use byte only... */
+       xor             r9,   SRC,  DEST
+       mask            r8,   r9,   0x3
+       bcnd            ne0,  r8,   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,  copyin_left_align_to_halfword
+copyin_left_aligned_to_halfword:
+       bb1             1,    SRC,  copyin_left_align_to_word
+copyin_left_aligned_to_word:
+       bb1             0,    LEN,  copyin_right_align_to_halfword
+copyin_right_aligned_to_halfword:
+       bb1             1,    LEN,  copyin_right_align_to_word
+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,  copyin_right_align_to_doubleword
+       or              r7,   r0,   4
+
+copyin_right_aligned_to_doubleword:
+#if  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,  copyin_right_aligned_to_doubleword
+       addu            DEST, DEST, 8
+       or              r2, r0, r0      /* successful return */
+       br              .Lcidone
+
+        /***************************************************/
+
+copyin_left_align_to_halfword:
+#if  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            copyin_left_aligned_to_halfword
+       addu            DEST, DEST, 1
+
+copyin_left_align_to_word:
+#if  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            copyin_left_aligned_to_word
+       addu            DEST, DEST, 2
+
+copyin_right_align_to_halfword:
+       subu            LEN,  LEN,  1
+#if  ERRATA__XXX_USR
+       NOP
+       ld.b.usr        r5,   SRC,  LEN
+       NOP
+       NOP
+       NOP
+#else
+       ld.b.usr        r5,   SRC,  LEN
+#endif
+       br.n            copyin_right_aligned_to_halfword
+       st.b            r5,   DEST, LEN
+
+copyin_right_align_to_word:
+       subu            LEN,  LEN,  2
+#if  ERRATA__XXX_USR
+       NOP
+       ld.h.usr        r5,   SRC,  LEN
+       NOP
+       NOP
+       NOP
+#else
+       ld.h.usr        r5,   SRC,  LEN
+#endif
+       br.n            copyin_right_aligned_to_word
+       st.h            r5,   DEST, LEN
+
+copyin_right_align_to_doubleword:
+       subu            LEN,  LEN,  4
+#if  ERRATA__XXX_USR
+       NOP
+       ld.usr          r5,   SRC,  LEN
+       NOP
+       NOP
+       NOP
+#else
+       ld.usr          r5,   SRC,  LEN
+#endif
+       bcnd.n          ne0,  LEN, copyin_right_aligned_to_doubleword
+       st              r5,   DEST, LEN
+       or              r2, r0, r0      /* successful return */
+       br              .Lcidone
+
+copyin_byte_only:
+       bcnd            eq0, LEN, 2f
+   1:
+       subu            LEN, LEN, 1
+#if  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:  or              r2, r0, r0      /* successful return */
+       br              .Lcidone
+.Lcidone:
+       or.u            r5,r0,hi16(_curpcb)
+       ld              r6,r5,lo16(_curpcb)
+       st              r0,r6,PCB_ONFAULT
+       jmp             r1
+.Lciflt:
+       or              r2, r0, EFAULT  /* return fault */
+       br              .Lcidone
+
+#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(_curpcb)       
+       ld              r7,   r6,   lo16(_curpcb)
+       or.u            r6,   r0,   hi16(.Lcisflt)
+       or              r6,   r6,   lo16(.Lcisflt)
+       st              r6,   r7,   PCB_ONFAULT
+       bcnd            lt0,  CNT,   .Lcisflt
+       bcnd            eq0,  CNT,   .Lcisdone
+       or              r6,   r0,   0
+   1:  
+#if  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
+       or              r2,   r0, ENAMETOOLONG  /* over flow */
+       br              .Lcisdone
+   2:                                          /* all done */
+       or              r2,   r0, 0
+       br              .Lcisdone
+
+.Lcisdone:
+        bcnd           eq0, LEN, 3f            
+       st              r6, r0, LEN
+   3:  or.u            r5,r0,hi16(_curpcb)
+       ld              r6,r5,lo16(_curpcb)
+       st              r0,r6,PCB_ONFAULT       /* clear the handler */
+       jmp             r1
+.Lcisflt:
+       or              r2, r0, EFAULT  /* return fault */
+       br              .Lcisdone
+
+#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(_curpcb)       
+       ld              r6,   r5,   lo16(_curpcb)
+       or.u            r5,   r0,   hi16(.Lcoflt)
+       or              r5,   r5,   lo16(.Lcoflt)
+       st              r5,   r6,   PCB_ONFAULT /* pcb_onfault = .Lcoflt */
+/*     ;bcnd           ne0,  LEN,  1f ; XXX optimize len = 0 case */
+/*     ;or             r2,   r0,   0 */
+/*     ;br             .Lcodone */
+    /*;1: ;bcnd                lt0,  LEN,  .Lcoflt ; EFAULT if len < 0  */
+       /* If it's a small length (less than 8), then do byte-by-byte */
+       cmp             r9,   LEN,  8
+       bb1             lt,   r9,   copyout_byte_only
+
+       /* If they're not aligned similiarly, use byte only... */
+       xor             r9,   SRC,  DEST
+       mask            r8,   r9,   0x3
+       bcnd            ne0,  r8,   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,  copyout_left_align_to_halfword
+copyout_left_aligned_to_halfword:
+       bb1             1,    SRC,  copyout_left_align_to_word
+copyout_left_aligned_to_word:
+       bb1             0,    LEN,  copyout_right_align_to_halfword
+copyout_right_aligned_to_halfword:
+       bb1             1,    LEN,  copyout_right_align_to_word
+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,  copyout_right_align_to_doubleword
+       or              r7,   r0,   4
+
+copyout_right_aligned_to_doubleword:
+       ld              r5,   SRC,  r0
+       ld              r6,   SRC,  r7
+       subu            LEN,  LEN,  8
+#if  ERRATA__XXX_USR
+       NOP
+       st.usr          r5,   DEST, r0
+       NOP
+       NOP
+       NOP
+#else
+       st.usr          r5,   DEST, r0
+#endif
+       addu            SRC,  SRC,  8
+#if  ERRATA__XXX_USR
+       NOP
+       st.usr          r6,   DEST, r7
+       NOP
+       NOP
+       NOP
+#else
+       st.usr          r6,   DEST, r7
+#endif
+       bcnd.n          ne0,  LEN,  copyout_right_aligned_to_doubleword
+       addu            DEST, DEST, 8
+       or              r2, r0, r0      /* successful return */
+       br              .Lcodone
+
+       /***************************************************/
+copyout_left_align_to_halfword:
+       ld.b            r5,   SRC,  r0
+       subu            LEN,  LEN,  1
+#if  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            copyout_left_aligned_to_halfword
+       addu            DEST, DEST, 1
+
+copyout_left_align_to_word:
+       ld.h            r5,   SRC,  r0
+       subu            LEN,  LEN,  2
+#if  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            copyout_left_aligned_to_word
+       addu            DEST, DEST, 2
+
+copyout_right_align_to_halfword:
+       subu            LEN,  LEN,  1
+       ld.b            r5,   SRC,  LEN
+#if  ERRATA__XXX_USR
+       NOP
+       st.b.usr        r5,   DEST, LEN
+       NOP
+       NOP
+       NOP
+       br              copyout_right_aligned_to_halfword
+#else
+       br.n            copyout_right_aligned_to_halfword
+       st.b.usr        r5,   DEST, LEN
+#endif
+
+copyout_right_align_to_word:
+       subu            LEN,  LEN,  2
+       ld.h            r5,   SRC,  LEN
+#if  ERRATA__XXX_USR
+       NOP
+       st.h.usr        r5,   DEST, LEN
+       NOP
+       NOP
+       NOP
+       br              copyout_right_aligned_to_word
+#else
+       br.n            copyout_right_aligned_to_word
+       st.h.usr        r5,   DEST, LEN
+#endif
+
+copyout_right_align_to_doubleword:
+       subu            LEN,  LEN,  4
+       ld              r5,   SRC,  LEN
+#if  ERRATA__XXX_USR
+       NOP
+       st.usr          r5,   DEST, LEN
+       NOP
+       NOP
+       NOP
+       bcnd            ne0,  LEN, copyout_right_aligned_to_doubleword
+#else
+       bcnd.n          ne0,  LEN, copyout_right_aligned_to_doubleword
+       st.usr          r5,   DEST, LEN
+#endif
+       or              r2, r0, r0      /* successful return */
+       br              .Lcodone
+
+_LABEL(copyout_byte_only)
+       bcnd            eq0, LEN, 2f
+   1:
+       subu            LEN, LEN, 1
+       ld.b            r5, SRC, LEN
+#if  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:  or              r2, r0, r0      /* successful return */
+       br              .Lcodone
+
+.Lcodone:
+       or.u            r5,r0,hi16(_curpcb)
+       ld              r6,r5,lo16(_curpcb)
+       st              r0,r6,PCB_ONFAULT       /* clear the handler */
+       jmp             r1
+.Lcoflt:
+       or              r2, r0, EFAULT  /* return fault */
+       br              .Lcodone
+
+#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(_curpcb)       
+       ld              r7,   r6,   lo16(_curpcb)
+       or.u            r6,   r0,   hi16(.Lcosflt)
+       or              r6,   r6,   lo16(.Lcosflt)
+       st              r6,   r7,   PCB_ONFAULT
+       bcnd            lt0,  CNT,   .Lcosflt
+       bcnd            eq0,  CNT,   .Lcosdone
+       or              r6,   r0,   0
+   1:  
+       ld.bu           r7,   SRC,  r6
+#if  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
+       or              r2,   r0, ENAMETOOLONG  /* over flow */
+       br              .Lcosdone
+   2:                                          /* all done */
+       or              r2,   r0, 0
+       br              .Lcosdone
+
+.Lcosflt:
+       or              r2, r0, EFAULT  /* return fault */
+       br              .Lcosdone
+
+.Lcosdone:
+        bcnd           eq0, LEN, 3f            
+       st              r6, r0, LEN
+   3:  or.u            r5,r0,hi16(_curpcb)
+       ld              r6,r5,lo16(_curpcb)
+       st              r0,r6,PCB_ONFAULT       /* clear the handler */
+       jmp             r1
+
+#undef SRC
+#undef DEST
+#undef CNT
+#undef LEN
+
+/*######################################################################*/
+/*LABEL(_ALLOW_FAULT_END)*/
+/*word 0       */ /* to separate from routine below */
+/*######################################################################*/
+
+/*
+ * 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    _ovbcopy      /* call 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,bcopy_out /* nothing to do if count <= 0 */
+/*
+ *     check position of source and destination data
+ */
+       cmp     r9,r2,r3        /* compare source address to destination */
+       bb1     eq,r9,bcopy_out /* nothing to do if addresses are equal */      
+       bb1     lo,r9,bcopy_reverse /* copy in reverse if src < destination */
+/*
+ *     source address is greater than destination address, copy forward 
+ */
+       cmp     r9,r4,16        /* see if we have at least 16 bytes */
+       bb1     lt,r9,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(f_strat) /* forward strategy table address (high) */
+       or      r12,r12,lo16(f_strat) /* forward strategy table address (low) */
+       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
+ */
+_LABEL(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    f_word_copy     /* copy full words */
+       subu    r4,r4,3         /* decrement length */
+
+/*
+ * Copy 1 halfword from src to destination then copy words
+ */
+_LABEL(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    f_word_copy     /* copy full words */
+       subu    r4,r4,2         /* decrement remaining length */
+
+/* 
+ * Copy 1 byte from src to destination then copy words
+ */
+_LABEL(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
+ */    
+_LABEL(f_word_copy)
+       cmp     r10,r4,16       /* see if we have 16 bytes remaining */ 
+       bb1     lo,r10,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    f_word_copy     /* branch to copy another block */
+       subu    r4,r4,16        /* decrement remaining length */
+       
+_LABEL(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 */
+
+_LABEL(f_half_copy)
+       cmp     r10,r4,16       /* see if we have 16 bytes remaining */ 
+       bb1     lo,r10,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    f_half_copy     /* branch to copy another block */
+       subu    r4,r4,16        /* decrement remaining length */
+       
+_LABEL(f_byte_copy)
+       bcnd    eq0,r4,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    f_byte_copy     /* branch for next byte */ 
+       subu    r4,r4,1         /* decrement remaining length */
+
+/*
+ *     source address is less than destination address, copy in reverse
+ */
+_LABEL(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,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(r_strat) /* reverse strategy table address (high) */
+       or      r12,r12,lo16(r_strat) /* reverse strategy table address (low) */
+       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
+ */
+_LABEL(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    r_word_copy     /* copy full words */
+       subu    r4,r4,3         /* decrement length */
+
+/*
+ * Copy 1 halfword from src to destination then copy words
+ */
+_LABEL(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    r_word_copy     /* copy full words */
+       subu    r4,r4,2         /* decrement remaining length */
+
+/* 
+ * Copy 1 byte from src to destination then copy words
+ */
+_LABEL(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
+ */    
+_LABEL(r_word_copy)
+       cmp     r10,r4,16       /* see if we have 16 bytes remaining */ 
+       bb1     lo,r10,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    r_word_copy     /* branch to copy another block */
+       subu    r4,r4,16        /* decrement remaining length */
+       
+_LABEL(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 */
+
+_LABEL(r_half_copy)
+       cmp     r10,r4,16       /* see if we have 16 bytes remaining */ 
+       bb1     lo,r10,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    r_half_copy     /* branch to copy another block */
+       subu    r4,r4,16        /* decrement remaining length */
+       
+_LABEL(r_byte_copy)
+       bcnd    eq0,r4,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    r_byte_copy     /* branch for next byte */ 
+       subu    r4,r4,1         /* decrement remaining length */
+
+_LABEL(bcopy_out)
+       jmp     r1              /* all done, return to caller */
+       
+       data
+       align   4
+_LABEL(f_strat)
+       word    f_word_copy
+       word    f_byte_copy
+       word    f_half_copy
+       word    f_byte_copy
+       word    f_byte_copy
+       word    f_3byte_word_copy
+       word    f_byte_copy
+       word    f_1byte_half_copy
+       word    f_half_copy
+       word    f_byte_copy
+       word    f_1half_word_copy
+       word    f_byte_copy
+       word    f_byte_copy
+       word    f_1byte_half_copy
+       word    f_byte_copy
+       word    f_1byte_word_copy
+
+_LABEL(r_strat)
+       word    r_word_copy
+       word    r_byte_copy
+       word    r_half_copy
+       word    r_byte_copy
+       word    r_byte_copy
+       word    r_1byte_word_copy
+       word    r_byte_copy
+       word    r_1byte_half_copy
+       word    r_half_copy
+       word    r_byte_copy
+       word    r_1half_word_copy
+       word    r_byte_copy
+       word    r_byte_copy
+       word    r_1byte_half_copy
+       word    r_byte_copy
+       word    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(blkclr)
+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, not_initially_word_aligned
+       bb1     1, R_dest, not_initially_word_aligned
+
+   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(mark)
+       or      R_mark_address, R_mark_address, lo16(mark)
+       
+   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, 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
+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 */
+
+   mark:
+       br.n    top_of_main_loop
+       addu    R_dest, R_dest, R_bytes /* bump up the dest address */
+
+
+
+   done_doing_words:
+       bcnd    ne0, R_len, finish_up_last_bytes
+       jmp     r1              /* RETURN */
+
+   finish_up_last_bytes:
+       subu    R_len, R_len, 1
+       bcnd.n  ne0, R_len, finish_up_last_bytes
+       st.b    r0, R_dest, R_len
+
+   leave:
+       jmp     r1              /* RETURN */
+       
+   not_initially_word_aligned:
+       /*
+        * Bzero to word-align the address (at least if the length allows it).
+        */
+       bcnd    eq0, R_len, leave
+       st.b    r0, R_dest, 0
+       addu    R_dest, R_dest, 1
+       mask    R_temp, R_dest, 0x3
+       bcnd.n  eq0, R_temp, now_word_aligned
+       subu    R_len, R_len, 1
+       br      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*);
+ */
+       global _setjmp
+_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
+
+       global  _longjmp
+_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(longjmp_int_enable)
+       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
+       or      r2,r3,r0
+       ldcr    r10,PSR
+       clr     r10,r10,1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r10,PSR
+       jmp     r1
+
+ENTRY(getsp)
+       or      r2, r0, r31
+       jmp     r1
+
+/*
+ * This has to be cleaned - we should not use INT_MASK_LEVEL. Should
+ * use pcc2_int_lvl instead. XXX nivas
+ */
+/*
+ * I don't think we need to explictly enable interrupts. We can always enable
+ * interrupts and depend on the int level and mask in PCC2 to block the
+ * appropriate interrupts for us. If we don't depend on the PCC2 to block ints
+ * for us, we need to explicitly set the IND bit in the PSR for every spln(x)
+ * when x > 0. But for now... Rewrite the whole mess. XXX nivas
+ * This is bogus - it is blocking interrupts for all but 0 XXX nivas
+ */
+
+ENTRY(spln)
+       ldcr    r10,PSR
+       or      r11,r0,r10
+       or      r5,r2,r0
+       bb1     PSR_INTERRUPT_DISABLE_BIT,r10,1f
+       set     r10,r10,1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r10,PSR
+        FLUSH_PIPELINE
+    1:
+       or.u    r3,r0,hi16(INT_MASK_LEVEL)
+       or      r3,r3,lo16(INT_MASK_LEVEL)
+       xmem.bu r2,r3,r0
+       bcnd    ne0, r5, 2f
+       clr     r11, r11, 1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r11,PSR
+        FLUSH_PIPELINE
+    2:
+       jmp     r1
+
+ENTRY(getipl)
+ENTRY(spl)
+       ldcr    r10,PSR
+       or      r11,r0,r10
+       bb1     PSR_INTERRUPT_DISABLE_BIT, r10, 1f
+       set     r10,r10,1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r10,PSR
+        FLUSH_PIPELINE
+      1:
+       or.u    r3,r0,hi16(INT_MASK_LEVEL)
+       ld.b    r2,r3,lo16(INT_MASK_LEVEL)
+       stcr    r11,PSR
+        FLUSH_PIPELINE
+       jmp     r1
+
+/*
+ *     Set the interrupt mask to the value passed in, returning the
+ *     the current mask level. This routine does not enable/disable
+ *     interrupts explicitly. It is assumed that the callers know what
+ *     to do with interrupts.
+ */
+ENTRY(setipl)
+       ldcr    r10,PSR
+       or      r11,r0,r10
+       bb1     PSR_INTERRUPT_DISABLE_BIT, r10, 1f
+       set     r10,r10,1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r10,PSR                         /* disable ints, if needed */
+        FLUSH_PIPELINE
+     1:
+       /* get the current mask value */
+       or.u    r3,r0,hi16(INT_MASK_LEVEL)
+       or      r3,r3,lo16(INT_MASK_LEVEL)
+       xmem.bu r2,r3,r0                        /* xchng the new mask value */
+        FLUSH_PIPELINE
+       stcr    r11,PSR                         /* restore psr */
+        FLUSH_PIPELINE
+       jmp     r1                              /* and return the old value */
+
+/*
+ *       invalidate_pte(pte)
+ *
+ *       This function will invalidate specified pte indivisibly
+ *       to avoid the write-back of used-bit and/or modify-bit into
+ *       that pte.  It also returns the pte found in the table.
+ */
+ENTRY(invalidate_pte)
+        or      r3,r0,r0
+        xmem    r3,r2,r0
+       tb1     0,r0,0
+        jmp.n   r1
+        or      r2,r3,r0
+
+#if DDB
+
+ENTRY(db_spln)
+       ldcr    r10,PSR
+       or      r11,r0,r10
+       or      r5,r2,r0
+       bb1     PSR_INTERRUPT_DISABLE_BIT,r10,1f
+       set     r10,r10,1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r10,PSR
+        FLUSH_PIPELINE
+    1:
+       or.u    r3,r0,hi16(INT_MASK_LEVEL)
+       or      r3,r3,lo16(INT_MASK_LEVEL)
+       xmem.bu r2,r3,r0
+       bcnd    ne0, r5, 2f
+       clr     r11, r11, 1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r11,PSR
+        FLUSH_PIPELINE
+    2:
+       jmp     r1
+
+ENTRY(db_setipl)
+       ldcr    r10,PSR
+       or      r11,r0,r10
+       bb1     PSR_INTERRUPT_DISABLE_BIT, r10, 1f
+       set     r10,r10,1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r10,PSR                         /* disable ints, if needed */
+        FLUSH_PIPELINE
+     1:
+       /* get the current mask value */
+       or.u    r3,r0,hi16(INT_MASK_LEVEL)
+       or      r3,r3,lo16(INT_MASK_LEVEL)
+       xmem.bu r2,r3,r0                        /* xchng the new mask value */
+        FLUSH_PIPELINE
+       stcr    r11,PSR                         /* restore psr */
+        FLUSH_PIPELINE
+       jmp     r1                              /* and return the old value */
+
+ENTRY(db_getipl)
+ENTRY(db_spl)
+       ldcr    r10,PSR
+       or      r11,r0,r10
+       bb1     PSR_INTERRUPT_DISABLE_BIT, r10, 1f
+       set     r10,r10,1<PSR_INTERRUPT_DISABLE_BIT>
+       stcr    r10,PSR
+      1:
+       or.u    r3,r0,hi16(INT_MASK_LEVEL)
+       ld.b    r2,r3,lo16(INT_MASK_LEVEL)
+       stcr    r11,PSR
+        FLUSH_PIPELINE
+       jmp     r1
+
+ENTRY(db_flush_pipeline)
+        FLUSH_PIPELINE
+       jmp     r1
+#endif /* DDB */       
+
+ENTRY(read_processor_identification_register)
+       jmp.n   r1
+       ldcr    r2, PID
+
+ENTRY(safe_byte_access)
+       ld.b     r9,r0,r2
+       tb1      0,r0,0
+       br       @L1
+       or      r0,r0,r0
+@L1:
+       st.b     r9,r0,r3
+       jmp     r1
+
+ENTRY(guarded_access)
+ENTRY(guarded_access_start)
+       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       _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
+
+ENTRY(guarded_access_bad)
+       jmp.n    r1
+       or       r2,r0,14
+@L142:
+
+ENTRY(guarded_access_end)
+       jmp.n    r1
+       or       r2,r0,0
diff --git a/sys/arch/mvme88k/mvme88k/locore_c_routines.c b/sys/arch/mvme88k/mvme88k/locore_c_routines.c
new file mode 100644 (file)
index 0000000..483dcb1
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ */
+/*
+ * HISTORY
+ *****************************************************************RCS**/
+/* This file created by Omron Corporation, 1990. */
+
+#include <machine/m88100.h>            /* DMT_VALID            */
+#include <assym.s>                      /* EF_NREGS, etc.      */
+#include <machine/locore.h>             /* END_OF_VECTOR_LIST, etc. */
+#ifdef DDB
+  #include <ddb/db_output.h>            /* db_printf()         */
+#endif /* DDB */
+
+
+#if defined(DDB) && defined(JEFF_DEBUG)
+# define DATA_DEBUG  1
+#endif
+
+
+#if DDB
+#  define DEBUG_MSG db_printf
+#else
+#  define DEBUG_MSG printf
+#endif /* DDB */
+
+/*
+ *  data access emulation for M88100 exceptions
+ */
+#define DMT_BYTE       1
+#define DMT_HALF       2
+#define DMT_WORD       4
+
+static struct
+{
+    unsigned char      offset;
+    unsigned char      size;
+} dmt_en_info[16] =
+{
+    {0, 0}, {3, DMT_BYTE}, {2, DMT_BYTE}, {2, DMT_HALF},
+    {1, DMT_BYTE}, {0, 0}, {0, 0}, {0, 0},
+    {0, DMT_BYTE}, {0, 0}, {0, 0}, {0, 0},
+    {0, DMT_HALF}, {0, 0}, {0, 0}, {0, DMT_WORD}
+};
+
+#if DATA_DEBUG
+   int data_access_emulation_debug = 0;
+   static char *bytes[] =
+   {
+           "____", "___x", "__x_", "__xx",
+           "_x__", "_x_x", "_xx_", "_xxx",
+           "x___", "x__x", "x_x_", "x_xx",
+           "xx__", "xx_x", "xxx_", "xxxx",
+   };
+  #define DAE_DEBUG(stuff) {                                           \
+       if ((data_access_emulation_debug != 0) && (                     \
+           data_access_emulation_debug == 0xffffffff)) { stuff ;}   }
+#else
+  #define DAE_DEBUG(stuff)
+#endif
+
+void data_access_emulation(unsigned *eframe)
+{
+    register int x;
+    register struct dmt_reg *dmtx;
+    register unsigned  dmax, dmdx;
+    register unsigned  v, reg;
+
+    if (!(eframe[EF_DMT0] & DMT_VALID))
+       return;
+
+    for (x = 0; x < 3; x++)
+    {
+       dmtx = (struct dmt_reg *)&eframe[EF_DMT0+x*3];
+
+       if (!dmtx->dmt_valid)
+               continue;
+
+       dmdx = eframe[EF_DMD0+x*3];
+       dmax = eframe[EF_DMA0+x*3];
+
+       DAE_DEBUG
+       (
+         if (dmtx->dmt_write)
+           DEBUG_MSG("[DMT%d=%x: st.%c %x to %x as [%s] %s %s]\n",
+             x, eframe[EF_DMT0+x*3], dmtx->dmt_das ? 's' : 'u',
+             dmdx, dmax, bytes[dmtx->dmt_en], 
+             dmtx->dmt_doub1 ? "double": "not double",
+             dmtx->dmt_lockbar ? "xmem": "not xmem");
+         else
+           DEBUG_MSG("[DMT%d=%x: ld.%c r%d<-%x as [%s] %s %s]\n",
+             x, eframe[EF_DMT0+x*3], dmtx->dmt_das ? 's' : 'u',
+             dmtx->dmt_dreg, dmax, bytes[dmtx->dmt_en], 
+             dmtx->dmt_doub1 ? "double": "not double",
+             dmtx->dmt_lockbar ? "xmem": "not xmem");
+       )
+
+       dmax += dmt_en_info[dmtx->dmt_en].offset;
+       reg = dmtx->dmt_dreg;
+
+       if ( ! dmtx->dmt_lockbar)
+       {
+           /* the fault is not during an XMEM */
+
+           if (x == 2 && dmtx->dmt_doub1)
+           {
+               /* pipeline 2 (earliest stage) for a double */
+
+               if (dmtx->dmt_write)
+               {
+                   /* STORE DOUBLE WILL BE RE-INITIATED BY rte */
+               }
+               else
+               {
+                   /* EMULATE ld.d INSTRUCTION */
+                       v = do_load_word(dmax, dmtx->dmt_das);
+                       if (reg != 0)
+                           eframe[EF_R0 + reg] = v;
+                       v = do_load_word(dmax ^ 4, dmtx->dmt_das);
+                       if (reg != 31)
+                           eframe[EF_R0 + reg + 1] = v;
+               }
+           }
+           else         /* not pipeline #2 with a double */
+           {
+               if (dmtx->dmt_write) switch (dmt_en_info[dmtx->dmt_en].size)
+               {
+                 case DMT_BYTE:
+                   DAE_DEBUG(DEBUG_MSG("[byte %x -> [%x(%c)]\n",
+                       dmdx & 0xff, dmax, dmtx->dmt_das ? 's' : 'u'))
+                   do_store_byte(dmax, dmdx, dmtx->dmt_das);
+                   break;
+                 case DMT_HALF:
+                   DAE_DEBUG(DEBUG_MSG("[half %x -> [%x(%c)]\n",
+                       dmdx & 0xffff, dmax, dmtx->dmt_das ? 's' : 'u'))
+                   do_store_half(dmax, dmdx, dmtx->dmt_das);
+                   break;
+                 case DMT_WORD:
+                   DAE_DEBUG(DEBUG_MSG("[word %x -> [%x(%c)]\n",
+                       dmdx, dmax, dmtx->dmt_das ? 's' : 'u'))
+                   do_store_word(dmax, dmdx, dmtx->dmt_das);
+                   break;
+               }
+               else    /* else it's a read */
+               {
+                   switch (dmt_en_info[dmtx->dmt_en].size)
+                   {
+                     case DMT_BYTE:
+                       v = do_load_byte(dmax, dmtx->dmt_das);
+                       if (!dmtx->dmt_signed)
+                           v &= 0x000000ff;
+                       break;
+                     case DMT_HALF:
+                       v = do_load_half(dmax, dmtx->dmt_das);
+                       if (!dmtx->dmt_signed)
+                           v &= 0x0000ffff;
+                       break;
+                     case DMT_WORD:
+                     default: /* 'default' just to shut up lint */
+                       v = do_load_word(dmax, dmtx->dmt_das);
+                       break;
+                   }
+                   if (reg == 0) {
+                       DAE_DEBUG(DEBUG_MSG("[no write to r0 done]\n"));
+                   }
+                   else
+                   {
+                       DAE_DEBUG(DEBUG_MSG("[r%d <- %x]\n",
+                               reg, v));
+                       eframe[EF_R0 + reg] = v;
+                   }
+               }
+           }
+       }
+       else /* if lockbar is set... it's part of an XMEM */
+       {
+           /*
+            * According to Motorola's "General Information",
+            * the dmt_doub1 bit is never set in this case, as it should be.
+            * They call this "general information" - I call it a f*cking bug!
+            *
+            * Anyway, if lockbar is set (as it is if we're here) and if
+            * the write is not set, then it's the same as if doub1
+            * was set...
+            */
+           if ( ! dmtx->dmt_write)
+           {
+               if (x != 2)
+               {
+                   /* RERUN xmem WITH DMD(x+1) */
+                   x++;
+                   dmdx = eframe[EF_DMD0 + x*3];
+               }
+               else
+               {
+                   /* RERUN xmem WITH DMD2 */
+               }
+
+               if (dmt_en_info[dmtx->dmt_en].size == DMT_WORD)
+                   v = do_xmem_word(dmax, dmdx, dmtx->dmt_das);
+               else
+                   v = do_xmem_byte(dmax, dmdx, dmtx->dmt_das);
+               eframe[EF_R0 + reg] = v;
+           }
+           else
+           {
+               if (x == 0)
+               {
+                   eframe[EF_R0 + reg] = dmdx;
+                   eframe[EF_SFIP] = eframe[EF_SNIP];
+                   eframe[EF_SNIP] = eframe[EF_SXIP];
+                   eframe[EF_SXIP] = 0;
+                   /* xmem RERUN ON rte */
+                   eframe[EF_DMT0] = 0;
+                   return;
+               }
+           }
+       }
+    }
+    eframe[EF_DMT0] = 0;
+}
+
+/*
+ ***********************************************************************
+ ***********************************************************************
+ */
+#define SIGSYS_MAX      501
+#define SIGTRAP_MAX     511
+
+#define EMPTY_BR       0xC0000000U      /* empty "br" instruction */
+#define NO_OP          0xf4005800U      /* "or r0, r0, r0" */
+
+typedef struct
+{
+       unsigned word_one,
+                word_two;
+} m88k_exception_vector_area;
+
+#define BRANCH(FROM, TO) (EMPTY_BR | ((unsigned)(TO) - (unsigned)(FROM)) >> 2)
+
+#define SET_VECTOR(NUM, to, VALUE) {                                       \
+       unsigned _NUM = (unsigned)(NUM);                                   \
+       unsigned _VALUE = (unsigned)(VALUE);                               \
+       vector[_NUM].word_one = NO_OP;                                     \
+       vector[_NUM].word_two = BRANCH(&vector[_NUM].word_two, _VALUE);    \
+}
+
+/*
+ * vector_init(vector, vector_init_list)
+ *
+ * This routine sets up the m88k vector table for the running processor.
+ * It is called with a very little stack, and interrupts disabled,
+ * so don't call any other functions!
+ *     XXX clean this - nivas
+ */
+void vector_init(
+       m88k_exception_vector_area *vector,
+       unsigned *vector_init_list)
+{
+    register unsigned num;
+    register unsigned vec;
+    extern void sigsys(), sigtrap(), stepbpt(), userbpt();
+    extern void syscall_handler();
+
+    for (num = 0; (vec = vector_init_list[num]) != END_OF_VECTOR_LIST; num++)
+    {
+       if (vec != PREDEFINED_BY_ROM)
+           SET_VECTOR(num, to, vec);
+    }
+
+    while (num < 496)
+       SET_VECTOR(num++, to, sigsys);
+    num++; /* skip 496, BUG ROM vector */
+
+    SET_VECTOR(450, to, syscall_handler);
+#if 0
+    while (num <= SIGSYS_MAX)
+       SET_VECTOR(num++, to, sigsys);
+
+    while (num <= SIGTRAP_MAX)
+       SET_VECTOR(num++, to, sigtrap);
+
+    SET_VECTOR(504, to, stepbpt);
+    SET_VECTOR(511, to, userbpt);
+    vector[496].word_one = 496 * 4;
+    vector[497].word_two = 497 * 4;
+#endif
+}
diff --git a/sys/arch/mvme88k/mvme88k/m88100_fp.S b/sys/arch/mvme88k/mvme88k/m88100_fp.S
new file mode 100644 (file)
index 0000000..8cbdddd
--- /dev/null
@@ -0,0 +1,2303 @@
+/*
+ * 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 */
+
+#define LOCORE
+
+#define ASSEMBLER
+
+#include <machine/trap.h>
+#include <machine/asm.h>
+
+#define psr cr1
+#define spsr cr2
+#define ssb cr3
+#define scip cr4
+#define snip cr5
+#define sfip cr6
+#define vbr cr7        
+#define dmt0 cr8       
+#define scratch1 cr18
+#define scratch2 cr20
+#define fpecr fcr0
+#define s1hi fcr1
+#define s1lo fcr2
+#define s2hi fcr3
+#define s2lo fcr4
+#define pcr fcr5
+#define manthi fcr6
+#define mantlo fcr7
+#define impcr fcr8
+#define fpsr fcr62
+#define fpcr fcr63
+#define valid 1
+#define exception 0
+#define exc_disable 0
+#define FP_disable 3
+#define dexc 27
+#define serial 29
+#define destsize 10
+#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 full 1
+#define fault 0
+#define FADDop 0x05
+#define FSUBop 0x06
+#define FCMPop 0x07
+#define FMULop 0x00
+#define FDIVop 0x0e
+#define FSQRTop 0x0f
+#define FLTop 0x04
+#define INTop 0x09
+#define NINTop 0x0a
+#define TRNCop 0x0b
+#define mode 31
+#define s1sign 9
+#define s2sign 8
+#define s1nan 7
+#define s2nan 6
+#define s1inf 5
+#define s2inf 4
+#define s1zero 3
+#define s2zero 2
+#define s1denorm 1
+#define s2denorm 0
+#define sigbit 19
+#define sigbits 22
+#define sigbitd 19
+#define nc 0
+#define cp 1
+#define eq 2
+#define ne 3
+#define gt 4
+#define le 5
+#define lt 6
+#define ge 7
+#define ou 8
+#define ib 9
+#define in 10
+#define ob 11
+
+#define modehi 30
+#define modelo 29
+#define rndhi 15
+#define rndlo 14
+#define efunf 7
+#define efovf 6
+#define efinx 5
+
+#define MARK   or      r21, r0, __LINE__
+       
+       text
+       align 8
+       global _Xfp_precise
+_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)
+2:     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: /*  bb0     5,r4, 5f        ;branch to FPpriviol if bit set */
+   /*  br      _FPpriviol */
+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
+
+FPuimp: global FPuimp
+fp_p_trap:
+       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     _trap           /* trap */
+       ld      r1,r31,36       /* recover return address */
+       addu    r31,r31,40      /* deallocate stack */
+       br      fp_p_return
+
+       /* 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 */
+       
+wrapup: global wrapup
+       tb1     0,r0,0          /* make sure all floating point operations */
+       /* have finished */
+       ldcr    r10, cr1        /* load the PSR */
+       or      r10, r10, 0x2   /* disable interrupts */
+       stcr    r10, cr1
+#if 0
+Why is this done? -jfriedl
+       or      r10, r10, 0x8 /* set SFU 1 disable bit, disable SFU 1 */
+       stcr    r10, cr1
+#endif
+       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 */
+writesingle: 
+       st     r6, r3 [r2]       /* write low word into memory */
+
+fp_p_return:
+       jmp     r1
+
+             text
+            align 8
+             global _FPdivzero
+
+
+/* Check if the numerator is zero.  If the numerator is zero, then handle */
+/* this instruction as you would a 0/0 invalid operation. */
+
+_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. */
+
+resoper:     
+             set   r2,r2,1<oper>    /* set bit in FPSR */
+#ifdef HANDLER
+            bb0   oper,r3,noreshand /* branch to execute default handling for */
+                                    /* reserved operands */
+             bsr   _handler         /* branch to user handler */
+             br    FP_div_return           /* return from function */
+#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            /* return from subroutine */
+                                   /* 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:
+#ifdef HANDLER
+             set   r2,r2,1<divzero> /* set bit in FPSR */
+             bb0   divzero,r3,default /* go to default routine if no handler */
+             bsr   _handler         /* execute handler routine */
+             br    FP_div_return           /* return from subroutine */
+#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           /* return from subroutine */
+             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               /* return from subroutine */
+
+       
+       
+/* 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. */
+       text
+       align 8
+_FPintover:  global _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                  /* jump into branch table */
+       
+ptable:      br     conversiondp
+p00001:      br     conversiondp
+p00010:      br     conversiondp
+p00011:      br     paddone
+p00100:      br     conversiondp
+p00101:      br     conversiondp
+p00110:      br     paddone
+p00111:      br     paddone
+p01000:      br     conversiondp
+p01001:      br     conversiondp
+p01010:      br     conversiondp
+p01011:      br     conversiondp
+p01100:      br     conversiondp
+p01101:      br     conversiondp
+p01110:      br     conversiondp
+p01111:      br     conversiondp
+p10000:      br     conversiondp
+p10001:      br     conversiondp
+p10010:      br     conversiondp
+p10011:      br     conversiondp
+p10100:      br     conversiondp
+p10101:      br     conversiondp
+p10110:      br     conversiondp
+p10111:      br     conversiondp
+p11000:      br     conversiondp
+p11001:      br     paddone
+p11010:      br     paddone
+p11011:      br     paddone
+p11100:      br     conversiondp
+p11101:      br     paddone
+p11110:      br     paddone
+p11111:      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 from subroutine. */
+       
+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 overflow */
+       extu   r10,r7,20<0>         /* check upper bits of upper mantissa */
+       bcnd   ne0,r10,overflw      /* one of the bits is a 1, so overflow */
+       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>        /* rounding mode is either round zero or */
+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               /* return from subroutine */
+       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               /* return from subroutine */
+       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               /* return from subroutine */
+       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               /* return from subroutine */
+       addu  r6,r6,1              /* add 1 to get 2''s complement */
+exp31s:      or    r6,r0,r0             /* clear r6 */
+       br.n  FPintov_return               /* return from subroutine */
+       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               /* return from subroutine */
+       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                 /* jump into branch table */
+       
+ntable:      br     nnoaddone
+n00001:      br     nnoaddone
+n00010:      br     nnoaddone
+n00011:      br     naddone
+n00100:      br     nnoaddone
+n00101:      br     nnoaddone
+n00110:      br     naddone
+n00111:      br     naddone
+n01000:      br     nnoaddone
+n01001:      br     nnoaddone
+n01010:      br     nnoaddone
+n01011:      br     nnoaddone
+n01100:      br     nnoaddone
+n01101:      br     nnoaddone
+n01110:      br     nnoaddone
+n01111:      br     nnoaddone
+n10000:      br     nnoaddone
+n10001:      br     naddone
+n10010:      br     naddone
+n10011:      br     naddone
+n10100:      br     nnoaddone
+n10101:      br     naddone
+n10110:      br     naddone
+n10111:      br     naddone
+n11000:      br     nnoaddone
+n11001:      br     nnoaddone
+n11010:      br     nnoaddone
+n11011:      br     nnoaddone
+n11100:      br     nnoaddone
+n11101:      br     nnoaddone
+n11110:      br     nnoaddone
+n11111:      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              /* return from subroutine */
+       addu   r6,r6,1             /* add 1 to get 2''s complement */
+       
+maxneg:      or     r6,r0,r0            /* clear integer */
+       br.n   FPintov_return              /* return from subroutine */
+       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:  
+#ifdef HANDLER
+       bb0.n  oper,r3,nohandler   /* do not go to user handler routine */
+       set    r2,r2,1<oper>       /* set invalid operand bit */
+       bsr    _handler            /* go to user handler routine */
+       br     FPintov_return              /* return from subroutine */
+nohandler:   
+#endif
+       bb0.n  sign,r7,FPintov_return      /* if positive then return from subroutine */
+       set    r6,r6,31<0>         /* set result to largest positive integer */
+       or.c   r6,r0,r6            /* negate r6,giving largest negative int. */
+       
+FPintov_return:      ld     r1,r31,0     /* load return address from memory */
+       jmp    r1                  /* return from subroutine */
+       
+       data
+
+/* 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. */
+
+             text
+LABEL(_FPresoper)
+            st     r1, r31, 0
+            extu   r10,r9,5<11>   /* extract opcode */
+/*             cmp    r11,r10,FSQRTop ;compare to FSQRT */
+/*             bb1    eq,r11,S1clear ;clear S1 if instruction only had S2 operand */
+             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 */
+
+_LABEL(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. */
+
+             
+_LABEL(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 */
+_LABEL(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 (internal 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''s */
+             bcnd   eq0,r11,noS1NaNs /* since r11 can only hold 0 or a positive */
+                                   /* 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 */
+_LABEL(noS1NaNs)
+            br.n   S2NaN          /* check contents of S2 */
+             set    r12,r0,1<s1inf> /* indicate that S1 has an infinity */
+
+_LABEL(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 positive */
+                                   /* 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 */
+_LABEL(noS1NaNd)
+            set    r12,r0,1<s1inf> /* indicate that S1 has an infinity */
+
+_LABEL(S2NaN)
+            bb1.n  s2size,r9,S2NaNdoub /* S1 is double precision */
+             extu   r10,r7,11<20>        /* internal representation for double */
+_LABEL(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 (internal 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 positive */
+                                   /* number, branch to noS2NaNs when eq0 */
+             br.n   _NaN           /* branch to NaN routine */
+             set    r12,r12,1<s2nan> /* indicate that s2 has a NaN */
+_LABEL(noS2NaNs)
+            bb0    s1nan,r12, 1f /* branch to NaN if S1 is a NaN */
+            br     _NaN
+1:           br.n   _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 */
+
+_LABEL(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 positive */
+                                   /* number, branch to noS2NaNd when eq0 */
+             br.n   _NaN           /* branch to NaN routine */
+             set    r12,r12,1<s2nan> /* indicate that s2 has a NaN */
+_LABEL(noS2NaNd)
+            bb0    s1nan,r12,1f /* branch to NaN if S1 is a NaN */
+            br     _NaN
+1:           br.n   _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. */
+
+_LABEL(inf)
+            bb0    s1nan,r12,1f  /* branch if S1 has a NaN and S2 does not */
+            br     _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 */
+/*
+ * The above "bb0 s1inf, r12,2f" had been a "bb1", but it just didn't make
+ * sense (and didn't work, either), so I changed it.
+ *     jfriedl Dec 1, 1989.
+ */
+            br     _infinity
+2:
+
+       br     _denorm        /* branch to denorm, the only remaining */
+                                   /* alternative */
+
+/* function _FPunderflow --       */
+/* The documentation for this release give an overall description of this code. */
+
+                text
+                global _FPunderflow
+
+/* 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. */
+
+_FPunderflow:   st    r1,r31,0 /* save return address */
+#ifdef HANDLER
+               bb0 efunf,r12,denorm /* jump to default procedure */
+                bb1.n destsize,r12,doubleprec /* double precision destination */
+                set   r2,r2,1<underflow>  /* set underflow flag in FPSR */
+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       /* return from subroutine */
+#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 */
+
+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
+r000001:        br    noaddone
+r000010:        br    noaddone
+r000011:        br    noaddone
+r000100:        br    noaddone
+r000101:        br    addone
+r000110:        br    addone
+r000111:        br    addone
+r001000:        br    noaddone
+r001001:        br    noaddone
+r001010:        br    noaddone
+r001011:        br    noaddone
+r001100:        br    addone
+r001101:        br    addone
+r001110:        br    addone
+r001111:        br    addone
+r010000:        br    noaddone
+r010001:        br    noaddone
+r010010:        br    noaddone
+r010011:        br    noaddone
+r010100:        br    noaddone
+r010101:        br    noaddone
+r010110:        br    noaddone
+r010111:        br    noaddone
+r011000:        br    noaddone
+r011001:        br    noaddone
+r011010:        br    noaddone
+r011011:        br    noaddone
+r011100:        br    noaddone
+r011101:        br    noaddone
+r011110:        br    noaddone
+r011111:        br    noaddone
+r100000:        br    noaddone
+r100001:        br    noaddone
+r100010:        br    noaddone
+r100011:        br    noaddone
+r100100:        br    noaddone
+r100101:        br    noaddone
+r100110:        br    noaddone
+r100111:        br    noaddone
+r101000:        br    noaddone
+r101001:        br    addone
+r101010:        br    addone
+r101011:        br    addone
+r101100:        br    addone
+r101101:        br    addone
+r101110:        br    addone
+r101111:        br    addone
+r110000:        br    noaddone
+r110001:        br    addone
+r110010:        br    addone
+r110011:        br    addone
+r110100:        br    addone
+r110101:        br    addone
+r110110:        br    addone
+r110111:        br    addone
+r111000:        br    noaddone
+r111001:        br    noaddone
+r111010:        br    noaddone
+r111011:        br    noaddone
+r111100:        br    noaddone
+r111101:        br    noaddone
+r111110:        br    noaddone
+r111111:        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:       
+#ifdef HANDLER
+               bb1.n efinx,r12,modformdef /* branch to modify form for user  */
+                                             /* handler */
+                or    r2,r2,5      /* set inexact and underflow flags */
+#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       /* return from subroutine */
+
+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       /* return from subroutine */
+                
+
+/* 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         /* return from subroutine */
+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           /* return from subroutine */
+  
+                data
+
+/* function _FPoverflow --       */
+/* The documentation for this release gives an overall description of this code. */
+data
+align 4
+msg2: string "here at line %d, r1 is %x\n\0"
+text
+
+#line 23
+
+/* 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. */
+              text                             
+             align 8
+              global _FPoverflow
+_FPoverflow:  
+             st     r1,r31,0 /* save return address */
+#ifdef HANDLER
+              set    r2,r2,1<overflow> /* set overflow bit in r2 which holds FPSR */
+              bb1    efovf,r12,hand  /* go to user handler if bit set for overflow */
+              set    r2,r2,1<inexact> /* set inexact bit in r2 since overflow bit */
+                                /* in FPCR is not set */
+              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     /* return from overflow subroutine */
+#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 */
+/* postive 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         /* return from subroutine */
+
+              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
+LABEL(_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>  /* set invalid operation bit in FPSR */
+#ifdef JEFF_DEBUGxxxxxxx
+               /*
+                * Generate a signal to the offending process.
+                * This uses hardcoded constants from mach/exception.h
+                * and mach/machine/exception.h.
+                */
+               ldcr     r2, cr17       /* first arg: current_thread() */
+               or       r3,  r0, 3     /* second arg: EXC_ARITHMETIC  */
+               or       r4,  r0, 3     /* third arg: EXC_M88K_FLOAT_P */
+               or       r5,  r0, r0
+               subu    r31, r31, 48
+               bsr.n    _thread_doexception
+               st       r1, r31, 44
+               ld       r1, r31, 44
+               br.n    FPnan_return
+               addu    r31, r31, 48
+#endif
+#ifdef HANDLER
+               bb0     oper,r3,S1nohandler /* branch if no user handler */
+               bsr     _handler       /* branch to handler */
+               br      FPnan_return
+_LABEL(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 */
+
+_LABEL(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>  /* set invalid operation bit in FPSR */
+#ifdef HANDLER
+               bb0     oper,r3,S2nohandler     /* branch if no user handler */
+               bsr     _handler       /* branch to handler */
+               br      FPnan_return
+#endif
+
+_LABEL(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. */
+
+_LABEL(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            /* return from subroutine */
+             set    r6,r6,1<ne>       /* set the not equal bit */
+_LABEL(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 */
+_LABEL(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            /* return from function */
+             or     r6,r6,r10         /* form result */
+
+_LABEL(wrdoubS1)
+/* ;;;;;            bb1    s1size,r9,wrdoubS1d ;write double source to double dest. */
+/* took out the above instruction -- don't see why it's there.... jfriedl */
+_LABEL(wrdoubS1s)
+            set    r6,r6,29<0>       /* set extra bits of lower word */
+_LABEL(wrdoubS1d)
+            br     FPnan_return      /* no modification necessary for writing */
+                                      /* double to double, so return from function */
+
+_LABEL(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            /* return from subroutine */
+             set    r6,r6,1<ne>       /* set the not equal bit */
+_LABEL(S2noFCMP)
+            bb1.n  dsize,r9,wrdoubS2 /* double destination */
+       /*
+        * In the original, the ".n" above and the "set r5..." below
+        * were omitted here.  Since they're in the S1 stuff above,
+        * and since this isn't working right now (r5 isn't being set
+        * to it's part of the nan), I'll try this...
+        *      jfriedl Dec 1, 1989
+        */
+             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 */
+_LABEL(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            /* return from function */
+             or     r6,r6,r10         /* form result */
+
+_LABEL(wrdoubS2)
+       
+/* ;;;      bb1  s2size,r9,FPnan_return  ;write double source to double dest. */
+       /*
+        * I took out the above branch because I just don't see how it
+        * makes sense. jfriedl Dec 1, '89
+        */
+_LABEL(wrdoubS2s)
+            set    r6,r8,29<0>       /* set extra bits of lower word */
+
+
+/* Return from this subroutine with the result. */
+
+_LABEL(FPnan_return)
+            /* no modification necessary for writing */
+                                      /* double to double, so return from function */
+             ld     r1,r31,     0   /* retrieve return address */
+             jmp    r1                /* return from function */
+
+             data
+
+/* function _infinity --       */
+/* See the documentation of this release for an overall description of this */
+/* code. */
+
+
+/* Extract the opcode, compare to a constant, and branch to the code */
+/* for the instruction. */
+
+             text
+            align 8
+             global _infinity
+_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 */
+/*              cmp    r11,r10,FSQRTop;compare to FSQRT */
+/*              bb1    eq,r11,FSQRT   ;operation is FSQRT */
+             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               /* return from subroutine */
+             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               /* return from subroutine */
+             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  _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 from subroutine if s2 is neg. */
+FCMPS1piS2pf: set   r4,r4,1<ou>        /* set ou bit */
+             br.n   move             /* return from subroutine */
+             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             /* return from subroutine */
+             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             /* return from subroutine */
+             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  _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 from subroutine if s2 is neg. */
+             set    r4,r4,1<ou>        /* set ou bit */
+             br.n   move             /* return from subroutine */
+             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  _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             /* return from subroutine */
+             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  _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          /* return from subroutine */
+             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    _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 */
+
+/* FSQRT:       bb0    sign,r7,poswrinf    ;write sqrt(inf) = inf */
+/*              br     excpt               ;write sqrt(-inf) = NaN */
+
+excpt:       
+             set    r2,r2,1<oper>      /* set invalid operation bit of FPSR */
+#ifdef HANDLER
+            bb0    oper,r3,nohandler  /* branch if no user handler */
+             bsr    _handler           /* branch to interface with user handler */
+             br     inf_return             /* return from function */
+nohandler:   
+#endif
+            set    r5,r0,0<0>        /* write NaN into r5 */
+             br.n   inf_return             /* return from subroutine */
+             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             /* return from subroutine */
+             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             /* return from subroutine */
+             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             /* return from subroutine */
+             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             /* return from subroutine */
+             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             /* return from subroutine */
+             set    r6,r6,1<31>        /* set sign bit */
+negwrzerod:  or     r5,r0,r0           /* clear high word */
+             br.n   inf_return             /* return from subroutine */
+             set    r5,r5,1<31>        /* set sign bit */
+             
+FP_inf_overflw:     
+             set    r2,r2,1<oper>       /* set invalid operand bit */
+#ifdef HANDLER
+            bb0    oper,r3,nohandlero  /* do not go to user handler routine */
+             bsr    _handler            /* go to user handler routine */
+             br     inf_return              /* return from subroutine */
+#endif
+
+nohandlero:  bb0.n  sign,r7,inf_return      /* if positive then return from subroutine */
+             
+             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                 /* return from subroutine */
+
+             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
+/* function _denorm --       */
+/* See the documentation for this release for an overall description of this */
+/* code. */
+       
+
+/* 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. */
+
+             text
+            align 8
+             global _denorm
+_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 */
+/*              cmp    r11,r10,0x0f;compare to FSQRT */
+/*              bb1    2,r11,FSQRT   ;operation is FSQRT */
+             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      /* return from subroutine */
+              fadd.sss r6,r6,r8   /* add the two sources and place result 10 S1 */
+FADDsDsS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fadd.sds r6,r5,r8   /* add the two sources and place result 10 S1 */
+FADDsDdS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fadd.dss r5,r6,r8   /* add the two sources and place result 10 S1 */
+FADDdDsS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fadd.dds r5,r5,r8   /* add the two sources and place result 10 S1 */
+FADDdDdS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fsub.sss r6,r6,r8   /* add the two sources and place result 10 S1 */
+FSUBsDsS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fsub.sds r6,r5,r8   /* add the two sources and place result 10 S1 */
+FSUBsDdS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fsub.dss r5,r6,r8   /* add the two sources and place result 10 S1 */
+FSUBdDsS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fsub.dds r5,r5,r8   /* add the two sources and place result 10 S1 */
+FSUBdDdS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+             fcmp.sss r6,r6,r8   /* add the two sources and place result 10 S1 */
+FCMPsS1dS2:  br.n  return      /* return from subroutine */
+             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      /* return from subroutine */
+             fcmp.sds r6,r5,r8   /* add the two sources and place result 10 S1 */
+FCMPdS1dS2:  br.n  return      /* return from subroutine */
+             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      /* return from subroutine */
+              fmul.sss r6,r6,r8   /* add the two sources and place result 10 S1 */
+FMULsDsS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fmul.sds r6,r5,r8   /* add the two sources and place result 10 S1 */
+FMULsDdS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fmul.dss r5,r6,r8   /* add the two sources and place result 10 S1 */
+FMULdDsS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+              fmul.dds r5,r5,r8   /* add the two sources and place result 10 S1 */
+FMULdDdS1dS2: br.n  return      /* return from subroutine */
+              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      /* return from subroutine */
+FDIVsDsS1dS2: fdiv.ssd r6,r6,r7   /* add the two sources and place result 10 S1 */
+              br    return      /* return from subroutine */
+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      /* return from subroutine */
+FDIVsDdS1dS2: fdiv.sdd r6,r5,r7   /* add the two sources and place result 10 S1 */
+             br    return      /* return from subroutine */
+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      /* return from subroutine */
+FDIVdDsS1dS2: fdiv.dsd r5,r6,r7   /* add the two sources and place result 10 S1 */
+             br    return      /* return from subroutine */
+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      /* return from subroutine */
+FDIVdDdS1dS2: fdiv.ddd r5,r5,r7   /* add the two sources and place result 10 S1 */
+             br    return      /* return from subroutine */
+
+/* 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   ;return from subroutine */
+            /* fsqrt.ss r6,r8   ;add the two sources and place result 10 S1 */
+/* FSQRTsDdS2:  br.n   return   ;return from subroutine */
+            /* 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   ;return from subroutine */
+            /* fsqrt.ds r5,r8   ;add the two sources and place result 10 S1 */
+/* FSQRTdDdS2:  br.n   return   ;return from subroutine */
+            /* fsqrt.dd r5,r7   ;add the two sources and place result 10 S1 */
+
+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   /* return from subroutine */
+             int.ss r6,r8    /* add the two sources and place result 10 S1 */
+INTdS2:      br.n   return   /* return from subroutine */
+             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   /* return from subroutine */
+             nint.ss r6,r8    /* add the two sources and place result 10 S1 */
+NINTdS2:     br.n   return   /* return from subroutine */
+             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   /* return from subroutine */
+             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                 /* return from subroutine */
+
+             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. */
+
+             text
+            align 8
+             global _zero
+_zero:       bb0    s1inf,r12,S1noinf /* see if S1 is zero */
+             bb0    s2inf,r12,S2noinf /* see if S2 is zero */
+             jmp    r1                /* return from function */
+
+/* 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 from */
+                                       /* function */
+             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 from */
+                                       /* function */
+             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 from */
+                                       /* function */
+             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 from */
+                                       /* function */
+operation:   jmp    r1                 /* return from function */
+
+             data
+
+               text                                    
+               align 8
+/*  input: r3 is the excepton frame */
+_Xfp_imprecise: global _Xfp_imprecise
+               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      _FPunderflow
+       2:      bb0     1,r4,3f /* branch to FPoverflow if bit set */
+               br      _FPoverflow
+       3:
+#ifdef HANDLER
+               br      _handler        /* branch to handler since bit will be set */
+                                       /* for inexact */
+#endif
+               /* should never get here!!!! */
+       data
+       align 8
+       1: string "error in inprecise fp exception handler, r4 is 0x%08x\n\0"
+       align 8
+       text
+               or.u r2, r0, hi16(1b)
+               or   r2, r2, lo16(1b)
+               or   r3, r4, r0
+               bsr _printf
+               or.u r2, r0, hi16(1b)
+               or   r2, r2, lo16(1b)
+               bsr _panic
+
+fpui_wrapup:
+        tb1     0,r0,0          /* make sure all floating point operations */
+        ldcr    r5, psr        /* load the PSR */
+        /* have finished */
+        or      r5, r5, 0x2   /* disable interrupts */
+        stcr    r5, psr
+#if 0
+Why is this done? -- it screws up things later.
+        or      r5, r5, 0x8   /* set SFU 1 disable bit, disable SFU 1 */
+        stcr    r5, psr
+#endif
+       ld      r1, r31, 32
+       ld      r29,r31, 36
+       addu    r31, r31, 40
+
+       /*  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]
+/* Return.. */
+       jmp     r1
diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c
new file mode 100644 (file)
index 0000000..ac680b2
--- /dev/null
@@ -0,0 +1,1704 @@
+/*
+ * 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.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/kernel.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/mount.h>
+#include <sys/msgbuf.h>
+#include <sys/syscallargs.h>
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+#ifdef SYSVSEM
+#include <sys/sem.h>
+#endif
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/exec.h>
+#include <sys/sysctl.h>
+#include <sys/errno.h>
+#include <net/netisr.h>
+
+#include <mvme88k/dev/pcctworeg.h>
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/psl.h>
+#include <machine/board.h>
+#include <machine/trap.h>
+#include <machine/bug.h>
+
+#include <dev/cons.h>
+
+#include <vm/vm.h>
+#include <vm/vm_map.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#define __IS_MACHDEP_C__
+#include <assym.s>                       /* EF_EPSR, etc. */
+#include <machine/m88100.h>                    /* DMT_VALID        */
+#include <machine/m882xx.h>                    /* CMMU stuff       */
+#if DDB
+#  include <machine/db_machdep.h>
+#endif /* DDB */
+
+#if DDB
+#define DEBUG_MSG db_printf
+#else
+#define DEBUG_MSG printf
+#endif /* DDB */
+static int waittime = -1;
+
+struct intrhand *intr_handlers[256];
+
+unsigned char *ivec[] = {
+       (unsigned char *)0xFFFE0003, /* not used, no such thing as int 0 */
+       (unsigned char *)0xFFFE0007,
+       (unsigned char *)0xFFFE000B,
+       (unsigned char *)0xFFFE000F,
+       (unsigned char *)0xFFFE0013,
+       (unsigned char *)0xFFFE0017,
+       (unsigned char *)0xFFFE001B,
+       (unsigned char *)0xFFFE001F,
+};
+
+u_char *int_mask_level = (u_char *)INT_MASK_LEVEL;
+u_char *int_pri_level = (u_char *)INT_PRI_LEVEL;
+u_char *iackaddr;
+volatile u_char *pcc2intr_mask;
+volatile u_char *pcc2intr_ipl;
+volatile vm_offset_t bugromva;
+volatile vm_offset_t sramva;
+volatile vm_offset_t obiova;
+
+
+int physmem;           /* available physical memory, in pages */
+int cold;
+vm_offset_t avail_end, avail_start, avail_next;
+int msgbufmapped = 0;
+int foodebug = 0;
+int longformat = 0;
+
+/*
+ * safepri is a safe priority for sleep to set for a spin-wait
+ * during autoconfiguration or after a panic.
+ */
+int   safepri = 0;
+
+#if XXX_FUTURE
+/*
+ * iomap stuff is for managing chunks of virtual address space that
+ * can be allocated to IO devices.
+ * XXX none of the drivers use this at this time. IO address is mapped
+ * so that pa == va. XXX nivas
+ */
+vm_offset_t iomapbase;
+struct map *iomap;
+vm_map_t   iomap_map;
+int       niomap;
+#endif
+
+/*
+ * Declare these as initialized data so we can patch them.
+ */
+int    nswbuf = 0;
+#ifdef NBUF
+int    nbuf = NBUF;
+#else
+int    nbuf = 0;
+#endif
+#ifdef BUFPAGES
+int    bufpages = BUFPAGES;
+#else
+int    bufpages = 0;
+#endif
+int *nofault;
+
+caddr_t allocsys __P((caddr_t));
+  
+/*
+ * Info for CTL_HW
+ */
+char   machine[] = "MVME187";          /* cpu "architecture" */
+char   cpu_model[120];
+extern char version[];
+
+struct bugenv bugargs;
+struct kernel{
+       void *entry;
+       void *symtab;
+       void *esym;
+       int   bflags;
+       int   bdev;
+       char *kname;
+       void *smini;
+       void *emini;
+       void *end_load;
+}kflags;
+char *esym;
+
+int boothowto; /* read in kern/bootstrap */
+int cputyp;
+int cpuspeed = 25;     /* 25 MHZ XXX should be read from NVRAM */
+
+#ifndef roundup
+#define roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1))
+#endif /* roundup */
+
+vm_size_t      mem_size;
+vm_size_t      rawmem_size;
+vm_offset_t    first_addr = 0;
+vm_offset_t    last_addr = 0;
+
+vm_offset_t    avail_start, avail_next, avail_end;
+vm_offset_t    virtual_avail, virtual_end;
+vm_offset_t    pcc2consvaddr, clconsvaddr;
+vm_offset_t    miniroot;
+
+void           *end_loaded;
+int            bootdev;
+int            no_symbols = 1;
+
+struct proc    *lastproc;
+pcb_t          curpcb;
+
+
+extern struct user *proc0paddr;
+
+/* XXX this is to fake out the console routines, while booting. */
+void bugttycnputc __P((dev_t, int));
+int bugttycngetc __P((dev_t));
+extern void nullcnpollc __P((dev_t, int));
+void   cmmu_init(void);
+
+static struct consdev bugcons =
+               { NULL, NULL, bugttycngetc, bugttycnputc,
+                   nullcnpollc, makedev(14,0), 1 };
+
+/*
+ * Console initialization: called early on from main,
+ * before vm init or startup.  Do enough configuration
+ * to choose and initialize a console.
+ */
+void
+consinit()
+{
+       extern struct consdev *cn_tab;
+
+       /*
+        * Initialize the console before we print anything out.
+        */
+       cn_tab = NULL;
+       cninit();
+
+#if defined (DDB)
+        kdb_init();
+        if (boothowto & RB_KDB)
+                Debugger();
+#endif
+}
+
+/*
+ * Figure out how much real memory is available.
+ * Start looking from the megabyte after the end of the kernel data,
+ * until we find non-memory.
+ */
+vm_offset_t
+size_memory(void)
+{
+    volatile unsigned int *look;
+    unsigned int *max;
+    extern char *end;
+    #define PATTERN   0x5a5a5a5a
+    #define STRIDE    (4*1024)         /* 4k at a time */
+    #define Roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1))
+
+    /*
+     * count it up.
+     */
+    max = (void*)MAXPHYSMEM;
+    for (look = (void*)Roundup(end, STRIDE); look < max;
+                       look = (int*)((unsigned)look + STRIDE)) {
+       unsigned save;
+
+       /* if can't access, we've reached the end */
+       if (foodebug)
+       printf("%x\n", look);
+       if (badwordaddr((vm_offset_t)look)) {
+#if defined(DEBUG)
+               printf("%x\n", look);
+#endif
+               look = (int *)((int)look - STRIDE);
+               break;
+       }
+
+       /*
+        * If we write a value, we expect to read the same value back.
+        * We'll do this twice, the 2nd time with the opposite bit
+        * pattern from the first, to make sure we check all bits.
+        */
+       save = *look;
+       if (*look = PATTERN, *look != PATTERN)
+               break;
+       if (*look = ~PATTERN, *look != ~PATTERN)
+               break;
+       *look = save;
+    }
+
+    physmem = btoc(trunc_page((unsigned)look));        /* in pages */
+    return(trunc_page((unsigned)look));
+}
+
+void
+identifycpu()
+{
+       /* XXX -take this one out. It can be done in m187_bootstrap() */
+       strcpy(cpu_model, "Motorola M88K");
+       printf("Model: %s\n", cpu_model);
+}
+
+/* The following two functions assume UPAGES == 3 */
+#if    UPAGES != 3
+#error "UPAGES changed?"
+#endif
+
+#if    USPACE != (UPAGES * NBPG)
+#error "USPACE changed?"
+#endif
+
+/*
+ *     Setup u area ptes for u area double mapping.
+ */
+
+void
+save_u_area(struct proc *p, vm_offset_t va)
+{
+    p->p_md.md_upte[0] = kvtopte(va)->bits;
+    p->p_md.md_upte[1] = kvtopte(va + NBPG)->bits;
+    p->p_md.md_upte[2] = kvtopte(va + NBPG + NBPG)->bits;
+}
+
+void
+load_u_area(struct proc *p)
+{
+    pte_template_t *t;
+
+    t = kvtopte(UADDR);
+    t->bits = p->p_md.md_upte[0];
+    t = kvtopte(UADDR + NBPG);
+    t->bits = p->p_md.md_upte[1];
+    t = kvtopte(UADDR + NBPG + NBPG);
+    t->bits = p->p_md.md_upte[2];
+    cmmu_flush_tlb(1, UADDR, NBPG);
+    cmmu_flush_tlb(1, UADDR + NBPG, NBPG);
+    cmmu_flush_tlb(1, UADDR + NBPG + NBPG, NBPG);
+}
+
+void
+cpu_startup()
+{
+       caddr_t v;
+       int sz, i;
+       vm_size_t size;    
+       int base, residual;
+       vm_offset_t minaddr, maxaddr, uarea_pages;
+       extern vm_offset_t miniroot;
+
+       /*
+        * Initialize error message buffer (at end of core).
+        * avail_end was pre-decremented in m1x7_bootstrap().
+        */
+
+       for (i = 0; i < btoc(sizeof(struct msgbuf)); i++)
+               pmap_enter(kernel_pmap, (vm_offset_t)msgbufp,
+                       avail_end + i * NBPG, VM_PROT_ALL, TRUE);
+
+       msgbufmapped = 1;
+
+       printf(version);
+       identifycpu();
+       printf("real mem  = %d\n", ctob(physmem));
+       
+       /*
+        * Find out how much space we need, allocate it,
+        * and then give everything true virtual addresses.
+        */
+       sz = (int)allocsys((caddr_t)0);
+       if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
+               panic("startup: no room for tables");
+       if (allocsys(v) - v != sz)
+               panic("startup: table size inconsistency");
+
+       /*
+        * Grab UADDR virtual address
+        */
+       
+       uarea_pages = UADDR;
+
+       vm_map_find(kernel_map, vm_object_allocate(USPACE), 0,
+               (vm_offset_t *)&uarea_pages, USPACE, TRUE);
+
+       if (uarea_pages != UADDR) {
+               printf("uarea_pages %x: UADDR not free\n", uarea_pages);
+               panic("bad UADDR");
+       }
+
+       /*
+        * Grab the BUGROM space that we hardwired in pmap_bootstrap
+        */
+
+       bugromva = BUGROM_START;
+
+       vm_map_find(kernel_map, vm_object_allocate(BUGROM_SIZE), 0,
+               (vm_offset_t *)&bugromva, BUGROM_SIZE, TRUE);
+
+       if (bugromva != BUGROM_START) {
+               printf("bugromva %x: BUGROM not free\n", bugromva);
+               panic("bad bugromva");
+       }
+
+       /*
+        * Grab the SRAM space that we hardwired in pmap_bootstrap
+        */
+
+       sramva = SRAM_START;
+
+       vm_map_find(kernel_map, vm_object_allocate(SRAM_SIZE), 0,
+               (vm_offset_t *)&sramva, SRAM_SIZE, TRUE);
+
+       if (sramva != SRAM_START) {
+               printf("sramva %x: SRAM not free\n", sramva);
+               panic("bad sramva");
+       }
+
+       /*
+        * Grab the OBIO space that we hardwired in pmap_bootstrap
+        */
+
+       obiova = OBIO_START;
+
+       vm_map_find(kernel_map, vm_object_allocate(OBIO_SIZE), 0,
+               (vm_offset_t *)&obiova, OBIO_SIZE, TRUE);
+
+       if (obiova != OBIO_START) {
+               printf("obiova %x: OBIO not free\n", obiova);
+               panic("bad OBIO");
+       }
+
+       /*
+        * Now allocate buffers proper.  They are different than the above
+        * in that they usually occupy more virtual memory than physical.
+        */
+
+       size = MAXBSIZE * nbuf;
+       buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
+                              &maxaddr, size, TRUE);
+       minaddr = (vm_offset_t)buffers;
+       if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
+                   (vm_offset_t *)&minaddr, size, FALSE) != KERN_SUCCESS) {
+               panic("startup: cannot allocate buffers");
+       }
+       if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
+               /* don't want to alloc more physical mem than needed */
+               bufpages = btoc(MAXBSIZE) * nbuf;
+       }
+       base = bufpages / nbuf;
+       residual = bufpages % nbuf;
+
+       for (i = 0; i < nbuf; i++) {
+               vm_size_t curbufsize;
+               vm_offset_t curbuf;
+
+               /*
+                * First <residual> buffers get (base+1) physical pages
+                * allocated for them.  The rest get (base) physical pages.
+                *
+                * The rest of each buffer occupies virtual space,
+                * but has no physical memory allocated for it.
+                */
+               curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
+               curbufsize = CLBYTES * (i < residual ? base+1 : base);
+
+               /* this faults in the required physical pages */
+               vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
+
+               vm_map_simplify(buffer_map, curbuf);
+       }
+
+       /*
+        * Allocate a submap for exec arguments.  This map effectively
+        * limits the number of processes exec'ing at any time.
+        */
+       exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+                            16*NCARGS, TRUE);
+
+       /*
+        * Allocate map for physio.
+        */
+
+       phys_map = vm_map_create(kernel_pmap, PHYSIO_MAP_START,
+               PHYSIO_MAP_START + PHYSIO_MAP_SIZE, TRUE);
+       if (phys_map == NULL) {
+               panic("cpu_startup: unable to create phys_map");
+       }
+
+#if XXX_FUTURE
+       iomap_map = vm_map_create(kernel_pmap, IOMAP_MAP_START,
+                       IOMAP_MAP_START + IOMAP_SIZE, TRUE);
+       if (iomap_map == NULL) {
+               panic("cpu_startup: unable to create iomap_map");
+       }
+
+       /*
+        * Allocate space from iomap for a (privately managed) pool
+        * of addresses for IO mappings.
+        */
+
+       iomapbase = kmem_alloc_wait(iomap_map, IOMAP_SIZE);
+       rminit(iomap, IOMAP_SIZE, (u_long)iomapbase, "iomap", niomap);
+#endif
+
+       /*
+        * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
+        * we use the more space efficient malloc in place of kmem_alloc.
+        */
+       mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
+                              M_MBUF, M_NOWAIT);
+       bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
+       mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
+                          VM_MBUF_SIZE, FALSE);
+
+       /*
+        * Initialize callouts
+        */
+       callfree = callout;
+       for (i = 1; i < ncallout; i++)
+       callout[i-1].c_next = &callout[i];
+       callout[i-1].c_next = NULL;
+
+       printf("avail mem = %d\n", ptoa(cnt.v_free_count));
+       printf("using %d buffers containing %d bytes of memory\n",
+          nbuf, bufpages * CLBYTES);
+
+#if 0
+       mfs_initminiroot(miniroot);
+#endif /* 0 */
+       /*
+        * Set up buffers, so they can be used to read disk labels.
+        */
+       bufinit();
+
+       /*
+        * Configure the system.
+        */
+       nofault = NULL;
+
+       /*
+        * zero out intr_handlers
+        */
+       bzero((void *)intr_handlers, 256 * sizeof(struct intrhand *));
+
+       configure();
+}
+
+/*
+ * Allocate space for system data structures.  We are given
+ * a starting virtual address and we return a final virtual
+ * address; along the way we set each data structure pointer.
+ *
+ * We call allocsys() with 0 to find out how much space we want,
+ * allocate that much and fill it with zeroes, and then call
+ * allocsys() again with the correct base virtual address.
+ */
+caddr_t
+allocsys(v)
+       register caddr_t v;
+{
+
+#define        valloc(name, type, num) \
+           v = (caddr_t)(((name) = (type *)v) + (num))
+
+#ifdef REAL_CLISTS
+       valloc(cfree, struct cblock, nclist);
+#endif
+       valloc(callout, struct callout, ncallout);
+       valloc(swapmap, struct map, nswapmap = maxproc * 2);
+#ifdef SYSVSHM
+       valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
+#endif
+#ifdef SYSVSEM
+       valloc(sema, struct semid_ds, seminfo.semmni);
+       valloc(sem, struct sem, seminfo.semmns);
+       /* This is pretty disgusting! */
+       valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
+#endif
+#ifdef SYSVMSG
+       valloc(msgpool, char, msginfo.msgmax);
+       valloc(msgmaps, struct msgmap, msginfo.msgseg);
+       valloc(msghdrs, struct msg, msginfo.msgtql);
+       valloc(msqids, struct msqid_ds, msginfo.msgmni);
+#endif
+
+       /*
+        * Determine how many buffers to allocate (enough to
+        * hold 5% of total physical memory, but at least 16).
+        * Allocate 1/2 as many swap buffer headers as file i/o buffers.
+        */
+       if (bufpages == 0)
+           if (physmem < btoc(2 * 1024 * 1024))
+               bufpages = (physmem / 10) / CLSIZE;
+           else
+               bufpages = (physmem / 20) / CLSIZE;
+       if (nbuf == 0) {
+               nbuf = bufpages;
+               if (nbuf < 16)
+                       nbuf = 16;
+       }
+       if (nswbuf == 0) {
+               nswbuf = (nbuf / 2) &~ 1;       /* force even */
+               if (nswbuf > 256)
+                       nswbuf = 256;           /* sanity */
+       }
+       valloc(swbuf, struct buf, nswbuf);
+       valloc(buf, struct buf, nbuf);
+
+#if XXX_FUTURE
+       /*
+        * Arbitrarily limit the number of devices mapping
+        * the IO space at a given time to NIOPMAP (= 32, default).
+        */
+       valloc(iomap, struct map, niomap = NIOPMAP);
+#endif
+       return v;
+}
+
+/*
+ * Set registers on exec.
+ * Clear all except sp and pc.
+ */
+void
+setregs(p, pack, stack, retval)
+       struct proc *p;
+       struct exec_package *pack;
+       u_long stack;
+       int retval[2];
+{
+       register struct trapframe *tf = USER_REGS(p);
+
+       /*
+        * The syscall will ``return'' to snip; set it.
+        * argc, argv, envp are placed on the stack by copyregs.
+        * Point r2 to the stack. crt0 should extract envp from
+        * argc & argv before calling user's main.
+        */
+#if 0
+       /*
+        * I don't think I need to mess with fpstate on 88k because
+        * we make sure the floating point pipeline is drained in
+        * the trap handlers. Should check on this later. XXX Nivas.
+        */
+
+       if ((fs = p->p_md.md_fpstate) != NULL) {
+               /*
+                * We hold an FPU state.  If we own *the* FPU chip state
+                * we must get rid of it, and the only way to do that is
+                * to save it.  In any case, get rid of our FPU state.
+                */
+               if (p == fpproc) {
+                       savefpstate(fs);
+                       fpproc = NULL;
+               }
+               free((void *)fs, M_SUBPROC);
+               p->p_md.md_fpstate = NULL;
+       }
+#endif /* 0 */
+       bzero((caddr_t)tf, sizeof *tf);
+       tf->epsr = 0x3f0; /* user mode, interrupts enabled, fp enabled */
+
+       /*
+        * We want to start executing at pack->ep_entry. The way to
+        * do this is force the processor to fetch from ep_entry. Set
+        * NIP to something bogus and invalid so that it will be a NOOP.
+        * And set sfip to ep_entry with valid bit on so that it will be
+        * fetched.
+        */
+
+       tf->snip = pack->ep_entry & ~3;
+       tf->sfip = (pack->ep_entry & ~3) | FIP_V;
+       tf->r[2] = stack;
+       tf->r[31] = stack;
+       retval[1] = 0;
+}
+
+struct sigstate {
+       int     ss_flags;               /* which of the following are valid */
+       struct  trapframe ss_frame;     /* original exception frame */
+};
+
+/*
+ * WARNING: code in locore.s assumes the layout shown for sf_signo
+ * thru sf_handler so... don't screw with them!
+ */
+struct sigframe {
+       int     sf_signo;               /* signo for handler */
+       siginfo_t *sf_sip;
+       struct  sigcontext *sf_scp;     /* context ptr for handler */
+       sig_t   sf_handler;             /* handler addr for u_sigc */
+       struct  sigcontext sf_sc;       /* actual context */
+       siginfo_t sf_si;
+};
+
+#ifdef DEBUG
+int sigdebug = 0;
+int sigpid = 0;
+#define SDB_FOLLOW     0x01
+#define SDB_KSTACK     0x02
+#define SDB_FPSTATE    0x04
+#endif
+
+/*
+ * Send an interrupt to process.
+ */
+void
+sendsig(catcher, sig, mask, code, type, val)
+       sig_t catcher;
+       int sig, mask;
+       unsigned long code;
+       int type;
+       union sigval val;
+{
+       register struct proc *p = curproc;
+       register struct trapframe *tf;
+       register struct sigacts *psp = p->p_sigacts;
+       struct sigframe *fp;
+       int oonstack, fsize;
+       struct sigframe sf;
+       int addr;
+       extern char sigcode[], esigcode[];
+
+#define szsigcode (esigcode - sigcode)
+
+       tf = p->p_md.md_tf;
+       oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+       /*
+        * Allocate and validate space for the signal handler
+        * context. Note that if the stack is in data space, the
+        * call to grow() is a nop, and the copyout()
+        * will fail if the process has not already allocated
+        * the space with a `brk'.
+        */
+       fsize = sizeof(struct sigframe);
+       if ((psp->ps_flags & SAS_ALTSTACK) &&
+           (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
+           (psp->ps_sigonstack & sigmask(sig))) {
+               fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
+                                        psp->ps_sigstk.ss_size - fsize);
+               psp->ps_sigstk.ss_flags |= SA_ONSTACK;
+       } else
+               fp = (struct sigframe *)(tf->r[31] - fsize);
+       if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 
+               (void)grow(p, (unsigned)fp);
+#ifdef DEBUG
+       if ((sigdebug & SDB_FOLLOW) ||
+           (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+               printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
+                      p->p_pid, sig, &oonstack, fp, &fp->sf_sc);
+#endif
+       /*
+        * Build the signal context to be used by sigreturn.
+        */
+       sf.sf_signo = sig;
+       sf.sf_scp = &fp->sf_sc;
+       sf.sf_handler = catcher;
+       sf.sf_sc.sc_onstack = oonstack;
+       sf.sf_sc.sc_mask = mask;
+
+       if (psp->ps_siginfo & sigmask(sig)) {
+               sf.sf_sip = &fp->sf_si;
+               initsiginfo(&sf.sf_si, sig, code, type, val);
+       }
+
+
+       /*
+        * Copy the whole user context into signal context that we
+        * are building.
+        */
+       bcopy((caddr_t)tf->r, (caddr_t)sf.sf_sc.sc_regs,
+                sizeof(sf.sf_sc.sc_regs));
+       sf.sf_sc.sc_xip = tf->sxip & ~3;
+       sf.sf_sc.sc_nip = tf->snip & ~3;
+       sf.sf_sc.sc_fip = tf->sfip & ~3;
+       sf.sf_sc.sc_ps = tf->epsr;
+       sf.sf_sc.sc_sp  = tf->r[31];
+       sf.sf_sc.sc_fpsr = tf->fpsr;
+       sf.sf_sc.sc_fpcr = tf->fpcr;
+       sf.sf_sc.sc_ssbr = tf->ssbr;
+       sf.sf_sc.sc_dmt0 = tf->dmt0;
+       sf.sf_sc.sc_dmd0 = tf->dmd0;
+       sf.sf_sc.sc_dma0 = tf->dma0;
+       sf.sf_sc.sc_dmt1 = tf->dmt1;
+       sf.sf_sc.sc_dmd1 = tf->dmd1;
+       sf.sf_sc.sc_dma1 = tf->dma1;
+       sf.sf_sc.sc_dmt2 = tf->dmt2;
+       sf.sf_sc.sc_dmd2 = tf->dmd2;
+       sf.sf_sc.sc_dma2 = tf->dma2;
+       sf.sf_sc.sc_fpecr = tf->fpecr;
+       sf.sf_sc.sc_fphs1 = tf->fphs1;
+       sf.sf_sc.sc_fpls1 = tf->fpls1;
+       sf.sf_sc.sc_fphs2 = tf->fphs2;
+       sf.sf_sc.sc_fpls2 = tf->fpls2;
+       sf.sf_sc.sc_fppt = tf->fppt;
+       sf.sf_sc.sc_fprh = tf->fprh;
+       sf.sf_sc.sc_fprl = tf->fprl;
+       sf.sf_sc.sc_fpit = tf->fpit;
+       if (copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf)) {
+               /*
+                * Process has trashed its stack; give it an illegal
+                * instruction to halt it in its tracks.
+                */
+               SIGACTION(p, SIGILL) = SIG_DFL;
+               sig = sigmask(SIGILL);
+               p->p_sigignore &= ~sig;
+               p->p_sigcatch &= ~sig;
+               p->p_sigmask &= ~sig;
+               psignal(p, SIGILL);
+               return;
+       }
+       /* 
+        * Build the argument list for the signal handler.
+        * Signal trampoline code is at base of user stack.
+        */
+       addr = (int)PS_STRINGS - szsigcode;
+       tf->snip = (addr & ~3) | NIP_V;
+       tf->sfip = (tf->snip + 4) | FIP_V;
+       tf->r[31] = (unsigned)fp;
+#ifdef DEBUG
+       if ((sigdebug & SDB_FOLLOW) ||
+           (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+               printf("sendsig(%d): sig %d returns\n",
+                      p->p_pid, sig);
+#endif
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken.  Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * psl to gain improper priviledges or to cause
+ * a machine fault.
+ */
+/* ARGSUSED */
+sys_sigreturn(p, v, retval)
+       struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct sys_sigreturn_args /* {
+               syscallarg(struct sigcontext *) sigcntxp;
+       } */ *uap = v;
+       register struct sigcontext *scp;
+       register struct trapframe *tf;
+       struct sigcontext ksc;
+       int error;
+
+       scp = (struct sigcontext *)SCARG(uap, sigcntxp);
+#ifdef DEBUG
+       if (sigdebug & SDB_FOLLOW)
+               printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+#endif
+       if ((int)scp & 3 || useracc((caddr_t)scp, sizeof *scp, B_WRITE) == 0 ||
+               copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(struct sigcontext)))
+               return (EINVAL);
+
+       tf = p->p_md.md_tf;
+       scp = &ksc;
+       /*
+        * xip, nip and fip must be multiples of 4.  This is all
+        * that is required; if it holds, just do it.
+        */
+#if 0
+       if (((scp->sc_xip | scp->sc_nip | scp->sc_fip) & 3) != 0)
+               return (EINVAL);
+#endif /* 0 */
+       if (((scp->sc_xip | scp->sc_nip | scp->sc_fip) & 3) != 0)
+               printf("xip %x nip %x fip %x\n",
+                       scp->sc_xip, scp->sc_nip, scp->sc_fip);
+
+
+       /*
+        * this can be improved by doing
+        *       bcopy(sc_reg to tf, sizeof sigcontext - 2 words)
+        * XXX nivas
+        */
+
+       bcopy((caddr_t)scp->sc_regs, (caddr_t)tf->r,
+                sizeof(scp->sc_regs));
+       tf->sxip = (scp->sc_xip) | XIP_V;
+       tf->snip = (scp->sc_nip) | NIP_V;
+       tf->sfip = (scp->sc_fip) | FIP_V;
+       tf->epsr = scp->sc_ps;
+       tf->r[31] = scp->sc_sp;
+       tf->fpsr = scp->sc_fpsr;
+       tf->fpcr = scp->sc_fpcr;
+       tf->ssbr = scp->sc_ssbr;
+       tf->dmt0 = scp->sc_dmt0;
+       tf->dmd0 = scp->sc_dmd0;
+       tf->dma0 = scp->sc_dma0;
+       tf->dmt1 = scp->sc_dmt1;
+       tf->dmd1 = scp->sc_dmd1;
+       tf->dma1 = scp->sc_dma1;
+       tf->dmt2 = scp->sc_dmt2;
+       tf->dmd2 = scp->sc_dmd2;
+       tf->dma2 = scp->sc_dma2;
+       tf->fpecr = scp->sc_fpecr;
+       tf->fphs1 = scp->sc_fphs1;
+       tf->fpls1 = scp->sc_fpls1;
+       tf->fphs2 = scp->sc_fphs2;
+       tf->fpls2 = scp->sc_fpls2;
+       tf->fppt = scp->sc_fppt;
+       tf->fprh = scp->sc_fprh;
+       tf->fprl = scp->sc_fprl;
+       tf->fpit = scp->sc_fpit;
+
+       tf->epsr = scp->sc_ps;
+       /*
+        * Restore the user supplied information
+        */
+       if (scp->sc_onstack & 01)
+               p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+       else
+               p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+       p->p_sigmask = scp->sc_mask & ~sigcantmask;
+       return (EJUSTRETURN);
+}
+
+_doboot()
+{
+       cmmu_shutdown_now();
+       bugreturn();
+}
+
+void
+boot(howto)
+       register int howto;
+{
+       /* take a snap shot before clobbering any registers */
+       if (curproc)
+               savectx(curproc->p_addr, 0);
+
+       boothowto = howto;
+       if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
+
+               extern struct proc proc0;
+
+               /* protect against curproc->p_stats.foo refs in sync()   XXX */
+               if (curproc == NULL)
+                       curproc = &proc0;
+
+               waittime = 0;
+               vfs_shutdown();
+
+               /*
+                * If we've been adjusting the clock, the todr
+                * will be out of synch; adjust it now.
+                */
+               resettodr();
+       }
+       splhigh();                      /* extreme priority */
+       if (howto&RB_HALT) {
+               printf("halted\n\n");
+               bugreturn();
+       } else {
+               if (howto & RB_DUMP)
+                       dumpsys();
+               doboot();
+               /*NOTREACHED*/
+       }
+       /*NOTREACHED*/
+}
+
+unsigned       dumpmag = 0x8fca0101;   /* magic number for savecore */
+int    dumpsize = 0;           /* also for savecore */
+long   dumplo = 0;
+
+dumpconf()
+{
+       int nblks;
+
+       dumpsize = physmem;
+       if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
+               nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+               if (dumpsize > btoc(dbtob(nblks - dumplo)))
+                       dumpsize = btoc(dbtob(nblks - dumplo));
+               else if (dumplo == 0)
+                       dumplo = nblks - btodb(ctob(physmem));
+       }
+       /*
+        * Don't dump on the first CLBYTES (why CLBYTES?)
+        * in case the dump device includes a disk label.
+        */
+       if (dumplo < btodb(CLBYTES))
+               dumplo = btodb(CLBYTES);
+}
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+dumpsys()
+{
+
+       msgbufmapped = 0;
+       if (dumpdev == NODEV)
+               return;
+       /*
+        * For dumps during autoconfiguration,
+        * if dump device has already configured...
+        */
+       if (dumpsize == 0)
+               dumpconf();
+       if (dumplo < 0)
+               return;
+       printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
+       printf("dump ");
+       switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
+
+       case ENXIO:
+               printf("device bad\n");
+               break;
+
+       case EFAULT:
+               printf("device not ready\n");
+               break;
+
+       case EINVAL:
+               printf("area improper\n");
+               break;
+
+       case EIO:
+               printf("i/o error\n");
+               break;
+
+       default:
+               printf("succeeded\n");
+               break;
+       }
+}
+
+/*
+ * fill up ivec array with interrupt response vector addresses.
+ */
+void
+setupiackvectors()
+{
+       register u_char *vaddr;
+#ifdef XXX_FUTURE
+       extern vm_offset_t iomap_mapin(vm_offset_t, vm_size_t,  boolean_t);
+#endif
+
+       /*
+        * map a page in for phys address 0xfffe0000 and set the
+        * addresses for various levels.
+        */
+#ifdef XXX_FUTURE
+       vaddr = (u_char *)iomap_mapin(0xfffe0000, NBPG, 1);
+#else
+       vaddr = (u_char *)0xfffe0000;
+#endif
+
+       ivec[0] = vaddr + 0x03;
+       ivec[1] = vaddr + 0x07;
+       ivec[2] = vaddr + 0x0b;
+       ivec[3] = vaddr + 0x0f;
+       ivec[4] = vaddr + 0x13;
+       ivec[5] = vaddr + 0x17;
+       ivec[6] = vaddr + 0x1b;
+       ivec[7] = vaddr + 0x1f;
+}
+
+/*
+ * Insert ihand in the list of handlers at vector vec.
+ * Return return different error codes for the different
+ * errors and let the caller decide what to do.
+ */
+
+int
+intr_establish(int vec, struct intrhand *ihand)
+{
+       register struct intrhand *intr;
+
+       if (vec < 0 || vec > 255) {
+#if DIAGNOSTIC
+               panic("intr_establish: vec (%x) not between 0 and 0xff\n",
+                       vec);
+#endif /* DIAGNOSTIC */
+               return (INTR_EST_BADVEC);
+       }
+
+       if (intr = intr_handlers[vec]) {
+               if (intr->ih_ipl != ihand->ih_ipl) {
+#if DIAGNOSTIC
+                       panic("intr_establish: there are other handlers with vec (%x) at ipl %x, but you want it at %x\n",
+                               intr->ih_ipl, vec, ihand->ih_ipl);
+#endif /* DIAGNOSTIC */
+                       return (INTR_EST_BADIPL);
+               }
+
+               /*
+                * Go to the end of the chain
+                */
+               while (intr->ih_next)
+                       intr = intr->ih_next;
+       }
+
+       ihand->ih_next = 0;
+
+       if (intr)
+               intr->ih_next = ihand;
+       else
+               intr_handlers[vec] = ihand;
+       
+       return (INTR_EST_SUCC);
+}
+
+/*
+ *     Device interrupt handler
+ *
+ *      when we enter, interrupts are disabled;
+ *      when we leave, they should be disabled,
+ *      but they need not be disabled throughout
+ *      the routine.
+ */
+
+void
+ext_int(u_int v, struct m88100_saved_state *eframe)
+{
+       register u_char mask, level, xxxvec;
+       register struct intrhand *intr;
+       int ret;
+       u_char vec;
+
+       /* get level and mask */
+
+       asm volatile("ld.b      %0,%1" : "=r" (mask) : "" (*pcc2intr_mask));
+       asm volatile("ld.b      %0,%1" : "=r" (level) : "" (*pcc2intr_ipl));
+
+       /*
+        * It is really bizarre for the mask and level to the be the same.
+        * pcc2 for 187 blocks all interrupts at and below the mask value,
+        * so we should not be getting an interrupt at the level that is
+        * already blocked. I can't explain this case XXX nivas
+        */
+
+       if ((mask == level) && level) {
+               printf("mask == level, %d\n", level);
+               goto beatit;
+       }
+
+       /*
+        * Interrupting level cannot be 0--0 doesn't produce an interrupt.
+        * Weird! XXX nivas
+        */
+
+       if (level == 0) {
+               printf("Bogons... level %x and mask %x\n", level, mask);
+               goto beatit;
+       }
+
+       /* and block interrupts at level or lower */
+       setipl((u_char)level);
+       /* and stash it away in the trap frame */
+       eframe->mask = mask;
+#if 0
+       asm volatile("st.b      %1,%0" : "=m" (*pcc2intr_mask) :  "r" (level));
+#endif
+       if (level > 7 || (char)level < 0) {
+               panic("int level (%x) is not between 0 and 7\n", level);
+       }
+
+       /* generate IACK and get the vector */
+
+#if XXX
+       asm volatile("ld.b      %0,%1" : "=r" (vec) : "" (*ivec[level]));
+       asm volatile("tb1       0, r0, 0");     
+       asm volatile("tb1       0, r0, 0");     
+       asm volatile("tb1       0, r0, 0");     
+
+       asm volatile("tb1       0, r0, 0");     
+
+       if (guarded_access(ivec[level], 1, &vec) == EFAULT) {
+               printf("Unable to get vector for this interrupt (level %x)\n",
+                                       level);
+               goto out;
+       }       
+#endif XXX
+
+       asm volatile("tb1       0, r0, 0");     
+       if (guarded_access(ivec[level], 1, &vec) == EFAULT) {
+               printf("Unable to get vector for this interrupt (level %x)\n",
+                                       level);
+               goto out;
+       }
+       asm volatile("tb1       0, r0, 0");     
+       asm volatile("tb1       0, r0, 0");     
+       asm volatile("tb1       0, r0, 0");     
+       /*vec = xxxvec;*/
+
+       if (vec > 0xFF) {
+               panic("interrupt vector %x greater than 255\n", vec);
+       }
+
+       enable_interrupt();
+
+       if ((intr = intr_handlers[vec]) == 0) {
+               printf("Spurious interrupt (level %x and vec %x)\n",
+                       level, vec);
+       }
+       if (intr && intr->ih_ipl != level) {
+               panic("Handler ipl %x not the same as level %x\n",
+                       intr->ih_ipl, level);
+       }
+
+       /*
+        * Walk through all interrupt handlers in the chain for the
+        * given vector, calling each handler in turn, till some handler
+        * returns a value != 0.
+        */
+
+       for (ret = 0; intr; intr = intr->ih_next) {
+               if (intr->ih_wantframe)
+                       ret = (*intr->ih_fn)(intr->ih_arg, (void *)eframe);
+               else
+                       ret = (*intr->ih_fn)(intr->ih_arg);
+               if (ret)
+                       break;
+       }
+
+       if (ret == 0) {
+               printf("Unclaimed interrupt (level %x and vec %x)\n",
+                       level, vec);
+       }
+
+       /*
+        * process any remaining data access exceptions before
+        * returning to assembler
+        */
+       disable_interrupt();
+
+out:
+       if (eframe->dmt0 & DMT_VALID) {
+               trap(T_DATAFLT, eframe);
+               data_access_emulation(eframe);
+               eframe->dmt0 &= ~DMT_VALID;
+       }
+       mask = eframe->mask;
+
+       /*
+        * Restore the mask level to what it was when the interrupt
+        * was taken.
+        */
+       setipl((u_char)mask);
+#if 0
+       asm volatile("st.b      %1,%0" : "=m" (*pcc2intr_mask) :  "r" (mask));
+#endif
+#if 0
+       splx((u_char)mask);
+#endif /* 0 */
+
+beatit:
+       return;
+}
+
+cpu_exec_aout_makecmds(p, epp)
+       struct proc *p;
+       struct exec_package *epp;
+{
+       return ENOEXEC;
+}
+
+sys_sysarch(p, v, retval)
+       struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct sys_sysarch_args /* {
+               syscallarg(int) op;
+               syscallarg(char *) parm;
+       } */ *uap = v;
+       int error = 0;
+
+       switch((int)SCARG(uap, op)) {
+       default:
+               error = EINVAL;
+               break;
+       }
+       return(error);
+}
+
+/*
+ * machine dependent system variables.
+ */
+cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+       int *name;
+       u_int namelen;
+       void *oldp;
+       size_t *oldlenp;
+       void *newp;
+       size_t newlen;
+       struct proc *p;
+{
+
+       /* all sysctl names are this level are terminal */
+       if (namelen != 1)
+               return (ENOTDIR);       /* overloaded */
+
+       switch (name[0]) {
+       default:
+               return (EOPNOTSUPP);
+       }
+       /*NOTREACHED*/
+}
+
+/*
+ * insert an element into a queue 
+ */
+
+void
+_insque(velement, vhead)
+       void *velement, *vhead;
+{
+       register struct prochd *element, *head;
+       element = velement;
+       head = vhead;
+       element->ph_link = head->ph_link;
+       head->ph_link = (struct proc *)element;
+       element->ph_rlink = (struct proc *)head;
+       ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
+}
+
+/*
+ * remove an element from a queue
+ */
+
+void
+_remque(velement)
+       void *velement;
+{
+       register struct prochd *element;
+       element = velement;
+       ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
+       ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
+       element->ph_rlink = (struct proc *)0;
+}
+
+int
+copystr(fromaddr, toaddr, maxlength, lencopied)
+       const void *fromaddr;
+        void *toaddr;
+       size_t maxlength;
+       size_t *lencopied;
+{
+       u_int tally;
+
+       tally = 0;
+
+       while (maxlength--) {
+               *(u_char *)toaddr = *(u_char *)fromaddr++;
+               tally++;
+               if (*(u_char *)toaddr++ == 0) {
+                       if(lencopied) *lencopied = tally;
+                       return(0);
+               }
+       }
+
+       if (lencopied)
+               *lencopied = tally;
+
+       return(ENAMETOOLONG);
+}
+
+void
+setrunqueue(p)
+       register struct proc *p;
+{
+       register struct prochd *q;
+       register struct proc *oldlast;
+       register int which = p->p_priority >> 2;
+
+       if (p->p_back != NULL)
+               panic("setrunqueue %x", p);
+       q = &qs[which];
+       whichqs |= 1 << which;
+       p->p_forw = (struct proc *)q;
+       p->p_back = oldlast = q->ph_rlink;
+       q->ph_rlink = p;
+       oldlast->p_forw = p;
+}
+
+/*
+ * Remove process p from its run queue, which should be the one
+ * indicated by its priority.  Calls should be made at splstatclock().
+ */
+void
+remrunqueue(vp)
+       struct proc *vp;
+{
+       register struct proc *p = vp;
+       register int which = p->p_priority >> 2;
+       register struct prochd *q;
+
+       if ((whichqs & (1 << which)) == 0)
+               panic("remrq %x", p);
+       p->p_forw->p_back = p->p_back;
+       p->p_back->p_forw = p->p_forw;
+       p->p_back = NULL;
+       q = &qs[which];
+       if (q->ph_link == (struct proc *)q)
+               whichqs &= ~(1 << which);
+}
+
+/* dummys for now */
+
+bugsyscall()
+{
+}
+
+void
+myetheraddr(cp)
+       u_char *cp;
+{
+       struct bugniocall niocall;
+
+       niocall.clun = 0;
+       niocall.dlun = 0;
+       niocall.ci = 0;
+       niocall.cd = 0;
+       niocall.cid = NETCTRL_GETHDW;
+       niocall.memaddr = (unsigned int)cp;
+       niocall.nbytes = 6;
+
+       bugnetctrl(&niocall);
+}
+
+netintr()
+{
+#ifdef INET
+       if (netisr & (1 << NETISR_ARP)) {
+               netisr &= ~(1 << NETISR_ARP);
+               arpintr();
+       }
+       if (netisr & (1 << NETISR_IP)) {
+               netisr &= ~(1 << NETISR_IP);
+               ipintr();
+       }
+#endif
+#ifdef NS
+       if (netisr & (1 << NETISR_NS)) {
+               netisr &= ~(1 << NETISR_NS);
+               nsintr();
+       }
+#endif
+#ifdef ISO
+       if (netisr & (1 << NETISR_ISO)) {
+               netisr &= ~(1 << NETISR_ISO);
+               clnlintr();
+       }
+#endif
+#ifdef CCITT
+       if (netisr & (1 << NETISR_CCITT)) {
+               netisr &= ~(1 << NETISR_CCITT);
+               ccittintr();
+       }
+#endif
+#include "ppp.h"
+#if NPPP > 0
+       if (netisr & (1 << NETISR_PPP)) {
+               netisr &= ~(1 << NETISR_PPP);
+               pppintr();
+       }
+#endif
+}
+
+void
+dosoftint()
+{
+       if (ssir & SIR_NET) {
+               siroff(SIR_NET);
+               cnt.v_soft++;
+               netintr();
+       }
+
+       if (ssir & SIR_CLOCK) {
+               siroff(SIR_CLOCK);
+               cnt.v_soft++;
+               softclock();
+       }
+
+       return;
+}
+
+int
+spl0()
+{
+       int x;
+       int level = 0;
+
+       x = splsoftclock();
+
+       if (ssir) {
+               dosoftint();
+       }
+
+       setipl(0);
+
+       return(x);
+}
+
+badwordaddr(void *addr)
+{
+       return badaddr((vm_offset_t)addr, 4);
+}
+
+MY_info(f, p, flags, s)
+       struct trapframe        *f;
+       caddr_t                 p;
+       int                     flags;
+       char                    *s;
+{
+       regdump(f);
+       printf("proc %x flags %x type %s\n", p, flags, s);
+}      
+
+MY_info_done(f, flags)
+       struct trapframe        *f;
+       int                     flags;
+{
+       regdump(f);
+}      
+
+void
+nmihand(void *framep)
+{
+       struct m88100_saved_state *frame = framep;
+
+#if DDB
+       DEBUG_MSG("Abort Pressed\n");
+       Debugger();
+#else
+       DEBUG_MSG("Spurious NMI?\n");
+#endif /* DDB */
+}
+
+regdump(struct trapframe *f)
+{
+#define R(i) f->r[i]
+    printf("R00-05: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(0),R(1),R(2),R(3),R(4),R(5));
+    printf("R06-11: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(6),R(7),R(8),R(9),R(10),R(11));
+    printf("R12-17: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(12),R(13),R(14),R(15),R(16),R(17));
+    printf("R18-23: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(18),R(19),R(20),R(21),R(22),R(23));
+    printf("R24-29: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
+       R(24),R(25),R(26),R(27),R(28),R(29));
+    printf("R30-31: 0x%08x  0x%08x\n",R(30),R(31));
+    printf("sxip %x snip %x sfip %x\n", f->sxip, f->snip, f->sfip);
+    if (f->vector == 0x3) { /* print dmt stuff for data access fault */
+       printf("dmt0 %x dmd0 %x dma0 %x\n", f->dmt0, f->dmd0, f->dma0);
+       printf("dmt1 %x dmd1 %x dma1 %x\n", f->dmt1, f->dmd1, f->dma1);
+       printf("dmt2 %x dmd2 %x dma2 %x\n", f->dmt2, f->dmd2, f->dma2);
+    }
+       if (longformat) {
+               printf("fpsr %x", f->fpsr);
+               printf("fpcr %x", f->fpcr);
+               printf("epsr %x", f->epsr);
+               printf("ssbr %x\n", f->ssbr);
+               printf("dmt0 %x", f->dmt0);
+               printf("dmd0 %x", f->dmd0);
+               printf("dma0 %x", f->dma0);
+               printf("dmt1 %x", f->dmt1);
+               printf("dmd1 %x", f->dmd1);
+               printf("dma1 %x", f->dma1);
+               printf("dmt2 %x", f->dmt2);
+               printf("dmd2 %x", f->dmd2);
+               printf("dma2 %x\n", f->dma2);
+               printf("fpecr %x", f->fpecr);
+               printf("fphs1 %x", f->fphs1);
+               printf("fpls1 %x", f->fpls1);
+               printf("fphs2 %x", f->fphs2);
+               printf("fpls2 %x", f->fpls2);
+               printf("fppt %x", f->fppt);
+               printf("fprh %x", f->fprh);
+               printf("fprl %x", f->fprl);
+               printf("fpit %x\n", f->fpit);
+               printf("vector %x", f->vector);
+               printf("mask %x", f->mask);
+               printf("mode %x", f->mode);
+               printf("scratch1 %x", f->scratch1);
+               printf("pad %x\n", f->pad);
+       }
+}
+
+#if DDB
+inline int
+db_splhigh(void)
+{
+       return (db_setipl(IPL_HIGH));
+}
+
+inline int
+db_splx(int s)
+{
+       return (db_setipl(s));
+}
+#endif /* DDB */       
+
+/*
+ * Called from locore.S during boot,
+ * this is the first C code that's run.
+ */
+
+void
+m187_bootstrap(void)
+{
+    extern char version[];
+    extern char *edata, *end;
+    extern int cold;
+    extern int kernelstart;
+    extern vm_offset_t size_memory(void);
+    extern struct consdev *cn_tab;
+    struct bugbrdid brdid;
+
+    cold = 1;  /* we are still booting */
+
+    cn_tab = &bugcons;
+
+    buginit();
+
+    bugbrdid(&brdid);
+    cputyp = brdid.brdno;
+
+    vm_set_page_size();
+
+#if 0
+    esym  = kflags.esym;
+    boothowto = kflags.bflags;
+    bootdev = kflags.bdev;
+#endif /* 0 */
+    
+#if 0
+    end_loaded = kflags.end_load;
+    if (esym != NULL) {
+       end = (char *)((int)(kflags.symtab));
+    } else {
+       first_addr = (vm_offset_t)&end;
+    }
+#endif
+
+    first_addr = m88k_round_page(first_addr);
+
+    if (!no_symbols)
+       boothowto |= RB_KDB;
+
+    last_addr = size_memory();
+
+    cmmu_init();
+
+    avail_start = first_addr;
+    avail_end = last_addr;
+    printf("%s",version);
+    printf("M187 boot: memory from 0x%x to 0x%x\n", avail_start, avail_end);
+
+    /*
+     * Steal one page at the top of physical memory for msgbuf
+     */
+    avail_end -= PAGE_SIZE;
+
+    pmap_bootstrap((vm_offset_t)M88K_TRUNC_PAGE((unsigned)&kernelstart) /* = loadpt */, 
+                  &avail_start, &avail_end, &virtual_avail,
+                  &virtual_end);
+#if defined(DEBUG)
+    printf("returned from pmap_bootstrap\n");
+#endif
+
+    /*
+     * Must initialize p_addr before autoconfig or
+     * the fault handler will get a NULL reference.
+     */
+    proc0.p_addr = proc0paddr;
+    curproc = &proc0;
+    curpcb = &proc0paddr->u_pcb;
+
+    /* Initialize cached PTEs for u-area mapping. */
+    save_u_area(&proc0, (vm_offset_t)proc0paddr);
+
+    /*
+     * Map proc0's u-area at the standard address (UADDR).
+     */
+    load_u_area(&proc0);
+
+    /* Initialize the "u-area" pages. */
+    bzero((caddr_t)UADDR, UPAGES*NBPG);
+#if defined(DEBUG)
+    printf("returning from init\n");
+#endif
+}
diff --git a/sys/arch/mvme88k/mvme88k/pmap.c b/sys/arch/mvme88k/mvme88k/pmap.c
new file mode 100644 (file)
index 0000000..11d8fa5
--- /dev/null
@@ -0,0 +1,5331 @@
+/*
+ * 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.
+ *
+ */
+
+/* don't want to make them general yet. */
+#ifdef luna88k
+#  define OMRON_PMAP
+#endif
+#  define OMRON_PMAP
+
+#include <sys/types.h>
+#include <machine/board.h>
+#include <vm/pmap.h>
+#include <machine/m882xx.h>            /* CMMU stuff */
+#include <vm/vm_kern.h>                        /* vm/vm_kern.h */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+#include <machine/assert.h>
+
+#include <mvme88k/dev/pcctworeg.h>
+#include <mvme88k/dev/clreg.h>
+
+ /*
+  *  VM externals
+  */
+extern vm_offset_t      avail_start, avail_next, avail_end;
+extern vm_offset_t      virtual_avail, virtual_end;
+
+extern vm_offset_t     pcc2consvaddr;
+extern vm_offset_t     clconsvaddr;
+
+/*
+ * Static variables, functions and variables for debugging
+ */
+#ifdef DEBUG
+#define        STATIC
+
+/*
+ * conditional debugging
+ */
+
+#define CD_NORM                0x01
+#define CD_FULL        0x02
+
+#define CD_ACTIVATE    0x0000004       /* _pmap_activate */
+#define CD_KMAP                0x0000008       /* pmap_expand_kmap */
+#define CD_MAP         0x0000010       /* pmap_map */
+#define CD_MAPB                0x0000020       /* pmap_map_batc */
+#define CD_CACHE       0x0000040       /* pmap_cache_ctrl */
+#define CD_BOOT                0x0000080       /* pmap_bootstrap */
+#define CD_INIT                0x0000100       /* pmap_init */
+#define CD_CREAT       0x0000200       /* pmap_create */
+#define CD_FREE                0x0000400       /* pmap_free_tables */
+#define CD_DESTR       0x0000800       /* pmap_destroy */
+#define CD_RM          0x0001000       /* pmap_remove */
+#define CD_RMAL                0x0002000       /* pmap_remove_all */
+#define CD_COW         0x0004000       /* pmap_copy_on_write */
+#define CD_PROT                0x0008000       /* pmap_protect */
+#define CD_EXP         0x0010000       /* pmap_expand */
+#define CD_ENT         0x0020000       /* pmap_enter */
+#define CD_UPD         0x0040000       /* pmap_update */
+#define CD_COL         0x0080000       /* pmap_collect */
+#define CD_CMOD                0x0100000       /* pmap_clear_modify */
+#define CD_IMOD                0x0200000       /* pmap_is_modified */
+#define CD_CREF                0x0400000       /* pmap_clear_reference */
+#define CD_PGMV                0x0800000       /* pagemove */
+#define CD_CHKPV       0x1000000       /* check_pv_list */
+#define CD_CHKPM       0x2000000       /* check_pmap_consistency */
+#define CD_CHKM                0x4000000       /* check_map */
+#define CD_ALL         0x0FFFFFC
+
+int pmap_con_dbg = CD_FULL|CD_NORM;
+#else
+
+#define        STATIC          static
+
+#endif /* DEBUG */
+
+caddr_t        vmmap;
+pt_entry_t     *vmpte, *msgbufmap;
+
+STATIC struct pmap     kernel_pmap_store;
+pmap_t kernel_pmap = &kernel_pmap_store;
+
+typedef struct kpdt_entry *kpdt_entry_t;
+struct kpdt_entry {
+               kpdt_entry_t    next;
+               vm_offset_t     phys;
+};
+#define        KPDT_ENTRY_NULL         ((kpdt_entry_t)0)
+
+STATIC kpdt_entry_t            kpdt_free;
+
+/*
+ * MAX_KERNEL_VA_SIZE must fit into the virtual address space between
+ * VM_MIN_KERNEL_ADDRESS and VM_MAX_KERNEL_ADDRESS.
+ */
+
+#define        MAX_KERNEL_VA_SIZE      (256*1024*1024) /* 256 Mb */
+
+/*
+ * Size of kernel page tables, which is enough to map MAX_KERNEL_VA_SIZE
+ */
+#define        KERNEL_PDT_SIZE (M88K_BTOP(MAX_KERNEL_VA_SIZE) * sizeof(pt_entry_t))
+
+/*
+ * Size of kernel page tables for mapping onboard IO space.
+ */
+#define        OBIO_PDT_SIZE   (M88K_BTOP(OBIO_SIZE) * sizeof(pt_entry_t))
+
+#define MAX_KERNEL_PDT_SIZE    (KERNEL_PDT_SIZE + OBIO_PDT_SIZE)
+
+/*
+ * Two pages of scratch space.
+ * Used in copy_to_phys(), pmap_copy_page() and pmap_zero_page().
+ */
+vm_offset_t    phys_map_vaddr1, phys_map_vaddr2;
+
+int            ptes_per_vm_page; /* no. of ptes required to map one VM page */
+
+#define PMAP_MAX       512
+
+/*
+ *     The Modify List
+ *
+ * This is an array, one byte per physical page, which keeps track
+ * of modified flags for pages which are no longer containd in any
+ * pmap. (for mapped pages, the modified flags are in the PTE.)
+ */
+char   *pmap_modify_list;
+
+
+/*     The PV (Physical to virtual) List.
+ *
+ * For each vm_page_t, pmap keeps a list of all currently valid virtual
+ * mappings of that page. An entry is a pv_entry_t; the list is the
+ * pv_head_table. This is used by things like pmap_remove, when we must
+ * find and remove all mappings for a particular physical page.
+ */
+typedef        struct pv_entry {
+       struct pv_entry *next;          /* next pv_entry */
+       pmap_t          pmap;           /* pmap where mapping lies */
+       vm_offset_t     va;             /* virtual address for mapping */
+} *pv_entry_t;
+
+#define PV_ENTRY_NULL  ((pv_entry_t) 0)
+
+static pv_entry_t      pv_head_table;  /* array of entries, one per page */
+
+/*
+ * Index into pv_head table, its lock bits, and the modify bits
+ * starting at pmap_phys_start.
+ */
+#define PFIDX(pa)              (atop(pa - pmap_phys_start))
+#define PFIDX_TO_PVH(pfidx)    (&pv_head_table[pfidx])
+
+
+/*
+ *     Locking and TLB invalidation primitives
+ */
+
+/*
+ *     Locking Protocols:
+ *
+ *     There are two structures in the pmap module that need locking:
+ *     the pmaps themselves, and the per-page pv_lists (which are locked
+ *     by locking the pv_lock_table entry that corresponds to the pv_head
+ *     for the list in question.)  Most routines want to lock a pmap and
+ *     then do operations in it that require pv_list locking -- however
+ *     pmap_remove_all and pmap_copy_on_write operate on a physical page
+ *     basis and want to do the locking in the reverse order, i.e. lock
+ *     a pv_list and then go through all the pmaps referenced by that list.
+ *     To protect against deadlock between these two cases, the pmap_lock
+ *     is used.  There are three different locking protocols as a result:
+ *
+ *  1.  pmap operations only (pmap_extract, pmap_access, ...)  Lock only
+ *             the pmap.
+ *
+ *  2.  pmap-based operations (pmap_enter, pmap_remove, ...)  Get a read
+ *             lock on the pmap_lock (shared read), then lock the pmap
+ *             and finally the pv_lists as needed [i.e. pmap lock before
+ *             pv_list lock.]
+ *
+ *  3.  pv_list-based operations (pmap_remove_all, pmap_copy_on_write, ...)
+ *             Get a write lock on the pmap_lock (exclusive write); this
+ *             also guaranteees exclusive access to the pv_lists.  Lock the
+ *             pmaps as needed.
+ *
+ *     At no time may any routine hold more than one pmap lock or more than
+ *     one pv_list lock.  Because interrupt level routines can allocate
+ *     mbufs and cause pmap_enter's, the pmap_lock and the lock on the
+ *     kernel_pmap can only be held at splvm.
+ */
+/* DCR: 12/18/91 - The above explanation is no longer true.  The pmap
+ *     system lock has been removed in favor of a backoff strategy to
+ *     avoid deadlock.  Now, pv_list-based operations first get the
+ *     pv_list lock, then try to get the pmap lock, but if they can't,
+ *     they release the pv_list lock and retry the whole operation.
+ */
+
+#define        SPLVM(spl)      { spl = splvm(); }
+#define        SPLX(spl)       { splx(spl); }
+
+#define PMAP_LOCK(pmap, spl)   SPLVM(spl)
+#define PMAP_UNLOCK(pmap, spl) SPLX(spl)
+
+#define PV_LOCK_TABLE_SIZE(n)  0
+#define LOCK_PVH(index)
+#define UNLOCK_PVH(index)
+
+#define ETHERPAGES 16
+void   *etherbuf;
+int    etherlen;
+
+/*
+ * First and last physical address that we maintain any information
+ * for. Initalized to zero so that pmap operations done before
+ * pmap_init won't touch any non-existent structures.
+ */
+
+static vm_offset_t     pmap_phys_start = (vm_offset_t) 0;
+static vm_offset_t     pmap_phys_end   = (vm_offset_t) 0;
+
+#define PMAP_MANAGED(pa) (pmap_initialized && ((pa) >= pmap_phys_start && (pa) < pmap_phys_end))
+
+/*
+ *     This variable extract vax's pmap.c.
+ *     pmap_verify_free refer to this.
+ *     pmap_init initialize this.
+ *     '90.7.17        Fuzzy
+ */
+boolean_t      pmap_initialized = FALSE;/* Has pmap_init completed? */
+
+/*
+ * Consistency checks.
+ * These checks are disabled by default; enabled by setting CD_FULL
+ * in pmap_con_dbg.
+ */
+#ifdef DEBUG
+
+static void check_pv_list __P((vm_offset_t, pv_entry_t, char *));
+static void check_pmap_consistency __P((char *));
+
+#define CHECK_PV_LIST(phys,pv_h,who) \
+       if (pmap_con_dbg & CD_CHKPV) check_pv_list(phys,pv_h,who)
+#define CHECK_PMAP_CONSISTENCY(who) \
+       if (pmap_con_dbg & CD_CHKPM) check_pmap_consistency(who)
+#else
+#define CHECK_PV_LIST(phys,pv_h,who)
+#define CHECK_PMAP_CONSISTENCY(who)
+#endif /* DEBUG */
+
+/*
+ * number of BATC entries used
+ */
+int    batc_used;
+
+/*
+ * keep track BATC mapping
+ */
+batc_entry_t batc_entry[BATC_MAX];
+
+int    maxcmmu_pb = 4; /* max number of CMMUs per processors pbus      */
+int    n_cmmus_pb = 1; /* number of CMMUs per processors pbus          */
+
+#define cpu_number()   0       /* just being lazy, should be taken out -nivas*/
+
+vm_offset_t kmapva = 0;
+extern vm_offset_t bugromva;
+extern vm_offset_t sramva;
+extern vm_offset_t obiova;
+
+STATIC void
+flush_atc_entry(unsigned users, vm_offset_t va, int kernel)
+{
+       cmmu_flush_remote_tlb(cpu_number(), kernel, va, M88K_PGBYTES);
+}
+
+/*
+ * Routine:    _PMAP_ACTIVATE
+ *
+ * Author:     N. Sugai
+ *
+ * Function:
+ *     Binds the given physical map to the given processor.
+ *
+ * Parameters:
+ *     pmap    pointer to pmap structure
+ *     p       pointer to proc structure
+ *     cpu     CPU number
+ *
+ * If the specified pmap is not kernel_pmap, this routine makes arp
+ * template and stores it into UAPR (user area pointer register) in the
+ * CMMUs connected to the specified CPU.
+ *
+ * If kernel_pmap is specified, only flushes the TLBs mapping kernel
+ * virtual space, in the CMMUs connected to the specified CPU.
+ *
+ * NOTE:
+ * All of the code of this function extracted from macro PMAP_ACTIVATE
+ * to make debugging easy. Accordingly, PMAP_ACTIVATE simlpy call
+ * _pmap_activate.
+ *
+ */
+void
+_pmap_activate(pmap_t pmap, pcb_t pcb, int my_cpu)
+{
+    apr_template_t     apr_data;
+    int                n;
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_ACTIVATE | CD_FULL)) == (CD_ACTIVATE | CD_NORM))
+       printf("(_pmap_activate :%x) pmap 0x%x\n", curproc, (unsigned)pmap);
+#endif
+    
+    if (pmap != kernel_pmap) {
+       /*
+        *      Lock the pmap to put this cpu in its active set.
+        */
+       simple_lock(&pmap->lock);
+
+       apr_data.bits = 0;
+       apr_data.field.st_base = M88K_BTOP(pmap->sdt_paddr); 
+       apr_data.field.wt = 0;
+       apr_data.field.g  = 1;
+       apr_data.field.ci = 0;
+       apr_data.field.te = 1;
+#ifdef notyet
+#ifdef OMRON_PMAP
+       /*
+        * cmmu_pmap_activate will set the uapr and the batc entries, then
+        * flush the *USER* TLB.  IF THE KERNEL WILL EVER CARE ABOUT THE
+        * BATC ENTRIES, THE SUPERVISOR TLBs SHOULB BE FLUSHED AS WELL.
+        */
+       cmmu_pmap_activate(my_cpu, apr_data.bits, pmap->i_batc, pmap->d_batc);
+        for (n = 0; n < BATC_MAX; n++)
+           *(unsigned*)&batc_entry[n] = pmap->i_batc[n].bits;
+#else
+       cmmu_set_uapr(apr_data.bits);
+       cmmu_flush_tlb(0, 0, -1);
+#endif
+#endif /* notyet */
+       /*
+        * I am forcing it to not program the BATC at all. pmap.c module
+        * needs major, major cleanup. XXX nivas
+        */
+       cmmu_set_uapr(apr_data.bits);
+       cmmu_flush_tlb(0, 0, -1);
+
+       /*
+        *      Mark that this cpu is using the pmap.
+        */
+       simple_unlock(&pmap->lock);
+
+    } else {
+
+       /*
+        * kernel_pmap must be always active.
+        */
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_ACTIVATE | CD_NORM)) == (CD_ACTIVATE | CD_NORM))
+       printf("(_pmap_activate :%x) called for kernel_pmap\n", curproc);
+#endif
+
+    }
+} /* _pmap_activate */
+
+/*
+ * Routine:    _PMAP_DEACTIVATE
+ *
+ * Author:     N. Sugai
+ *
+ * Function:
+ *     Unbinds the given physical map to the given processor.
+ *
+ * Parameters:
+ *     pmap    pointer to pmap structure
+ *     th      pointer to thread structure
+ *     cpu     CPU number
+ *
+ * _pmap_deactive simply clears the cpus_using field in given pmap structure.
+ *
+ * NOTE:
+ * All of the code of this function extracted from macro PMAP_DEACTIVATE
+ * to make debugging easy. Accordingly, PMAP_DEACTIVATE simlpy call
+ * _pmap_deactivate.
+ *
+ */
+void
+_pmap_deactivate(pmap_t pmap, pcb_t pcb, int my_cpu)
+{
+    if (pmap != kernel_pmap) {
+       /* Nothing to do */
+    }
+}
+
+/*
+ *  Author: Joe Uemura
+ *     Convert machine-independent protection code to M88K protection bits.
+ *
+ *     History:
+ *     '90.8.3 Fuzzy
+ *                     if defined TEST, 'static' undeclared.
+ *     '90.8.30        Fuzzy
+ *                     delete "if defined TEST, 'static' undeclared."
+ *
+ */
+
+STATIC unsigned int
+m88k_protection(pmap_t map, vm_prot_t prot)
+{
+       pte_template_t p;
+
+       p.bits = 0;
+       p.pte.prot = (prot & VM_PROT_WRITE) ? 0 : 1;
+
+       return(p.bits);
+
+} /* m88k_protection */
+
+
+/*
+ * Routine:    PMAP_PTE
+ *
+ * Function:
+ *     Given a map and a virtual address, compute a (virtual) pointer
+ *     to the page table entry (PTE) which maps the address .
+ *     If the page table associated with the address does not
+ *     exist, PT_ENTRY_NULL is returned (and the map may need to grow).
+ *
+ * Parameters:
+ *     pmap    pointer to pmap structure
+ *     virt    virtual address for which page table entry is desired
+ *
+ *    Otherwise the page table address is extracted from the segment table,
+ *    the page table index is added, and the result is returned.
+ *
+ * Calls:
+ *     SDTENT
+ *     SDT_VALID
+ *     PDT_IDX
+ */
+
+pt_entry_t *
+pmap_pte(pmap_t map, vm_offset_t virt)
+{
+       sdt_entry_t     *sdt;
+
+       /*XXX will this change if physical memory is not contiguous? */
+       /* take a look at PDTIDX XXXnivas */
+       if (map == PMAP_NULL)
+               panic("pmap_pte: pmap is NULL");
+
+       sdt = SDTENT(map,virt);
+
+       /*
+        * Check whether page table is exist or not.
+        */
+       if (!SDT_VALID(sdt))
+               return(PT_ENTRY_NULL);
+       else
+               return((pt_entry_t *)(((sdt + SDT_ENTRIES)->table_addr)<<PDT_SHIFT) +
+                               PDTIDX(virt));
+
+} /* pmap_pte */
+
+
+/*
+ * Routine:    PMAP_EXPAND_KMAP (internal)
+ *
+ * Function:
+ *    Allocate a page descriptor table (pte_table) and validate associated
+ * segment table entry, returning pointer to page table entry. This is
+ * much like 'pmap_expand', except that table space is acquired
+ * from an area set up by pmap_bootstrap, instead of through
+ * kmem_alloc. (Obviously, because kmem_alloc uses the kernel map
+ * for allocation - which we can't do when trying to expand the
+ * kernel map!) Note that segment tables for the kernel map were
+ * all allocated at pmap_bootstrap time, so we only need to worry
+ * about the page table here.
+ *
+ * Parameters:
+ *     virt    VA for which translation tables are needed
+ *     prot    protection attributes for segment entries
+ *
+ * Extern/Global:
+ *     kpdt_free       kernel page table free queue
+ *
+ * Calls:
+ *     m88k_protection
+ *     SDTENT
+ *     SDT_VALID
+ *     PDT_IDX
+ *
+ * This routine simply dequeues a table from the kpdt_free list,
+ * initalizes all its entries (invalidates them), and sets the
+ * corresponding segment table entry to point to it. If the kpdt_free
+ * list is empty - we panic (no other places to get memory, sorry). (Such
+ * a panic indicates that pmap_bootstrap is not allocating enough table
+ * space for the kernel virtual address space).
+ *
+ */
+
+STATIC pt_entry_t *
+pmap_expand_kmap(vm_offset_t virt, vm_prot_t prot)
+{
+    int                        aprot;
+    sdt_entry_t                *sdt;
+    kpdt_entry_t       kpdt_ent;
+    pmap_t             map = kernel_pmap;
+
+#if    DEBUG
+    if ((pmap_con_dbg & (CD_KMAP | CD_FULL)) == (CD_KMAP | CD_FULL))
+       printf("(pmap_expand_kmap :%x) v %x\n", curproc,virt);
+#endif
+
+    aprot = m88k_protection (map, prot);
+
+    /*  segment table entry derivate from map and virt. */
+    sdt = SDTENT(map, virt);
+    if (SDT_VALID(sdt))
+       panic("pmap_expand_kmap: segment table entry VALID");
+
+    kpdt_ent = kpdt_free;
+    if (kpdt_ent == KPDT_ENTRY_NULL) {
+       printf("pmap_expand_kmap: Ran out of kernel pte tables\n");
+       return(PT_ENTRY_NULL);
+    }
+    kpdt_free = kpdt_free->next;
+
+    ((sdt_entry_template_t *)sdt)->bits = kpdt_ent->phys | aprot | DT_VALID;
+    ((sdt_entry_template_t *)(sdt + SDT_ENTRIES))->bits = (vm_offset_t)kpdt_ent | aprot | DT_VALID;
+    (unsigned)(kpdt_ent->phys) = 0;
+    (unsigned)(kpdt_ent->next) = 0;
+
+    return((pt_entry_t *)(kpdt_ent) + PDTIDX(virt));
+}/* pmap_expand_kmap() */
+
+/*
+ * Routine:    PMAP_MAP
+ *
+ * Function:
+ *    Map memory at initalization. The physical addresses being
+ * mapped are not managed and are never unmapped.
+ *
+ * Parameters:
+ *     virt    virtual address of range to map    (IN)
+ *     start   physical address of range to map   (IN)
+ *     end     physical address of end of range   (IN)
+ *     prot    protection attributes              (IN)
+ *
+ * Calls:
+ *     pmap_pte
+ *     pmap_expand_kmap
+ *
+ * Special Assumptions
+ *     For now, VM is already on, only need to map the specified
+ * memory. Used only by pmap_bootstrap() and vm_page_startup().
+ *
+ * For each page that needs mapping:
+ *     pmap_pte is called to obtain the address of the page table
+ *     table entry (PTE). If the page table does not exist,
+ *     pmap_expand_kmap is called to allocate it. Finally, the page table
+ *     entry is set to point to the physical page.
+ *
+ *
+ *     initialize template with paddr, prot, dt
+ *     look for number of phys pages in range
+ *     {
+ *             pmap_pte(virt)  - expand if necessary
+ *             stuff pte from template
+ *             increment virt one page
+ *             increment template paddr one page
+ *     }
+ *
+ */
+vm_offset_t
+pmap_map(vm_offset_t virt, vm_offset_t start, vm_offset_t end, vm_prot_t prot)
+{
+    int                        aprot;
+    unsigned           npages;
+    unsigned           num_phys_pages;
+    unsigned           cmode;
+    pt_entry_t         *pte;
+    pte_template_t      template;
+
+    /*
+     * cache mode is passed in the top 16 bits.
+     * extract it from there. And clear the top
+     * 16 bits from prot.
+     */
+    cmode = (prot & 0xffff0000) >> 16;
+    prot &= 0x0000ffff;
+
+#if    DEBUG
+    if ((pmap_con_dbg & (CD_MAP | CD_FULL)) == (CD_MAP | CD_FULL))
+       printf ("(pmap_map :%x) phys address from %x to %x mapped at virtual %x, prot %x cmode %x\n",
+                curproc, start, end, virt, prot, cmode);
+#endif
+
+    if (start > end)
+       panic("pmap_map: start greater than end address");
+
+    aprot = m88k_protection (kernel_pmap, prot);
+
+    template.bits = M88K_TRUNC_PAGE(start) | aprot | DT_VALID | cmode;
+
+    npages = M88K_BTOP(M88K_ROUND_PAGE(end) - M88K_TRUNC_PAGE(start));
+
+    for (num_phys_pages = npages; num_phys_pages > 0; num_phys_pages--) {
+
+       if ((pte = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL)
+           if ((pte = pmap_expand_kmap(virt, VM_PROT_READ|VM_PROT_WRITE)) == PT_ENTRY_NULL)
+               panic ("pmap_map: Cannot allocate pte table");
+
+#ifdef DEBUG
+       if (pmap_con_dbg & CD_MAP)
+         if (pte->dtype)
+               printf("(pmap_map :%x) pte @ 0x%x already valid\n", curproc, (unsigned)pte);
+#endif
+
+       *pte = template.pte;
+       virt += M88K_PGBYTES;
+       template.bits += M88K_PGBYTES;
+    }
+
+    return(virt);
+
+} /* pmap_map() */
+
+/*
+ * Routine:    PMAP_MAP_BATC
+ *
+ * Function:
+ *    Map memory using BATC at initalization. The physical addresses being
+ * mapped are not managed and are never unmapped.
+ *
+ * Parameters:
+ *     virt    virtual address of range to map    (IN)
+ *     start   physical address of range to map   (IN)
+ *     end     physical address of end of range   (IN)
+ *     prot    protection attributes              (IN)
+ *     cmode   cache control attributes           (IN)
+ *
+ * External & Global:
+ *     batc_used       number of BATC used     (IN/OUT)
+ *
+ * Calls:
+ *     m88k_protection
+ *     BATC_BLK_ALIGNED
+ *     cmmu_store
+ *     pmap_pte
+ *     pmap_expand_kmap
+ *
+ *
+ * For each page that needs mapping:
+ *     If both virt and phys are on the BATC block boundary, map using BATC.
+ *     Else make mapping in the same manner as pmap_map.
+ *
+ *     initialize BATC and pte template
+ *     look for number of phys pages in range
+ *     {
+ *             if virt and phys are on BATC block boundary
+ *             {
+ *                     map using BATC
+ *                     increment virt and phys one BATC block
+ *                     continue outer loop
+ *             }
+ *             pmap_pte(virt)  - expand if necessary
+ *             stuff pte from template
+ *             increment virt one page
+ *             increment template paddr one page
+ *     }
+ *
+ */
+vm_offset_t
+pmap_map_batc(vm_offset_t virt, vm_offset_t start, vm_offset_t end,
+                                       vm_prot_t prot, unsigned cmode)
+{
+    int                        aprot;
+    unsigned           num_phys_pages;
+    vm_offset_t                phys;
+    pt_entry_t         *pte;
+    pte_template_t     template;
+    batc_template_t    batctmp;
+    register int       i;
+
+#if    DEBUG
+    if ((pmap_con_dbg & (CD_MAPB | CD_FULL)) == (CD_MAPB | CD_FULL))
+      printf ("(pmap_map_batc :%x) phys address from %x to %x mapped at virtual %x, prot %x\n", curproc,
+             start, end, virt, prot);
+#endif
+
+    if (start > end)
+      panic("pmap_map_batc: start greater than end address");
+
+    aprot = m88k_protection (kernel_pmap, prot);
+    template.bits = M88K_TRUNC_PAGE(start) | aprot | DT_VALID | cmode;
+    phys = start;
+    batctmp.bits = 0;
+    batctmp.field.sup = 1;                     /* supervisor */
+    batctmp.field.wt = template.pte.wt;                /* write through */
+    batctmp.field.g = template.pte.g;          /* global */
+    batctmp.field.ci = template.pte.ci;                /* cache inhibit */
+    batctmp.field.wp = template.pte.prot;      /* protection */
+    batctmp.field.v = 1;                       /* valid */
+
+    num_phys_pages = M88K_BTOP(M88K_ROUND_PAGE(end) - M88K_TRUNC_PAGE(start));
+
+    while (num_phys_pages > 0) {
+
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_MAPB | CD_FULL)) == (CD_MAPB | CD_FULL))
+         printf("(pmap_map_batc :%x) num_phys_pg=%x, virt=%x, aligne V=%d, phys=%x, aligne P=%d\n", curproc,
+              num_phys_pages, virt, BATC_BLK_ALIGNED(virt), phys, BATC_BLK_ALIGNED(phys));
+#endif
+
+       if ( BATC_BLK_ALIGNED(virt) && BATC_BLK_ALIGNED(phys) && 
+           num_phys_pages >= BATC_BLKBYTES/M88K_PGBYTES &&
+           batc_used < BATC_MAX ) {
+
+           /*
+            * map by BATC
+            */
+           batctmp.field.lba = M88K_BTOBLK(virt);
+           batctmp.field.pba = M88K_BTOBLK(phys);
+
+           cmmu_set_pair_batc_entry(0, batc_used, batctmp.bits);
+
+           batc_entry[batc_used] = batctmp.field;
+
+#ifdef DEBUG
+           if ((pmap_con_dbg & (CD_MAPB | CD_NORM)) == (CD_MAPB | CD_NORM)) {
+               printf("(pmap_map_batc :%x) BATC used=%d, data=%x\n", curproc, batc_used, batctmp.bits);
+           }
+           if (pmap_con_dbg & CD_MAPB) {
+
+               for (i = 0; i < BATC_BLKBYTES; i += M88K_PGBYTES ) {
+                   pte = pmap_pte(kernel_pmap, virt+i);
+                   if (pte->dtype)
+                     printf("(pmap_map_batc :%x) va %x is already mapped : pte %x\n", curproc, virt+i, ((pte_template_t *)pte)->bits);
+               }
+           }
+#endif
+           batc_used++;
+           virt += BATC_BLKBYTES;
+           phys += BATC_BLKBYTES;
+           template.pte.pfn = M88K_BTOP(phys);
+           num_phys_pages -= BATC_BLKBYTES/M88K_PGBYTES;
+           continue;
+       }
+       if ((pte = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL)
+         if ((pte = pmap_expand_kmap(virt, VM_PROT_READ|VM_PROT_WRITE)) == PT_ENTRY_NULL)
+           panic ("pmap_map_batc: Cannot allocate pte table");
+
+#ifdef DEBUG
+       if (pmap_con_dbg & CD_MAPB)
+         if (pte->dtype)
+               printf("(pmap_map_batc :%x) pte @ 0x%x already valid\n", curproc, (unsigned)pte);
+#endif
+
+       *pte = template.pte;
+       virt += M88K_PGBYTES;
+       phys += M88K_PGBYTES;
+       template.bits += M88K_PGBYTES;
+       num_phys_pages--;
+    }
+
+    return(M88K_ROUND_PAGE(virt));
+
+} /* pmap_map_batc() */
+
+/*
+ * Routine:    PMAP_CACHE_CONTROL
+ *
+ * Function:
+ *     Set the cache-control bits in the page table entries(PTE) which maps
+ *     the specifid virutal address range.
+ *
+ *     mode
+ *             writethrough    0x200
+ *             global          0x80
+ *             cache inhibit   0x40
+ *
+ * Parameters:
+ *     pmap_t          map
+ *     vm_offset_t     s
+ *     vm_offset_t     e
+ *     unsigned        mode
+ *
+ * Calls:
+ *     PMAP_LOCK
+ *     PMAP_UNLOCK
+ *     pmap_pte
+ *     invalidate_pte
+ *     flush_atc_entry
+ *     dcachefall
+ *
+ *  This routine sequences through the pages of the specified range.
+ * For each, it calls pmap_pte to acquire a pointer to the page table
+ * entry (PTE). If the PTE is invalid, or non-existant, nothing is done.
+ * Otherwise, the cache-control bits in the PTE's are adjusted as specified.
+ *
+ */
+void
+pmap_cache_ctrl(pmap_t pmap, vm_offset_t s, vm_offset_t e, unsigned mode)
+{
+    int                spl, spl_sav;
+    pt_entry_t *pte;
+    vm_offset_t        va;
+    int                                kflush;
+    int                                cpu;
+    register pte_template_t    opte;
+
+#ifdef DEBUG
+    if ( mode & CACHE_MASK ) {
+       printf("(cache_ctrl) illegal mode %x\n",mode);
+       return;
+    }
+    if ((pmap_con_dbg & (CD_CACHE | CD_NORM)) == (CD_CACHE | CD_NORM)) {
+       printf("(pmap_cache_ctrl :%x) pmap %x, va %x, mode %x\n", curproc, pmap, s, mode);
+    }
+#endif /* DEBUG */
+
+    if ( pmap == PMAP_NULL ) {
+       panic("pmap_cache_ctrl: pmap is NULL");
+    }
+
+    PMAP_LOCK(pmap, spl);
+
+    if (pmap == kernel_pmap) {
+       kflush = 1;
+    } else {
+       kflush = 0;
+    }
+
+    for (va = s; va < e; va += M88K_PGBYTES) {
+       if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL)
+           continue;
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_CACHE | CD_NORM)) == (CD_CACHE | CD_NORM)) {
+       printf("(cache_ctrl) pte@0x%08x\n",(unsigned)pte);
+    }
+#endif /* DEBUG */
+
+       /*
+        * Invalidate pte temporarily to avoid being written back
+        * the modified bit and/or the reference bit by other cpu.
+        *  XXX
+        */
+       spl_sav = splimp();
+       opte.bits = invalidate_pte(pte);
+       ((pte_template_t *)pte)->bits = (opte.bits & CACHE_MASK) | mode;
+       flush_atc_entry(0, va, kflush);
+       splx(spl_sav);
+
+       /*
+        * Data cache should be copied back and invalidated.
+        */
+        cmmu_flush_remote_cache(0, M88K_PTOB(pte->pfn), M88K_PGBYTES);
+    }
+
+    PMAP_UNLOCK(pmap, spl);
+
+} /* pmap_cache_ctrl */
+
+
+/*
+ * Routine:    PMAP_BOOTSTRAP
+ *
+ * Function:
+ *     Bootstarp the system enough to run with virtual memory.
+ *     Map the kernel's code and data, allocate the kernel
+ *     translation table space, and map control registers
+ *     and other IO addresses.
+ *
+ * Parameters:
+ *     load_start      PA where kernel was loaded (IN)
+ *     &phys_start     PA of first available physical page (IN/OUT)
+ *     &phys_end       PA of last available physical page (IN)
+ *     &virtual_avail  VA of first available page (after kernel bss)
+ *     &virtual_end    VA of last available page (end of kernel address space)
+ *
+ * Extern/Global:
+ *
+ *     PAGE_SIZE       VM (software) page size (IN)
+ *     kernelstart     start symbol of kernel text (IN)
+ *     etext           end of kernel text (IN)
+ *     phys_map_vaddr1 VA of page mapped arbitrarily for debug/IO (OUT)
+ *     phys_map_vaddr2 VA of page mapped arbitrarily for debug/IO (OUT)
+ *
+ * Calls:
+ *     simple_lock_init
+ *     pmap_map
+ *     pmap_map_batc
+ *
+ *    The physical address 'load_start' is mapped at
+ * VM_MIN_KERNEL_ADDRESS, which maps the kernel code and data at the
+ * virtual address for which it was (presumably) linked. Immediately
+ * following the end of the kernel code/data, sufficent page of
+ * physical memory are reserved to hold translation tables for the kernel
+ * address space. The 'phys_start' parameter is adjusted upward to
+ * reflect this allocation. This space is mapped in virtual memory
+ * immediately following the kernel code/data map.
+ *
+ *    A pair of virtual pages are reserved for debugging and IO
+ * purposes. They are arbitrarily mapped when needed. They are used,
+ * for example, by pmap_copy_page and pmap_zero_page.
+ *
+ * For m88k, we have to map BUG memory also. This is a read only 
+ * mapping for 0x10000 bytes. We will end up having load_start as
+ * 0 and VM_MIN_KERNEL_ADDRESS as 0 - yes sir, we have one-to-one
+ * mapping!!!
+ */
+
+void
+pmap_bootstrap(vm_offset_t     load_start,     /* IN */
+              vm_offset_t      *phys_start,    /* IN/OUT */
+              vm_offset_t      *phys_end,      /* IN */
+              vm_offset_t      *virt_start,    /* OUT */
+              vm_offset_t      *virt_end)      /* OUT */
+{
+    kpdt_entry_t       kpdt_virt;
+    sdt_entry_t                *kmap;
+    vm_offset_t                vaddr,
+                       virt,
+                       kpdt_phys,
+                       s_text,
+                       e_text,
+                       kernel_pmap_size,
+                       etherpa;
+    apr_template_t     apr_data;
+    pt_entry_t         *pte;
+    int                        i;
+    u_long             foo;
+    extern char        *kernelstart, *etext;
+    extern void cmmu_go_virt(void);
+
+#ifdef DEBUG 
+    if ((pmap_con_dbg & (CD_BOOT | CD_NORM)) == (CD_BOOT | CD_NORM)) {
+       printf("pmap_bootstrap : \"load_start\" 0x%x\n", load_start);
+    }
+#endif
+    ptes_per_vm_page = PAGE_SIZE >> M88K_PGSHIFT;
+    if (ptes_per_vm_page == 0)
+               panic("pmap_bootstrap: VM page size < MACHINE page size");
+
+    if (!PAGE_ALIGNED(load_start)) {
+       panic("pmap_bootstrap : \"load_start\" not on the m88k page boundary : 0x%x\n", load_start);
+    }
+
+    /*
+     * Allocate the kernel page table from the front of available
+     * physical memory,
+     * i.e. just after where the kernel image was loaded.
+     */
+    /*
+     * The calling sequence is 
+     *    ...
+     *  pmap_bootstrap(&kernelstart,...) 
+     *  kernelstart is the first symbol in the load image.
+     *  We link the kernel such that &kernelstart == 0x10000 (size of
+     *                                                 BUG ROM)
+     *  The expression (&kernelstart - load_start) will end up as
+     * 0, making *virt_start == *phys_start, giving a 1-to-1 map)
+     */
+
+    *phys_start = M88K_ROUND_PAGE(*phys_start);
+    *virt_start = *phys_start +
+                (M88K_TRUNC_PAGE((unsigned)&kernelstart) - load_start);
+
+    /*
+     * Initialilze kernel_pmap structure
+     */
+    kernel_pmap->ref_count = 1;
+    kernel_pmap->sdt_paddr = kmap = (sdt_entry_t *)(*phys_start);
+    kernel_pmap->sdt_vaddr = (sdt_entry_t *)(*virt_start);
+    kmapva = *virt_start;
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+       printf("kernel_pmap->sdt_paddr = %x\n",kernel_pmap->sdt_paddr);
+       printf("kernel_pmap->sdt_vaddr = %x\n",kernel_pmap->sdt_vaddr);
+    }
+    /* init double-linked list of pmap structure */
+    kernel_pmap->next = kernel_pmap;
+    kernel_pmap->prev = kernel_pmap;
+#endif
+
+    /* 
+     * Reserve space for segment table entries.
+     * One for the regular segment table and one for the shadow table
+     * The shadow table keeps track of the virtual address of page
+     * tables. This is used in virtual-to-physical address translation
+     * functions. Remember, MMU cares only for physical addresses of
+     * segment and page table addresses. For kernel page tables, we
+     * really don't need this virtual stuff (since the kernel will
+     * be mapped 1-to-1) but for user page tables, this is required.
+     * Just to be consistent, we will maintain the shadow table for
+     * kernel pmap also.
+     */
+
+    kernel_pmap_size = 2*SDT_SIZE;
+
+    /* save pointers to where page table entries start in physical memory */
+    kpdt_phys = (*phys_start + kernel_pmap_size);
+    kpdt_virt = (kpdt_entry_t)(*virt_start + kernel_pmap_size);
+    kernel_pmap_size += MAX_KERNEL_PDT_SIZE;
+    *phys_start += kernel_pmap_size;
+    *virt_start += kernel_pmap_size;
+
+    /* init all segment and page descriptor to zero */
+    bzero(kernel_pmap->sdt_vaddr, kernel_pmap_size);
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+       printf("kpdt_phys = %x\n",kpdt_phys);
+       printf("kpdt_virt = %x\n",kpdt_virt);
+       printf("end of kpdt at (virt)0x%08x  ; (phys)0x%08x\n",
+               *virt_start,*phys_start);
+    }
+#endif
+    /*
+     * init the kpdt queue
+     */
+    kpdt_free = kpdt_virt;
+    for (i = MAX_KERNEL_PDT_SIZE/PDT_SIZE; i>0; i--) {
+       kpdt_virt->next = (kpdt_entry_t)((vm_offset_t)kpdt_virt + PDT_SIZE);
+       kpdt_virt->phys = kpdt_phys;
+       kpdt_virt = kpdt_virt->next;
+       kpdt_phys += PDT_SIZE;
+    }
+    kpdt_virt->next = KPDT_ENTRY_NULL; /* terminate the list */
+
+    /*
+     * Map the kernel image into virtual space
+     */
+
+    s_text = load_start;                       /* paddr of text */
+    e_text = load_start + ((unsigned)&etext -
+               M88K_TRUNC_PAGE((unsigned)&kernelstart));
+                                       /* paddr of end of text section*/
+    e_text = M88K_ROUND_PAGE(e_text);
+
+#ifdef OMRON_PMAP
+#define PMAPER pmap_map
+#else
+#define PMAPER pmap_map_batc
+#endif
+
+    /*  map the first 64k (BUG ROM) read only, cache inhibited (? XXX) */
+    vaddr = PMAPER(
+               0,
+               0,
+               0x10000,
+               (VM_PROT_READ|VM_PROT_WRITE)|(CACHE_INH <<16));
+
+    assert(vaddr == M88K_TRUNC_PAGE((unsigned)&kernelstart));
+
+    vaddr = PMAPER(
+               (vm_offset_t)M88K_TRUNC_PAGE(((unsigned)&kernelstart)),
+               s_text,
+               e_text,
+               VM_PROT_WRITE | VM_PROT_READ|(CACHE_GLOBAL<<16));       /* shouldn't it be RO? XXX*/
+
+    vaddr = PMAPER(
+               vaddr,
+               e_text,
+               (vm_offset_t)kmap,
+               (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_GLOBAL << 16));
+
+    /*
+     * Map system segment & page tables - should be cache inhibited?
+     * 88200 manual says that CI bit is driven on the Mbus while accessing
+     * the translation tree. I don't think we need to map it CACHE_INH
+     * here...
+     */
+    if (kmapva != vaddr) {
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+           printf("(pmap_bootstrap) correcting vaddr\n");
+       }
+#endif
+       while (vaddr < (*virt_start - kernel_pmap_size))
+         vaddr = M88K_ROUND_PAGE(vaddr + 1);
+    }
+
+    vaddr = PMAPER(
+               vaddr,
+               (vm_offset_t)kmap,
+               *phys_start,
+               (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_GLOBAL << 16));
+       
+    etherlen = ETHERPAGES * NBPG;
+
+    /*
+     * Get ethernet buffer - need etherlen bytes physically contiguous.
+     *  1 to 1 mapped as well???. There is actually a bug in the macros
+     *  used by the 1x7 ethernet driver. Remove this when that is fixed.
+     *  XXX -nivas
+     */
+
+    if (vaddr != *virt_start) {
+#ifdef DEBUG
+        if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+           printf("1:vaddr %x *virt_start %x *phys_start %x\n", vaddr,
+               *virt_start, *phys_start);
+       }
+#endif
+       *virt_start = vaddr;
+       *phys_start = round_page(*phys_start);
+    }
+
+    *phys_start = vaddr;
+
+    etherbuf = (void *)vaddr;
+
+    vaddr = PMAPER(
+               vaddr,
+               *phys_start,
+               *phys_start + etherlen,
+               (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_INH << 16));
+
+    *virt_start += etherlen;
+    *phys_start += etherlen;
+
+    if (vaddr != *virt_start) {
+#ifdef DEBUG
+        if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+            printf("2:vaddr %x *virt_start %x *phys_start %x\n", vaddr,
+               *virt_start, *phys_start);
+       }
+#endif
+       *virt_start = vaddr;
+       *phys_start = round_page(*phys_start);
+    }
+
+    *virt_start = round_page(*virt_start);
+    *virt_end = VM_MAX_KERNEL_ADDRESS;
+
+    /*
+     * Map a few more pages for phys routines and debugger.
+     */
+
+    phys_map_vaddr1 = round_page(*virt_start);
+    phys_map_vaddr2 = phys_map_vaddr1 + PAGE_SIZE;
+
+    /*
+     * To make 1:1 mapping of virt:phys, throw away a few phys pages.
+     * XXX what is this? nivas
+     */
+
+   
+    *phys_start += 2 * PAGE_SIZE;
+    *virt_start += 2 * PAGE_SIZE;
+
+    /*
+     * Map all IO space 1-to-1. Ideally, I would like to not do this
+     * but have va for the given IO address dynamically allocated. But
+     * on the 88200, 2 of the BATCs are hardwired to do map the IO space
+     * 1-to-1; I decided to map the rest of the IO space 1-to-1.
+     * And bug ROM & the SRAM need to be mapped 1-to-1 if we ever want to
+     * execute bug system calls after the MMU has been turned on.
+     * OBIO should be mapped cache inhibited.
+     */
+
+    PMAPER(
+            BUGROM_START,
+            BUGROM_START,
+            BUGROM_START + BUGROM_SIZE,
+            VM_PROT_WRITE|VM_PROT_READ|(CACHE_INH << 16));
+
+    PMAPER(
+            SRAM_START,
+            SRAM_START,
+            SRAM_START + SRAM_SIZE,
+            VM_PROT_WRITE|VM_PROT_READ|(CACHE_GLOBAL << 16));
+
+    PMAPER(
+            OBIO_START,
+            OBIO_START,
+            OBIO_START + OBIO_SIZE,
+            VM_PROT_WRITE|VM_PROT_READ|(CACHE_INH << 16));
+
+       /*
+        * Allocate all the submaps we need. Note that SYSMAP just allocates
+        * kernel virtual address with no physical backing memory. The idea
+        * is physical memory will be mapped at this va before using that va.
+        * This means that if different physcal pages are going to be mapped
+        * at different times, we better do a tlb flush before using it -                * else we will be referencing the wrong page.
+        */
+
+#define        SYSMAP(c, p, v, n)      \
+({ \
+       v = (c)virt; \
+       if ((p = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL) \
+               pmap_expand_kmap(virt, VM_PROT_READ|VM_PROT_WRITE|(CACHE_GLOBAL << 16)); \
+       virt += ((n)*NBPG); \
+})
+
+       virt = *virt_start;
+
+       SYSMAP(caddr_t, vmpte , vmmap, 1);
+       SYSMAP(struct msgbuf *, msgbufmap ,msgbufp, 1);
+
+       vmpte->pfn = -1;
+       vmpte->dtype = DT_INVALID;
+       
+       *virt_start = virt;
+
+    /*
+     * Set translation for UPAGES at UADDR. The idea is we want to
+     * have translations set up for UADDR. Later on, the ptes for
+     * for this address will be set so that kstack will refer
+     * to the u area. Make sure pmap knows about this virtual
+     * address by doing vm_findspace on kernel_map.
+     */
+
+    for (i = 0, virt = UADDR; i < UPAGES; i++, virt += PAGE_SIZE) {
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+               printf("setting up mapping for Upage %d @ %x\n", i, virt);
+       }
+#endif
+       if ((pte = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL)
+               pmap_expand_kmap(virt, VM_PROT_READ|VM_PROT_WRITE|(CACHE_GLOBAL << 16));
+    }
+
+    /*
+     * Switch to using new page tables
+     */
+
+    apr_data.bits = 0;
+    apr_data.field.st_base = M88K_BTOP(kernel_pmap->sdt_paddr);
+    apr_data.field.wt = 1;
+    apr_data.field.g  = 1;
+    apr_data.field.ci = 0;
+    apr_data.field.te = 1;     /* Translation enable */
+
+    /* Invalidate entire kernel TLB. */
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+       printf("invalidating tlb %x\n", apr_data.bits);
+    }
+#endif
+    cmmu_flush_remote_tlb(0, 1, 0, -1);
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+       printf("done invalidating tlb %x\n", apr_data.bits);
+    }
+#endif
+
+    /*
+     * Set valid bit to DT_INVALID so that the very first pmap_enter()
+     * on these won't barf in pmap_remove_range().
+     */
+    pte = pmap_pte(kernel_pmap, phys_map_vaddr1);
+    pte->pfn = -1;
+    pte->dtype = DT_INVALID;
+    pte = pmap_pte(kernel_pmap, phys_map_vaddr2);
+    pte->dtype = DT_INVALID;
+    pte->pfn = -1;
+
+    /* still physical */ 
+    /* Load supervisor pointer to segment table. */
+    cmmu_remote_set_sapr(0, apr_data.bits);
+    /* virtual now on */
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+        printf("running virtual - avail_next 0x%x\n", *phys_start);
+    }
+#endif
+    avail_next = *phys_start;
+
+    return;
+    
+} /* pmap_bootstrap() */
+
+/*
+ * Bootstrap memory allocator. This function allows for early dynamic
+ * memory allocation until the virtual memory system has been bootstrapped.
+ * After that point, either kmem_alloc or malloc should be used. This
+ * function works by stealing pages from the (to be) managed page pool,
+ * stealing virtual address space, then mapping the pages and zeroing them.
+ *
+ * It should be used from pmap_bootstrap till vm_page_startup, afterwards
+ * it cannot be used, and will generate a panic if tried. Note that this
+ * memory will never be freed, and in essence it is wired down.
+ */
+
+void *
+pmap_bootstrap_alloc(int size)
+{
+       register void *mem;
+
+       size = round_page(size);
+       mem = (void *)virtual_avail;
+       virtual_avail = pmap_map(virtual_avail, avail_start,
+                               avail_start + size,
+                               VM_PROT_READ|VM_PROT_WRITE|(CACHE_GLOBAL << 16));
+       avail_start += size;
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {
+               printf("pmap_bootstrap_alloc: size %x virtual_avail %x avail_start %x\n",
+                       size, virtual_avail, avail_start);
+       }
+#endif
+       bzero((void *)mem, size);
+       return (mem);
+}
+
+/*
+ * Routine:    PMAP_INIT
+ *
+ * Function:
+ *     Initialize the pmap module. It is called by vm_init, to initialize
+ *     any structures that the pmap system needs to map virtual memory.
+ *
+ * Parameters:
+ *     phys_start      physical address of first available page
+ *                     (was last set by pmap_bootstrap)
+ *     phys_end        physical address of last available page
+ *
+ * Extern/Globals
+ *     pv_head_table (OUT)
+ *     pv_lock_table (OUT)
+ *     pmap_modify_list (OUT)
+ *     pmap_phys_start (OUT)
+ *     pmap_phys_end (OUT)
+ *     pmap_initialized(OUT)
+ *
+ * Calls:
+ *     kmem_alloc
+ *     zinit
+ *
+ *   This routine does not really have much to do. It allocates space
+ * for the pv_head_table, pv_lock_table, pmap_modify_list; and sets these
+ * pointers. It also initializes zones for pmap structures, pv_entry
+ * structures, and segment tables.
+ *
+ *  Last, it sets the pmap_phys_start and pmap_phys_end global
+ * variables. These define the range of pages 'managed' be pmap. These
+ * are pages for which pmap must maintain the PV list and the modify
+ * list. (All other pages are kernel-specific and are permanently
+ * wired.)
+ *
+ *
+ *     kmem_alloc() memory for pv_table
+ *     kmem_alloc() memory for modify_bits
+ *     zinit(pmap_zone)
+ *     zinit(segment zone)
+ *
+ */
+void
+pmap_init(vm_offset_t phys_start, vm_offset_t phys_end)
+{
+    register long              npages;
+    register vm_offset_t       addr;
+    register vm_size_t         s;
+    register int               i;
+    vm_size_t                  pvl_table_size;
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_INIT | CD_NORM)) == (CD_INIT | CD_NORM))
+       printf("(pmap_init) phys_start %x  phys_end %x\n", phys_start, phys_end);
+#endif
+
+    /*
+     * Allocate memory for the pv_head_table,
+     * the modify bit array, and the pte_page table.
+     */
+    npages = atop(phys_end - phys_start);
+    pvl_table_size = PV_LOCK_TABLE_SIZE(npages);
+    s = (vm_size_t)(npages * sizeof(struct pv_entry)   /* pv_list */
+       + npages);                                      /* pmap_modify_list */
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_INIT | CD_FULL)) == (CD_INIT | CD_FULL)) {
+       printf("(pmap_init) nbr of managed pages = %x\n", npages);
+       printf("(pmap_init) size of pv_list = %x\n",
+              npages * sizeof(struct pv_entry));
+    }
+#endif
+
+    s = round_page(s);
+    addr = (vm_offset_t)kmem_alloc(kernel_map, s);
+
+    pv_head_table =  (pv_entry_t)addr;
+    addr = (vm_offset_t)(pv_head_table + npages);
+
+    pmap_modify_list = (char *)addr;
+
+    /*
+     * Only now, when all of the data structures are allocated,
+     * can we set pmap_phys_start and pmap_phys_end. If we set them
+     * too soon, the kmem_alloc above will blow up when it causes
+     * a call to pmap_enter, and pmap_enter tries to manipulate the
+     * (not yet existing) pv_list.
+     */
+    pmap_phys_start = phys_start;
+    pmap_phys_end = phys_end;
+
+    pmap_initialized = TRUE;
+
+} /* pmap_init() */
+
+
+/*
+ * Routine:    PMAP_ZERO_PAGE
+ *
+ * History:
+ *     '90.7.13        Fuzzy
+ *     '90.9.05        Fuzzy
+ *             Bug: template page invalid --> template page valid
+ *
+ *     template = M88K_TRUNC_PAGE(phys)
+ *        | m88k_protection (kernel_pmap, VM_PROT_READ | VM_PROT_WRITE)
+ *        | DT_VALID;
+ *          ^^^^^^^^ add
+ *
+ * Function:
+ *     Zeros the specified (machine independent) page.
+ *
+ * Parameters:
+ *     phys            PA of page to zero
+ *
+ * Extern/Global:
+ *     phys_map_vaddr1
+ *
+ * Calls:
+ *     M88K_TRUNC_PAGE
+ *     m88k_protection
+ *     cmmu_sflush_page
+ *     DO_PTES
+ *     bzero
+ *
+ * Special Assumptions:
+ *     no locking required
+ *
+ *     This routine maps the physical pages ath the 'phys_map' virtual
+ * address set up in pmap_bootstrap. It flushes the TLB to make the new
+ * mappings effective, and zeros all the bits.
+ */
+void
+pmap_zero_page(vm_offset_t phys)
+{
+       vm_offset_t     srcva;
+       pte_template_t  template;
+       unsigned int i;
+       unsigned int spl_sav;
+
+       register int    my_cpu = cpu_number();
+       pt_entry_t      *srcpte;
+
+       srcva = (vm_offset_t)(phys_map_vaddr1 + (my_cpu * PAGE_SIZE));
+       srcpte = pmap_pte(kernel_pmap, srcva);
+
+       for (i = 0; i < ptes_per_vm_page; i++, phys += M88K_PGBYTES)
+         {
+           template.bits = M88K_TRUNC_PAGE(phys)
+             | m88k_protection (kernel_pmap, VM_PROT_READ | VM_PROT_WRITE)
+               | DT_VALID | CACHE_GLOBAL;
+
+
+           spl_sav = splimp();
+           cmmu_flush_tlb(1, srcva, M88K_PGBYTES);
+           *srcpte = template.pte;
+           splx(spl_sav);
+           bzero (srcva, M88K_PGBYTES);
+           /* force the data out */
+           cmmu_flush_remote_data_cache(my_cpu,phys, M88K_PGBYTES);
+         }
+
+} /* pmap_zero_page() */
+
+
+/*
+ * Routine:    PMAP_CREATE
+ *
+ * Author:     Fuzzy
+ *
+ * History:
+ *     '90.7.13        Fuzzy   level 1 --> segment exchange
+ *     '90.7.16        Fuzzy   PT_ALIGNED --> PAGE_ALIGNED exchange
+ *                                     l1_utemplate    delete
+ *     '90.7.20        Fuzzy   kernel segment entries in segment table
+ *                             entries for user space address delete.
+ *                             copying kernel segment entries
+ *                             to user pmap segment entries delete.
+ *                             all user segment table entries initialize
+ *                             to zero (invalid).
+ *
+ * Function:
+ *     Create and return a physical map. If the size specified for the
+ *     map is zero, the map is an actual physical map, and may be referenced
+ *     by the hardware. If the size specified is non-zero, the map will be
+ *     used in software only, and is bounded by that size.
+ *
+ * Paramerters:
+ *     size            size of the map
+ *
+ *  This routines allocates a pmap structure.
+ */
+pmap_t
+pmap_create(vm_size_t size)
+{
+       pmap_t          p;
+
+    /*
+     * A software use-only map doesn't even need a map.
+     */
+    if (size != 0)
+       return(PMAP_NULL);
+
+    CHECK_PMAP_CONSISTENCY("pmap_create");
+
+    p = (pmap_t)malloc(sizeof(*p), M_VMPMAP, M_WAITOK);
+    if (p == PMAP_NULL) {
+       panic("pmap_create: cannot allocate a pmap");
+    }
+
+    bzero(p, sizeof(*p));
+    pmap_pinit(p);
+    return(p);
+
+} /* pmap_create() */
+
+void
+pmap_pinit(pmap_t p)
+{
+    pmap_statistics_t  stats;
+    sdt_entry_t                *segdt;
+    int                        i;
+
+    /*
+     * Allocate memory for *actual* segment table and *shadow* table.
+     */
+    segdt = (sdt_entry_t *)kmem_alloc(kernel_map, 2 * SDT_SIZE);
+    if (segdt == NULL)
+             panic("pmap_create: kmem_alloc failure");
+
+#if 0
+    /* maybe, we can use bzero to zero out the segdt. XXX nivas */
+    bzero(segdt, 2 * SDT_SIZE); */
+#endif /* 0 */
+    /* use pmap zero page to zero it out */
+    pmap_zero_page(pmap_extract(kernel_pmap,(vm_offset_t)segdt));
+    if (PAGE_SIZE == SDT_SIZE)  /* only got half */
+      pmap_zero_page(pmap_extract(kernel_pmap,(vm_offset_t)segdt+PAGE_SIZE));
+    if (PAGE_SIZE < 2*SDT_SIZE) /* get remainder */
+      bzero((vm_offset_t)segdt+PAGE_SIZE, (2*SDT_SIZE)-PAGE_SIZE);
+
+    /*
+     * Initialize pointer to segment table both virtual and physical.
+     */
+    p->sdt_vaddr = segdt;
+    p->sdt_paddr = (sdt_entry_t *)pmap_extract(kernel_pmap,(vm_offset_t)segdt);
+
+    if (!PAGE_ALIGNED(p->sdt_paddr)) {
+       printf("pmap_create: std table = %x\n",(int)p->sdt_paddr);
+       panic("pmap_create: sdt_table not aligned on page boundary");
+    }
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_CREAT | CD_NORM)) == (CD_CREAT | CD_NORM)) {
+       printf("(pmap_create :%x) pmap=0x%x, sdt_vaddr=0x%x, sdt_paddr=0x%x\n",
+            curproc, (unsigned)p, p->sdt_vaddr, p->sdt_paddr);
+    }
+#endif
+
+#if notneeded
+    /*
+     * memory for page tables should be CACHE DISABLED?
+     */
+    pmap_cache_ctrl(kernel_pmap,
+                  (vm_offset_t)segdt,
+                  (vm_offset_t)segdt+SDT_SIZE,
+                  CACHE_INH);
+#endif
+    /*
+     * Initalize SDT_ENTRIES.
+     */
+    /*
+     * There is no need to clear segment table, since kmem_alloc would
+     * provides us clean pages.
+     */
+
+    /*
+     * Initialize pmap structure.
+     */
+    p->ref_count = 1;
+
+#ifdef OMRON_PMAP
+     /* initialize block address translation cache */
+     for (i = 0; i < BATC_MAX; i++) {
+        p->i_batc[i].bits = 0;
+        p->d_batc[i].bits = 0;
+     }
+#endif
+
+    /*
+     * Initialize statistics.
+     */
+    stats = &p->stats;
+    stats->resident_count = 0;
+    stats->wired_count = 0;
+
+#ifdef DEBUG
+    /* link into list of pmaps, just after kernel pmap */
+    p->next = kernel_pmap->next;
+    p->prev = kernel_pmap;
+    kernel_pmap->next = p;
+    p->next->prev = p;
+#endif
+
+} /* pmap_pinit() */
+
+/*
+ * Routine:    PMAP_FREE_TABLES (internal)
+ *
+ *     Internal procedure used by pmap_destroy() to actualy deallocate
+ *     the tables.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *
+ * Calls:
+ *     pmap_pte
+ *     kmem_free
+ *     PT_FREE
+ *
+ * Special Assumptions:
+ *     No locking is needed, since this is only called which the
+ *     ref_count field of the pmap structure goes to zero.
+ *
+ * This routine sequences of through the user address space, releasing
+ * all translation table space back to the system using PT_FREE.
+ * The loops are indexed by the virtual address space
+ * ranges represented by the table group sizes(PDT_TABLE_GROUP_VA_SPACE).
+ *
+ */
+
+STATIC void
+pmap_free_tables(pmap_t pmap)
+{
+    unsigned long      sdt_va; /*  outer loop index */
+    sdt_entry_t        *sdttbl; /*  ptr to first entry in the segment table */
+    pt_entry_t  *gdttbl; /*  ptr to first entry in a page table */
+    unsigned int i,j;
+
+#if    DEBUG
+    if ((pmap_con_dbg & (CD_FREE | CD_NORM)) == (CD_FREE | CD_NORM))
+       printf("(pmap_free_tables :%x) pmap %x\n", curproc, pmap);
+#endif
+
+    sdttbl = pmap->sdt_vaddr;          /* addr of segment table */
+
+    /* 
+      This contortion is here instead of the natural loop 
+      because of integer overflow/wraparound if VM_MAX_USER_ADDRESS is near 0xffffffff
+    */
+
+    i = VM_MIN_USER_ADDRESS / PDT_TABLE_GROUP_VA_SPACE;
+    j = VM_MAX_USER_ADDRESS / PDT_TABLE_GROUP_VA_SPACE;
+    if ( j < 1024 ) j++;
+
+    /* Segment table Loop */
+    for ( ; i < j; i++)
+      {
+       sdt_va = PDT_TABLE_GROUP_VA_SPACE*i;
+       if ((gdttbl = pmap_pte(pmap, (vm_offset_t)sdt_va)) != PT_ENTRY_NULL) {
+#ifdef DEBUG
+           if ((pmap_con_dbg & (CD_FREE | CD_FULL)) == (CD_FREE | CD_FULL))
+               printf("(pmap_free_tables :%x) free page table = 0x%x\n", curproc, gdttbl);
+#endif
+               PT_FREE(gdttbl);
+       }
+
+    } /* Segment Loop */
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_FREE | CD_FULL)) == (CD_FREE | CD_FULL))
+      printf("(pmap_free_tables :%x) free segment table = 0x%x\n", curproc, sdttbl);
+#endif
+    /*
+     * Freeing both *actual* and *shadow* segment tables
+     */
+    kmem_free(kernel_map, (vm_offset_t)sdttbl, 2*SDT_SIZE);
+
+} /* pmap_free_tables() */
+
+
+void
+pmap_release(register pmap_t p)
+{
+       pmap_free_tables(p);
+#ifdef DBG
+       DEBUG ((pmap_con_dbg & (CD_DESTR | CD_NORM)) == (CD_DESTR | CD_NORM))
+         printf("(pmap_destroy :%x) ref_count = 0\n", curproc);
+       /* unlink from list of pmap structs */
+       p->prev->next = p->next;
+       p->next->prev = p->prev;
+#endif
+
+}
+
+/*
+ * Routine:    PMAP_DESTROY
+ *
+ * Function:
+ *     Retire the given physical map from service. Should only be called
+ *     if the map contains no valid mappings.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *
+ * Calls:
+ *     CHECK_PMAP_CONSISTENCY
+ *     PMAP_LOCK, PMAP_UNLOCK
+ *     pmap_free_tables
+ *     zfree
+ *
+ * Special Assumptions:
+ *     Map contains no valid mappings.
+ *
+ *  This routine decrements the reference count in the pmap
+ * structure. If it goes to zero, pmap_free_tables is called to release
+ * the memory space to the system. Then, call kmem_free to free the
+ * pmap structure.
+ */
+void
+pmap_destroy(pmap_t p)
+{
+    register int       c, s;
+
+    if (p == PMAP_NULL) {
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_DESTR | CD_NORM)) == (CD_DESTR | CD_NORM))
+         printf("(pmap_destroy :%x) pmap is NULL\n", curproc);
+#endif
+       return;
+     }
+
+    if (p == kernel_pmap) {
+       panic("pmap_destroy: Attempt to destroy kernel pmap");
+    }
+
+    CHECK_PMAP_CONSISTENCY("pmap_destroy");
+
+    PMAP_LOCK(p, s);
+    c = --p->ref_count;
+    PMAP_UNLOCK(p, s);
+
+    if (c == 0) {
+       pmap_release(p);
+       free((caddr_t)p,M_VMPMAP);
+    }
+
+} /* pmap_destroy() */
+
+
+/*
+ * Routine:    PMAP_REFERENCE
+ *
+ * Function:
+ *     Add a reference to the specified  pmap.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *
+ * Calls:
+ *     PMAP_LOCK, PMAP_UNLOCK
+ *
+ *   Under a pmap read lock, the ref_count field of the pmap structure
+ * is incremented. The function then returns.
+ */
+void
+pmap_reference(pmap_t p)
+{
+    int                s;
+
+    if (p != PMAP_NULL) {
+       PMAP_LOCK(p, s);
+       p->ref_count++;
+       PMAP_UNLOCK(p, s);
+    }
+
+} /* pmap_reference */
+
+
+/*
+ * Routine:    PMAP_REMOVE_RANGE (internal)
+ *
+ * Function:
+ *     Invalidate page table entries associated with the
+ *     given virtual address range. The entries given are the first
+ *     (inclusive) and last (exclusive) entries for the VM pages.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *     s               virtual address of start of range to remove
+ *     e               virtual address of start of range to remove
+ *
+ * External/Global:
+ *     pv lists
+ *     pmap_modify_list
+ *
+ * Calls:
+ *     CHECK_PAGE_ALIGN
+ *     SDTENT
+ *     SDT_VALID
+ *     SDT_NEXT
+ *     pmap_pte
+ *     PDT_VALID
+ *     M88K_PTOB
+ *     PMAP_MANAGED
+ *     PFIDX
+ *     LOCK_PVH
+ *     UNLOCK_PVH
+ *     PFIDX_TO_PVH
+ *     CHECK_PV_LIST
+ *     zfree
+ *     invalidate_pte
+ *     flush_atc_entry
+ *     vm_page_set_modified
+ *     PHYS_TO_VM_PAGE
+ *
+ * Special Assumptions:
+ *     The pmap must be locked.
+ *
+ *   This routine sequences through the pages defined by the given
+ * range. For each page, pmap_pte is called to obtain a (virtual)
+ * pointer to the page table  entry (PTE) associated with the page's
+ * virtual address. If the page table entry does not exist, or is invalid,
+ * nothing need be done.
+ *
+ *  If the PTE is valid, the routine must invalidated the entry. The
+ * 'modified' bit, if on, is referenced to the VM through the
+ * 'vm_page_set_modified' macro, and into the appropriate entry in the
+ * pmap_modify_list. Next, the function must find the PV list entry
+ * associated with this pmap/va (if it doesn't exist - the function
+ * panics). The PV list entry is unlinked from the list, and returned to
+ * its zone.
+ */
+
+STATIC void
+pmap_remove_range(pmap_t pmap, vm_offset_t s, vm_offset_t e)
+{
+    int                        pfi;
+    int                        pfn;
+    int                        num_removed = 0,
+                       num_unwired = 0;
+    register int       i;
+    pt_entry_t         *pte;
+    pv_entry_t         prev, cur;
+    pv_entry_t         pvl;
+    vm_offset_t                pa, va, tva;
+    register unsigned          users;
+    register pte_template_t    opte;
+    int                                kflush;
+
+    if (e < s)
+      panic("pmap_remove_range: end < start");
+
+    /*
+     * Pmap has been locked by pmap_remove.
+     */
+    if (pmap == kernel_pmap) {
+       kflush = 1;
+    } else {
+       kflush = 0;
+    }
+
+    /*
+     * Loop through the range in vm_page_size increments.
+     * Do not assume that either start or end fail on any
+     * kind of page boundary (though this may be true!?).
+     */
+
+    CHECK_PAGE_ALIGN(s, "pmap_remove_range - start addr");
+
+    for (va = s; va < e; va += PAGE_SIZE) {
+
+       sdt_entry_t *sdt;
+
+       sdt = SDTENT(pmap,va);
+
+       if (!SDT_VALID(sdt)) {
+           va &= SDT_MASK; /* align to segment */
+           if (va <= e - (1<<SDT_SHIFT))
+             va += (1<<SDT_SHIFT) - PAGE_SIZE; /* no page table, skip to next seg entry */
+           else /* wrap around */
+             break;
+           continue;
+       }
+
+       pte = pmap_pte(pmap,va);
+
+       if (!PDT_VALID(pte)) {
+           continue;                   /* no page mapping */
+       }
+
+       num_removed++;
+
+       if (pte->wired)
+         num_unwired++;
+
+       pfn = pte->pfn;
+       pa = M88K_PTOB(pfn);
+
+       if (PMAP_MANAGED(pa)) {
+           pfi = PFIDX(pa);
+           /*
+            * Remove the mapping from the pvlist for
+            * this physical page.
+            */
+           pvl = PFIDX_TO_PVH(pfi);
+           CHECK_PV_LIST(pa, pvl, "pmap_remove_range before");
+
+           if (pvl->pmap == PMAP_NULL)
+             panic("pmap_remove: null pv_list");
+
+           if (pvl->va == va && pvl->pmap == pmap) {
+
+               /*
+                * Hander is the pv_entry. Copy the next one
+                * to hander and free the next one (we can't
+                * free the hander)
+                */
+               cur = pvl->next;
+               if (cur != PV_ENTRY_NULL) {
+                   *pvl = *cur;
+                   free((caddr_t)cur, M_VMPVENT);
+               } else {
+                   pvl->pmap =  PMAP_NULL;
+               }
+
+           } else {
+
+               for (prev = pvl; (cur = prev->next) != PV_ENTRY_NULL; prev = cur) {
+                   if (cur->va == va && cur->pmap == pmap) {
+                       break;
+                   }
+               }
+               if (cur == PV_ENTRY_NULL) {
+                   printf("pmap_remove_range: looking for VA "
+                          "0x%x (pa 0x%x) PV list at 0x%x\n", va, pa, (unsigned)pvl);
+                   panic("pmap_remove_range: mapping not in pv_list");
+               }
+
+               prev->next = cur->next;
+               free((caddr_t)cur, M_VMPVENT);
+           }
+
+           CHECK_PV_LIST(pa, pvl, "pmap_remove_range after");
+
+       } /* if PAGE_MANAGED */
+
+       /*
+        * For each pte in vm_page (NOTE: vm_page, not
+        * M88K (machine dependent) page !! ), reflect
+        * modify bits to pager and zero (invalidate,
+        * remove) the pte entry.
+        */
+       tva = va;
+       for (i = ptes_per_vm_page; i > 0; i--) {
+
+           /*
+            * Invalidate pte temporarily to avoid being written back
+            * the modified bit and/or the reference bit by other cpu.
+            */
+           opte.bits = invalidate_pte(pte);
+           flush_atc_entry(0, tva, kflush);
+
+           if (opte.pte.modified) {
+               if (IS_VM_PHYSADDR(pa)) {
+                       vm_page_set_modified(PHYS_TO_VM_PAGE(opte.bits & M88K_PGMASK));
+               }
+               /* keep track ourselves too */
+               if (PMAP_MANAGED(pa))
+                 pmap_modify_list[pfi] = 1;
+           }
+           pte++;
+           tva += M88K_PGBYTES;
+       }
+       
+    } /* end for ( va = s; ...) */
+
+    /*
+     * Update the counts
+     */
+    pmap->stats.resident_count -= num_removed;
+    pmap->stats.wired_count -= num_unwired;
+
+} /* pmap_remove_range */
+
+/*
+ * Routine:    PMAP_REMOVE
+ *
+ * Function:
+ *     Remove the given range of addresses from the specified map.
+ *     It is assumed that start is properly rounded to the VM page size.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *
+ * Special Assumptions:
+ *     Assumes not all entries must be valid in specified range.
+ *
+ * Calls:
+ *     CHECK_PAGE_ALIGN
+ *     PMAP_LOCK, PMAP_UNLOCK
+ *     pmap_remove_range
+ *     panic
+ *
+ *  After taking pmap read lock, pmap_remove_range is called to do the
+ * real work.
+ */
+void
+pmap_remove(pmap_t map, vm_offset_t s, vm_offset_t e)
+{
+    int                spl;
+
+    if (map == PMAP_NULL) {
+        return;
+     }
+
+#if    DEBUG
+    if ((pmap_con_dbg & (CD_RM | CD_NORM)) == (CD_RM | CD_NORM))
+       printf("(pmap_remove :%x) map %x  s %x  e %x\n", curproc, map, s, e);
+#endif
+
+    CHECK_PAGE_ALIGN(s, "pmap_remove start addr");
+
+    if (s>e)
+       panic("pmap_remove: start greater than end address");
+
+    pmap_remove_range(map, s, e);
+} /* pmap_remove() */
+
+
+/*
+ * Routine:    PMAP_REMOVE_ALL
+ *
+ * Function:
+ *     Removes this physical page from all physical maps in which it
+ *     resides. Reflects back modify bits to the pager.
+ *
+ * Parameters:
+ *     phys            physical address of pages which is to
+ *                     be removed from all maps
+ *
+ * Extern/Global:
+ *     pv_head_array, pv lists
+ *     pmap_modify_list
+ *
+ * Calls:
+ *     PMAP_MANAGED
+ *     SPLVM, SPLX
+ *     PFIDX
+ *     PFIDX_TO_PVH
+ *     CHECK_PV_LIST
+ *     simple_lock
+ *     M88K_PTOB
+ *     PDT_VALID
+ *     pmap_pte
+ *     vm_page_set_modified
+ *     PHYS_TO_VM_PAGE
+ *     zfree
+ *
+ *  If the page specified by the given address is not a managed page,
+ * this routine simply returns. Otherwise, the PV list associated with
+ * that page is traversed. For each pmap/va pair pmap_pte is called to
+ * obtain a pointer to the page table entry (PTE) associated with the
+ * va (the PTE must exist and be valid, otherwise the routine panics).
+ * The hardware 'modified' bit in the PTE is examined. If it is on, the
+ * pmap_modify_list entry corresponding to the physical page is set to 1.
+ * Then, the PTE is invalidated, and the PV list entry is unlinked and
+ * freed.
+ *
+ *  At the end of this function, the PV list for the specified page
+ * will be null.
+ */
+void
+pmap_remove_all(vm_offset_t phys)
+{
+    pv_entry_t                 pvl, cur;
+    register pt_entry_t                *pte;
+    int                                pfi;
+    register int               i;
+    register vm_offset_t       va;
+    register pmap_t            pmap;
+    int                                spl;
+    int                                dbgcnt = 0;
+    register unsigned          users;
+    register pte_template_t    opte;
+    int                                kflush;
+
+    if (!PMAP_MANAGED(phys)) {
+       /* not a managed page. */
+#ifdef DEBUG
+       if (pmap_con_dbg & CD_RMAL)
+         printf("(pmap_remove_all :%x) phys addr 0x%x not a managed page\n", curproc, phys);
+#endif
+       return;
+    }
+
+    SPLVM(spl);
+
+    /*
+     * Walk down PV list, removing all mappings.
+     * We have to do the same work as in pmap_remove_pte_page
+     * since that routine locks the pv_head. We don't have
+     * to lock the pv_head, since we have the entire pmap system.
+     */
+remove_all_Retry:
+
+    pfi = PFIDX(phys);
+    pvl = PFIDX_TO_PVH(pfi);
+    CHECK_PV_LIST(phys, pvl, "pmap_remove_all before");
+
+    /*
+     * Loop for each entry on the pv list
+     */
+    while ((pmap = pvl->pmap) != PMAP_NULL) {
+       va = pvl->va;
+       users = 0;
+       if (pmap == kernel_pmap) {
+           kflush = 1;
+       } else {
+           kflush = 0;
+       }
+
+       pte = pmap_pte(pmap, va);
+
+       /*
+        * Do a few consistency checks to make sure
+        * the PV list and the pmap are in synch.
+        */
+       if (pte == PT_ENTRY_NULL) {
+           printf("(pmap_remove_all :%x) phys %x pmap %x va %x dbgcnt %x\n",
+                (unsigned)curproc, phys, (unsigned)pmap, va, dbgcnt);
+           panic("pmap_remove_all: pte NULL");
+       }
+       if (!PDT_VALID(pte))
+           panic("pmap_remove_all: pte invalid");
+       if (M88K_PTOB(pte->pfn) != phys)
+           panic("pmap_remove_all: pte doesn't point to page");
+       if (pte->wired)
+           panic("pmap_remove_all: removing  a wired page");
+
+       pmap->stats.resident_count--;
+
+       if ((cur = pvl->next) != PV_ENTRY_NULL) {
+           *pvl  = *cur;
+           free((caddr_t)cur, M_VMPVENT);
+       }
+       else
+           pvl->pmap = PMAP_NULL;
+
+       /*
+        * Reflect modified pages to pager.
+        */
+       for (i = ptes_per_vm_page; i>0; i--) {
+
+           /*
+            * Invalidate pte temporarily to avoid being written back
+            * the modified bit and/or the reference bit by other cpu.
+            */
+           opte.bits = invalidate_pte(pte);
+           flush_atc_entry(users, va, kflush);
+
+           if (opte.pte.modified) {
+               vm_page_set_modified((vm_page_t)PHYS_TO_VM_PAGE(phys));
+               /* keep track ourselves too */
+               pmap_modify_list[pfi] = 1;
+           }
+           pte++;
+           va += M88K_PGBYTES;
+       }
+
+       /*
+        * Do not free any page tables,
+        * leaves that for when VM calls pmap_collect().
+        */
+       dbgcnt++;
+    }
+    CHECK_PV_LIST(phys, pvl, "pmap_remove_all after");
+
+    SPLX(spl);
+
+} /* pmap_remove_all() */
+
+/*
+ * Routine:    PMAP_COPY_ON_WRITE
+ *
+ * Function:
+ *     Remove write privileges from all physical maps for this physical page.
+ *
+ * Parameters:
+ *     phys            physical address of page to be read-protected.
+ *
+ * Calls:
+ *             SPLVM, SPLX
+ *             PFIDX_TO_PVH
+ *             CHECK_PV_LIST
+ *             simple_lock, simple_unlock
+ *             panic
+ *             PDT_VALID
+ *             M88K_PTOB
+ *             pmap_pte
+ *
+ * Special Assumptions:
+ *     All mapings of the page are user-space mappings.
+ *
+ *  This routine walks the PV list. For each pmap/va pair it locates
+ * the page table entry (the PTE), and sets the hardware enforced
+ * read-only bit. The TLB is appropriately flushed.
+ */
+STATIC void
+pmap_copy_on_write(vm_offset_t phys)
+{
+    register pv_entry_t                pv_e;
+    register pt_entry_t        *pte;
+    register int               i;
+    int                                spl, spl_sav;
+    register unsigned          users;
+    register pte_template_t    opte;
+    int                                kflush;
+
+    if (!PMAP_MANAGED(phys)) {
+#ifdef DEBUG
+       if (pmap_con_dbg & CD_CMOD)
+         printf("(pmap_copy_on_write :%x) phys addr 0x%x not managed \n", curproc, phys);
+#endif
+       return;
+    }
+
+    SPLVM(spl);
+
+    pv_e = PFIDX_TO_PVH(PFIDX(phys));
+    CHECK_PV_LIST(phys, pv_e, "pmap_copy_on_write before");
+    if (pv_e->pmap  == PMAP_NULL) {
+
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_COW | CD_NORM)) == (CD_COW | CD_NORM))
+         printf("(pmap_copy_on_write :%x) phys addr 0x%x not mapped\n", curproc, phys);
+#endif
+
+       SPLX(spl);
+
+       return;         /* no mappings */
+    }
+
+    /*
+     * Run down the list of mappings to this physical page,
+     * disabling write privileges on each one.
+     */
+
+    while (pv_e != PV_ENTRY_NULL) {
+       pmap_t          pmap;
+       vm_offset_t     va;
+
+       pmap = pv_e->pmap;
+       va = pv_e->va;
+
+       users = 0;
+       if (pmap == kernel_pmap) {
+           kflush = 1;
+       } else {
+           kflush = 0;
+       }
+
+       /*
+        * Check for existing and valid pte
+        */
+       pte = pmap_pte(pmap, va);
+       if (pte == PT_ENTRY_NULL)
+           panic("pmap_copy_on_write: pte from pv_list not in map");
+       if (!PDT_VALID(pte))
+           panic("pmap_copy_on_write: invalid pte");
+       if (M88K_PTOB(pte->pfn) != phys)
+           panic("pmap_copy_on_write: pte doesn't point to page");
+
+       /*
+        * Flush TLBs of which cpus using pmap.
+        */
+
+       for (i = ptes_per_vm_page; i > 0; i--) {
+
+           /*
+            * Invalidate pte temporarily to avoid being written back
+            * the modified bit and/or the reference bit by other cpu.
+            */
+           spl_sav = splimp();
+           opte.bits = invalidate_pte(pte);
+           opte.pte.prot = M88K_RO;
+           ((pte_template_t *)pte)->bits = opte.bits;
+           flush_atc_entry(users, va, kflush);
+           splx(spl_sav);
+           pte++;
+           va += M88K_PGBYTES;
+       }
+
+       pv_e = pv_e->next;
+    }
+    CHECK_PV_LIST(phys, PFIDX_TO_PVH(PFIDX(phys)), "pmap_copy_on_write");
+
+    SPLX(spl);
+
+} /* pmap_copy_on_write */
+
+/*
+ * Routine:    PMAP_PROTECT
+ *
+ * Function:
+ *     Sets the physical protection on the specified range of this map
+ *     as requested.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *     s               start address of start of range
+ *     e               end address of end of range
+ *     prot            desired protection attributes
+ *
+ *     Calls:
+ *             m88k_protection
+ *             PMAP_LOCK, PMAP_UNLOCK
+ *             CHECK_PAGE_ALIGN
+ *             panic
+ *             pmap_pte
+ *             SDT_NEXT
+ *             PDT_VALID
+ *
+ *  This routine sequences through the pages of the specified range.
+ * For each, it calls pmap_pte to acquire a pointer to the page table
+ * entry (PTE). If the PTE is invalid, or non-existant, nothing is done.
+ * Otherwise, the PTE's protection attributes are adjusted as specified.
+ */
+void
+pmap_protect(pmap_t pmap, vm_offset_t s, vm_offset_t e, vm_prot_t prot)
+{
+    pte_template_t             maprot;
+    unsigned                   ap;
+    int                                spl, spl_sav;
+    register int               i;
+    pt_entry_t                 *pte;
+    vm_offset_t                        va, tva;
+    register unsigned          users;
+    register pte_template_t    opte;
+    int                                kflush;
+
+    if (pmap == PMAP_NULL || prot & VM_PROT_WRITE)
+       return;
+    if ((prot & VM_PROT_READ) == 0) {
+       pmap_remove(pmap, s, e);
+       return;
+    }
+    if (s > e)
+       panic("pmap_protect: start grater than end address");
+
+    maprot.bits = m88k_protection(pmap, prot);
+    ap = maprot.pte.prot;
+
+    PMAP_LOCK(pmap, spl);
+
+    if (pmap == kernel_pmap) {
+       kflush = 1;
+    } else {
+       kflush = 0;
+    }
+
+    CHECK_PAGE_ALIGN(s, "pmap_protect");
+
+    /*
+     * Loop through the range in vm_page_size increment.
+     * Do not assume that either start or end fall on any
+     * kind of page boundary (though this may be true ?!).
+     */
+    for (va = s; va <= e; va += PAGE_SIZE) {
+
+       pte = pmap_pte(pmap, va);
+
+       if (pte == PT_ENTRY_NULL) {
+
+           va &= SDT_MASK; /* align to segment */
+           if (va <= e - (1<<SDT_SHIFT))
+             va += (1<<SDT_SHIFT) - PAGE_SIZE; /* no page table, skip to next seg entry */
+           else /* wrap around */
+             break;
+           
+#ifdef DEBUG
+           if ((pmap_con_dbg & (CD_PROT | CD_FULL)) == (CD_PROT | CD_FULL))
+             printf("(pmap_protect :%x) no page table :: skip to 0x%x\n", curproc, va + PAGE_SIZE);
+#endif
+           continue;
+       }
+
+       if (!PDT_VALID(pte)) {
+#ifdef DEBUG
+           if ((pmap_con_dbg & (CD_PROT | CD_FULL)) == (CD_PROT | CD_FULL))
+             printf("(pmap_protect :%x) pte invalid pte @ 0x%x\n", curproc, pte);
+#endif
+           continue;                   /*  no page mapping */
+       }
+
+       tva = va;
+       for (i = ptes_per_vm_page; i>0; i--) {
+
+           /*
+            * Invalidate pte temporarily to avoid being written back
+            * the modified bit and/or the reference bit by other cpu.
+            */
+           spl_sav = splimp();
+           opte.bits = invalidate_pte(pte);
+           opte.pte.prot = ap;
+           ((pte_template_t *)pte)->bits = opte.bits;
+           flush_atc_entry(0, tva, kflush);
+           splx(spl_sav);
+           pte++;
+           tva += M88K_PGBYTES;
+       }
+    }
+
+    PMAP_UNLOCK(pmap, spl);
+
+} /* pmap_protect() */
+
+
+
+/*
+ * Routine:    PMAP_EXPAND
+ *
+ * Function:
+ *     Expands a pmap to be able to map the specified virtual address.
+ *     New kernel virtual memory is allocated for a page table
+ *
+ *     Must be called with the pmap system and the pmap unlocked, since
+ *     these must be unlocked to use vm_allocate or vm_deallocate (via
+ *     kmem_alloc, zalloc). Thus it must be called in a unlock/lock loop
+ *     that checks whether the map has been expanded enough. ( We won't loop
+ *     forever, since page table aren't shrunk.)
+ *
+ * Parameters:
+ *     map     point to map structure
+ *     v       VA indicating which tables are needed
+ *
+ * Extern/Global:
+ *     user_pt_map
+ *     kernel_pmap
+ *
+ * Calls:
+ *     pmap_pte
+ *     kmem_alloc
+ *     kmem_free
+ *     zalloc
+ *     zfree
+ *     pmap_extract
+ *
+ * Special Assumptions
+ *     no pmap locks held
+ *
+ * 1:  This routine immediately allocates space for a page table.
+ *
+ * 2:   The page table entries (PTEs) are initialized (set invalid), and
+ *     the corresponding segment table entry is set to point to the new
+ *     page table.
+ *
+ *
+ *     if (kernel_pmap)
+ *             pmap_expand_kmap()
+ *     ptva = kmem_alloc(user_pt_map)
+ *
+ */
+STATIC void
+pmap_expand(pmap_t map, vm_offset_t v)
+{
+       int             i,
+                       spl;
+       vm_offset_t     pdt_vaddr,
+                       pdt_paddr;
+
+       sdt_entry_t *sdt;
+       pt_entry_t              *pte;
+       vm_offset_t pmap_extract();
+
+       if (map == PMAP_NULL) {
+           panic("pmap_expand: pmap is NULL");
+       }
+
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_EXP | CD_NORM)) == (CD_EXP | CD_NORM))
+               printf ("(pmap_expand :%x) map %x v %x\n", curproc, map, v);
+#endif
+
+       CHECK_PAGE_ALIGN (v, "pmap_expand");
+
+       /*
+        * Handle kernel pmap in pmap_expand_kmap().
+        */
+       if (map == kernel_pmap) {
+               PMAP_LOCK(map, spl);
+               if (pmap_expand_kmap(v, VM_PROT_READ|VM_PROT_WRITE) == PT_ENTRY_NULL)
+                       panic ("pmap_expand: Cannot allocate kernel pte table");
+               PMAP_UNLOCK(map, spl);
+#ifdef DEBUG
+               if ((pmap_con_dbg & (CD_EXP | CD_FULL)) == (CD_EXP | CD_FULL))
+                       printf("(pmap_expand :%x) kernel_pmap\n", curproc);
+#endif
+               return;
+       }
+
+       /* XXX */
+#ifdef MACH_KERNEL
+        if (kmem_alloc_wired(kernel_map, &pdt_vaddr, PAGE_SIZE) != KERN_SUCCESS)
+          panic("pmap_enter: kmem_alloc failure");
+       pmap_zero_page(pmap_extract(kernel_pmap, pdt_vaddr));
+#else
+       pdt_vaddr = kmem_alloc (kernel_map, PAGE_SIZE);
+#endif
+
+       pdt_paddr = pmap_extract(kernel_pmap, pdt_vaddr);
+
+#if notneeded
+       /*
+        * the page for page tables should be CACHE DISABLED
+        */
+       pmap_cache_ctrl(kernel_pmap, pdt_vaddr, pdt_vaddr+PAGE_SIZE, CACHE_INH);
+#endif
+
+       PMAP_LOCK(map, spl);
+
+       if ((pte = pmap_pte(map, v)) != PT_ENTRY_NULL) {
+               /*
+                * Someone else caused us to expand
+                * during our vm_allocate.
+                */
+               PMAP_UNLOCK(map, spl);
+               /* XXX */
+               kmem_free (kernel_map, pdt_vaddr, PAGE_SIZE);
+#ifdef DEBUG
+               if (pmap_con_dbg & CD_EXP)
+                       printf("(pmap_expand :%x) table has already allocated\n", curproc);
+#endif
+               return;
+       }
+
+       /*
+        * Apply a mask to V to obtain the vaddr of the beginning of
+        * its containing page 'table group',i.e. the group of
+        * page  tables that fit eithin a single VM page.
+        * Using that, obtain the segment table pointer that references the
+        * first page table in the group, and initilize all the
+        * segment table descriptions for the page 'table group'.
+        */
+       v &= ~((1<<(LOG2_PDT_TABLE_GROUP_SIZE+PDT_BITS+PG_BITS))-1);
+
+       sdt = SDTENT(map,v);
+
+       /*
+        * Init each of the segment entries to point the freshly allocated
+        * page tables.
+        */
+
+       for (i = PDT_TABLE_GROUP_SIZE; i>0; i--) {
+               ((sdt_entry_template_t *)sdt)->bits = pdt_paddr | M88K_RW | DT_VALID;
+               ((sdt_entry_template_t *)(sdt + SDT_ENTRIES))->bits = pdt_vaddr | M88K_RW | DT_VALID;
+               sdt++;
+               pdt_paddr += PDT_SIZE;
+               pdt_vaddr += PDT_SIZE;
+       }
+
+       PMAP_UNLOCK(map, spl);
+
+} /* pmap_expand() */
+
+
+
+/*
+ * Routine:    PMAP_ENTER
+ *
+ *
+ * Update:
+ *     July 13,90 - JUemura
+ *             initial porting
+ *         *****TO CHECK*****
+ *              locks removed since we don't have to allocate
+ *             level 2 tables anymore. locks needed?
+ *     '90.7.26        Fuzzy   VM_MIN_KERNEL_ADDRESS -> VM_MAX_USER_ADDRESS
+ *     '90.8.17        Fuzzy   Debug message added(PV no mapped at VA)
+ *     '90.8.31        Sugai   Remove redundant message output
+ *
+ * Function:
+ *     Insert the given physical page (p) at the specified virtual
+ *     address (v) in the target phisical map with the protecton requested.
+ *     If specified, the page will be wired down, meaning that the
+ *     related pte can not be reclaimed.
+ *
+ * N.B.: This is only routine which MAY NOT lazy-evaluation or lose
+ *     information. That is, this routine must actually insert this page
+ *     into the given map NOW.
+ *
+ * Parameters:
+ *     pmap    pointer to pmap structure
+ *     va      VA of page to be mapped
+ *     pa      PA of page to be mapped
+ *     prot    protection attributes for page
+ *     wired   wired attribute for page
+ *
+ * Extern/Global:
+ *     pv_head_array, pv lists
+ *     pmap_modify_list
+ *
+ * Calls:
+ *     m88k_protection
+ *     pmap_pte
+ *     pmap_expand
+ *     pmap_remove_range
+ *     zfree
+ *
+ *     This routine starts off by calling pmap_pte to obtain a (virtual)
+ * pointer to the page table entry corresponding to given virtual
+ * address. If the page table itself does not exist, pmap_expand is
+ * called to allocate it.
+ *
+ *      If the page table entry (PTE) already maps the given physical page,
+ * all that is needed is to set the protection and wired attributes as
+ * given. TLB entries are flushed and pmap_enter returns.
+ *
+ *     If the page table entry (PTE) maps a different physical page than
+ * that given, the old mapping is removed by a call to map_remove_range.
+ * And execution of pmap_enter continues.
+ *
+ *     To map the new physical page, the routine first inserts a new
+ * entry in the PV list exhibiting the given pmap and virtual address.
+ * It then inserts the physical page address, protection attributes, and
+ * wired attributes into the page table entry (PTE).
+ *
+ *
+ *     get machine-dependent prot code
+ *     get the pte for this page
+ *     if necessary pmap expand(pmap,v)
+ *     if (changing wired attribute or protection) {
+ *             flush entry from TLB
+ *             update template
+ *             for (ptes per vm page)
+ *                     stuff pte
+ *     } else if (mapped at wrong addr)
+ *             flush entry from TLB
+ *             pmap_remove_range
+ *     } else {
+ *             enter mapping in pv_list
+ *             setup template and stuff ptes
+ *     }
+ *
+ */
+void
+pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa,
+                                       vm_prot_t prot, boolean_t wired)
+{
+    int                                ap;
+    int                                spl, spl_sav;
+    pv_entry_t                 pv_e;
+    pt_entry_t                 *pte;
+    vm_offset_t                        old_pa;
+    pte_template_t             template;
+    register int               i;
+    int                                pfi;
+    pv_entry_t                 pvl;
+    register unsigned          users;
+    register pte_template_t    opte;
+    int                                kflush;
+
+    if (pmap == PMAP_NULL) {
+       panic("pmap_enter: pmap is NULL");
+    }
+
+    CHECK_PAGE_ALIGN (va, "pmap_entry - VA");
+    CHECK_PAGE_ALIGN (pa, "pmap_entry - PA");
+
+    /*
+     * Range check no longer use, since we use whole address space
+     */
+
+#ifdef DEBUG
+    if ((pmap_con_dbg & (CD_ENT | CD_NORM)) == (CD_ENT | CD_NORM)) {
+       if (pmap == kernel_pmap)
+         printf ("(pmap_enter :%x) pmap kernel va %x pa %x\n", curproc, va, pa);
+       else
+         printf ("(pmap_enter :%x) pmap %x  va %x pa %x\n", curproc, pmap, va, pa);
+    }
+#endif
+
+    ap = m88k_protection (pmap, prot);
+
+    /*
+     * Must allocate a new pvlist entry while we're unlocked;
+     * zalloc may cause pageout (which will lock the pmap system).
+     * If we determine we need a pvlist entry, we will unlock
+     * and allocate one. Then will retry, throwing away
+     * the allocated entry later (if we no longer need it).
+     */
+    pv_e = PV_ENTRY_NULL;
+  Retry:
+
+    PMAP_LOCK(pmap, spl);
+
+    /*
+     * Expand pmap to include this pte. Assume that
+     * pmap is always expanded to include enough M88K
+     * pages to map one VM page.
+     */
+    while ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL) {
+       /*
+        * Must unlock to expand the pmap.
+        */
+       PMAP_UNLOCK(pmap, spl);
+       pmap_expand(pmap, va);
+       PMAP_LOCK(pmap, spl);
+    }
+
+    /*
+     * Special case if the physical page is already mapped
+     * at this address.
+     */
+    old_pa = M88K_PTOB(pte->pfn);
+    if (old_pa == pa) {
+
+       users = 0;
+       if (pmap == kernel_pmap) {
+           kflush = 1;
+       } else {
+           kflush = 0;
+       }
+       
+       /*
+        * May be changing its wired attributes or protection
+        */
+
+       if (wired && !pte->wired)
+         pmap->stats.wired_count++;
+       else if (!wired && pte->wired)
+         pmap->stats.wired_count--;
+
+       if ((unsigned long)pa >= MAXPHYSMEM)
+           template.bits = DT_VALID | ap | M88K_TRUNC_PAGE(pa) | CACHE_INH;
+       else
+           template.bits = DT_VALID | ap | M88K_TRUNC_PAGE(pa) | CACHE_GLOBAL;
+       if (wired)
+         template.pte.wired = 1;
+
+       /*
+        * If there is a same mapping, we have nothing to do.
+        */
+       if ( !PDT_VALID(pte) || (pte->wired != template.pte.wired)
+           || (pte->prot != template.pte.prot)) {
+
+           for (i = ptes_per_vm_page; i>0; i--) {
+               
+               /*
+                * Invalidate pte temporarily to avoid being written back
+                * the modified bit and/or the reference bit by other cpu.
+                */
+               spl_sav = splimp();
+               opte.bits = invalidate_pte(pte);
+               template.pte.modified = opte.pte.modified;
+               *pte++ = template.pte;
+               flush_atc_entry(users, va, kflush);
+               splx(spl_sav);
+               template.bits += M88K_PGBYTES;
+               va += M88K_PGBYTES;
+           }
+       }
+       
+    } else { /* if ( pa == old_pa) */
+
+       /*
+        * Remove old mapping from the PV list if necessary.
+        */
+       if (old_pa != (vm_offset_t)-1) {
+           /*
+            *  Invalidate the translation buffer,
+            *  then remove the mapping.
+            */
+#ifdef DEBUG
+               if ((pmap_con_dbg & (CD_ENT | CD_NORM)) == (CD_ENT | CD_NORM)) {
+                       if (va == phys_map_vaddr1 || va == phys_map_vaddr2) {
+                               printf("vaddr1 0x%x vaddr2 0x%x va 0x%x pa 0x%x managed %x\n", 
+                               phys_map_vaddr1, phys_map_vaddr2, va, old_pa,
+                                       PMAP_MANAGED(pa) ? 1 : 0);
+                               printf("pte %x pfn %x valid %x\n",
+                                       pte, pte->pfn, pte->dtype);
+                       }
+               }
+#endif
+               if (va == phys_map_vaddr1 || va == phys_map_vaddr2) {
+                       flush_atc_entry(0, va, 1);
+               } else {
+                       pmap_remove_range(pmap, va, va + PAGE_SIZE);
+               }
+       }
+
+       if (PMAP_MANAGED(pa)) {
+#ifdef DEBUG
+               if ((pmap_con_dbg & (CD_ENT | CD_NORM)) == (CD_ENT | CD_NORM)) {
+                       if (va == phys_map_vaddr1 || va == phys_map_vaddr2) {
+                               printf("va 0x%x and managed pa 0x%x\n", va, pa);
+                       }
+               }
+#endif
+           /*
+            *  Enter the mappimg in the PV list for this
+            *  physical page.
+            */
+           pfi = PFIDX(pa);
+           pvl = PFIDX_TO_PVH(pfi);
+           CHECK_PV_LIST (pa, pvl, "pmap_enter before");
+
+           if (pvl->pmap == PMAP_NULL) {
+
+               /*
+                *      No mappings yet
+                */
+               pvl->va = va;
+               pvl->pmap = pmap;
+               pvl->next = PV_ENTRY_NULL;
+
+           } else {
+#ifdef DEBUG
+               /*
+                * check that this mapping is not already there
+                */
+               {
+                   pv_entry_t e = pvl;
+                   while (e != PV_ENTRY_NULL) {
+                       if (e->pmap == pmap && e->va == va)
+                         panic ("pmap_enter: already in pv_list");
+                       e = e->next;
+                   }
+               }
+#endif
+               /*
+                *      Add new pv_entry after header.
+                */
+               if (pv_e == PV_ENTRY_NULL) {
+                   PMAP_UNLOCK(pmap, spl);
+                   pv_e = (pv_entry_t) malloc(sizeof *pv_e, M_VMPVENT,
+                               M_NOWAIT);
+                   goto Retry;
+               }
+               pv_e->va = va;
+               pv_e->pmap = pmap;
+               pv_e->next = pvl->next;
+               pvl->next = pv_e;
+               /*
+                *              Remeber that we used the pvlist entry.
+                */
+               pv_e = PV_ENTRY_NULL;
+           }
+       }
+
+       /*
+        * And count the mapping.
+        */
+       pmap->stats.resident_count++;
+       if (wired)
+         pmap->stats.wired_count++;
+
+       if ((unsigned long)pa >= MAXPHYSMEM)
+           template.bits = DT_VALID | ap | M88K_TRUNC_PAGE(pa) | CACHE_INH;
+       else
+           template.bits = DT_VALID | ap | M88K_TRUNC_PAGE(pa) | CACHE_GLOBAL;
+
+       if (wired)
+         template.pte.wired = 1;
+
+       DO_PTES (pte, template.bits);
+
+    } /* if ( pa == old_pa ) ... else */
+
+    PMAP_UNLOCK(pmap, spl);
+
+    if (pv_e != PV_ENTRY_NULL)
+      free((caddr_t) pv_e, M_VMPVENT);
+
+} /* pmap_enter */
+
+
+
+/*
+ *     Routine:        pmap_change_wiring
+ *
+ *     Author:         Fuzzy
+ *
+ *     Function:       Change the wiring attributes for a map/virtual-address
+ *                     Pair.
+ *     Prameterts:
+ *             pmap            pointer to pmap structure
+ *             v               virtual address of page to be wired/unwired
+ *             wired           flag indicating new wired state
+ *
+ *     Extern/Global:
+ *             pte_per_vm_page
+ *
+ *     Calls:
+ *             PMAP_LOCK, PMAP_UNLOCK
+ *             pmap_pte
+ *             panic
+ *
+ *     Special Assumptions:
+ *             The mapping must already exist in the pmap.
+ */
+void
+pmap_change_wiring(pmap_t map, vm_offset_t v, boolean_t wired)
+{
+       pt_entry_t      *pte;
+       int             i;
+       int             spl;
+
+       PMAP_LOCK(map, spl);
+
+       if ((pte = pmap_pte(map, v)) == PT_ENTRY_NULL)
+               panic ("pmap_change_wiring: pte missing");
+
+       if (wired && !pte->wired)
+               /*
+                *      wiring mapping
+                */
+               map->stats.wired_count++;
+
+       else if (!wired && pte->wired)
+               /*
+                *      unwired mapping
+                */
+               map->stats.wired_count--;
+
+       for (i = ptes_per_vm_page; i>0; i--)
+               (pte++)->wired = wired;
+
+       PMAP_UNLOCK(map, spl);
+
+} /* pmap_change_wiring() */
+
+
+
+/*
+ * Routine:    PMAP_EXTRACT
+ *
+ * Author:     Fuzzy
+ *
+ * Function:
+ *     Extract the physical page address associoated
+ *     with the given map/virtual_address pair.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *     va              virtual address
+ *
+ * Calls:
+ *     PMAP_LOCK, PMAP_UNLOCK
+ *     pmap_pte
+ *
+ *
+ *     This routine checks BATC mapping first. BATC has been used and 
+ * the specified pmap is kernel_pmap, batc_entry is scanned to find out
+ * the mapping. 
+ *     Then the routine calls pmap_pte to get a (virtual) pointer to
+ * the page table entry (PTE) associated with the given virtual
+ * address. If the page table does not exist, or if the PTE is not valid,
+ * then 0 address is returned. Otherwise, the physical page address from
+ * the PTE is returned.
+ */
+vm_offset_t
+pmap_extract(pmap_t pmap, vm_offset_t va)
+{
+    register pt_entry_t         *pte;
+    register vm_offset_t pa;
+    register int        i;
+    int                         spl;
+    
+    if (pmap == PMAP_NULL)
+       panic("pmap_extract: pmap is NULL");
+    
+    /*
+     * check BATC first
+     */
+    if (pmap == kernel_pmap && batc_used > 0)
+       for (i = batc_used-1; i > 0; i--)
+           if (batc_entry[i].lba == M88K_BTOBLK(va)) {
+               pa = (batc_entry[i].pba << BATC_BLKSHIFT) | (va & BATC_BLKMASK );
+               return(pa);
+           }
+
+    PMAP_LOCK(pmap, spl);
+    
+    if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL)
+       pa = (vm_offset_t) 0;
+    else {
+       if (PDT_VALID(pte))
+           pa = M88K_PTOB(pte->pfn);
+       else
+           pa = (vm_offset_t) 0;
+    }
+    
+    if (pa)
+       pa |= (va & M88K_PGOFSET);      /* offset within page */
+
+    PMAP_UNLOCK(pmap, spl);
+    
+#if 0
+    printf("pmap_extract ret %x\n", pa);
+#endif /* 0 */
+    return(pa);
+    
+} /* pamp_extract() */
+
+/*
+  a version for the kernel debugger 
+*/
+
+vm_offset_t
+pmap_extract_unlocked(pmap_t pmap, vm_offset_t va)
+{
+    pt_entry_t *pte;
+    vm_offset_t        pa;
+    int                i;
+    
+    if (pmap == PMAP_NULL)
+       panic("pmap_extract: pmap is NULL");
+    
+    /*
+     * check BATC first
+     */
+    if (pmap == kernel_pmap && batc_used > 0)
+       for (i = batc_used-1; i > 0; i--)
+           if (batc_entry[i].lba == M88K_BTOBLK(va)) {
+               pa = (batc_entry[i].pba << BATC_BLKSHIFT) | (va & BATC_BLKMASK );
+               return(pa);
+           }
+
+    if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL)
+       pa = (vm_offset_t) 0;
+    else {
+       if (PDT_VALID(pte))
+           pa = M88K_PTOB(pte->pfn);
+       else
+           pa = (vm_offset_t) 0;
+    }
+    
+    if (pa)
+       pa |= (va & M88K_PGOFSET);      /* offset within page */
+
+    return(pa);
+    
+} /* pamp_extract_unlocked() */
+
+
+/*
+ *     Routine:        PMAP_COPY
+ *
+ *     Function:
+ *             Copy the range specigfied by src_adr/len from the source map
+ *             to the range dst_addr/len in the destination map. This routine
+ *             is only advisory and need not do anything.
+ *
+ *     Parameters:
+ *             dst_pmap        pointer to destination  pmap structure
+ *             src_pmap        pointer to source pmap structure
+ *             dst_addr        VA in destionation map
+ *             len             length of address space being copied
+ *             src_addr        VA in source map
+ *
+ *     At this time, the 88200 pmap implementation does nothing in this
+ * function. Translation tables in the destination map will be allocated
+ * at VM fault time.
+ */
+void
+pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
+                               vm_size_t len, vm_offset_t src_addr)
+{
+#ifdef        lint
+      dst_pmap++; src_pmap++; dst_addr++; len++; src_addr++;
+#endif
+
+
+}/* pmap_copy() */
+
+
+/*
+ * Routine:    PMAP_UPDATE
+ *
+ * Function:
+ *     Require that all active physical maps contain no incorrect entries
+ *     NOW. [This update includes forcing updates of any address map
+ *     cashing]
+ *     Generally used to ensure that thread about to run will see a
+ *     semantically correct world.
+ *
+ * Parameters:
+ *     none
+ *
+ * Call:
+ *     cmmuflush
+ *
+ *     The 88200 pmap implementation does not defer any operations.
+ * Therefore, the translation table trees are always consistent while the
+ * pmap lock is not held. Therefore, there is really no work to do in
+ * this function other than to flush the TLB.
+ */
+void
+pmap_update(void)
+{
+#ifdef DBG
+    if ((pmap_con_dbg & (CD_UPD | CD_FULL)) == (CD_UPD | CD_FULL))
+       printf("(pmap_update :%x) Called \n", curproc);
+#endif
+
+}/* pmap_update() */
+
+
+
+/*
+ * Routine:    PMAP_COLLECT
+ *
+ * Runction:
+ *     Garbage collects the physical map system for pages which are
+ *     no longer used. there may well be pages which are not
+ *     referenced, but others may be collected as well.
+ *     Called by the pageout daemon when pages are scarce.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *
+ * Calls:
+ *     CHECK_PMAP_CONSISTENCY
+ *     panic
+ *     PMAP_LOCK, PMAP_UNLOCK
+ *     PT_FREE
+ *     pmap_pte
+ *     pmap_remove_range
+ *
+ *     The intent of this routine is to release memory pages being used
+ * by translation tables. They can be release only if they contain no
+ * valid mappings, and their parent table entry has been invalidated.
+ *
+ *     The routine sequences through the entries user address space,
+ * inspecting page-sized groups of page tables for wired entries. If
+ * a full page of tables has no wired enties, any otherwise valid
+ * entries are invalidated (via pmap_remove_range). Then, the segment
+ * table entries corresponding to this group of page tables are
+ * invalidated. Finally, PT_FREE is called to return the page to the
+ * system.
+ *
+ *     If all entries in a segment table are invalidated, it too can
+ * be returned to the system.
+ *
+ *     [Note: depending upon compilation options, tables may be in zones
+ * or allocated through kmem_alloc. In the former case, the
+ * module deals with a single table at a time.]
+ */
+void
+pmap_collect(pmap_t pmap)
+{
+
+    vm_offset_t                sdt_va; /* outer loop index */
+    vm_offset_t                sdt_vt; /* end of segment */
+    sdt_entry_t        *sdttbl;        /* ptr to first entry in the segment table */
+    sdt_entry_t        *sdtp;          /* ptr to index into segment table */
+    sdt_entry_t        *sdt;           /* ptr to index into segment table */
+    pt_entry_t *gdttbl;        /* ptr to first entry in a page table */
+    pt_entry_t *gdttblend;     /* ptr to byte after last entry in table group */
+    pt_entry_t *gdtp;          /* ptr to index into a page table */
+    boolean_t  found_gdt_wired; /* flag indicating a wired page exists in */
+                                /* a page table's address range           */
+    int                spl;
+    unsigned int i,j;
+
+
+
+    if (pmap == PMAP_NULL) {
+       panic("pmap_collect: pmap is NULL");
+    }
+    if (pmap == kernel_pmap) {
+#ifdef MACH_KERNEL
+       return;
+#else
+       panic("pmap_collect attempted on kernel pmap");
+#endif
+    }
+    
+    CHECK_PMAP_CONSISTENCY ("pmap_collect");
+
+#if    DBG
+    if ((pmap_con_dbg & (CD_COL | CD_NORM)) == (CD_COL | CD_NORM))
+      printf ("(pmap_collect :%x) pmap %x\n", curproc, pmap);
+#endif
+
+    PMAP_LOCK(pmap, spl);
+
+    sdttbl = pmap->sdt_vaddr;  /* addr of segment table */
+    sdtp = sdttbl;
+
+    /* 
+      This contortion is here instead of the natural loop 
+      because of integer overflow/wraparound if VM_MAX_USER_ADDRESS is near 0xffffffff
+    */
+
+    i = VM_MIN_USER_ADDRESS / PDT_TABLE_GROUP_VA_SPACE;
+    j = VM_MAX_USER_ADDRESS / PDT_TABLE_GROUP_VA_SPACE;
+    if ( j < 1024 ) j++;
+
+    /* Segment table loop */
+    for ( ; i < j; i++, sdtp += PDT_TABLE_GROUP_SIZE)
+      {
+       sdt_va = VM_MIN_USER_ADDRESS + PDT_TABLE_GROUP_VA_SPACE*i;
+
+       gdttbl = pmap_pte(pmap, (vm_offset_t)sdt_va);
+
+       if (gdttbl == PT_ENTRY_NULL)
+         continue;     /* no maps in this range */
+
+       gdttblend = gdttbl + (PDT_ENTRIES * PDT_TABLE_GROUP_SIZE);
+
+       /* scan page maps for wired pages */
+       found_gdt_wired = FALSE;
+       for (gdtp=gdttbl; gdtp <gdttblend; gdtp++) {
+           if (gdtp->wired) {
+               found_gdt_wired = TRUE;
+               break;
+           }
+       }
+
+       if (found_gdt_wired)
+         continue;     /* can't free this range */
+
+       /* figure out end of range. Watch for wraparound */
+
+       sdt_vt = sdt_va <= VM_MAX_USER_ADDRESS-PDT_TABLE_GROUP_VA_SPACE ?
+                sdt_va+PDT_TABLE_GROUP_VA_SPACE : 
+                VM_MAX_USER_ADDRESS;
+
+       /* invalidate all maps in this range */
+       pmap_remove_range (pmap, (vm_offset_t)sdt_va, (vm_offset_t)sdt_vt);
+
+       /*
+        * we can safely deallocated the page map(s)
+        */
+       for (sdt = sdtp; sdt < (sdtp+PDT_TABLE_GROUP_SIZE); sdt++) {
+           ((sdt_entry_template_t *) sdt) -> bits = 0;
+           ((sdt_entry_template_t *) sdt+SDT_ENTRIES) -> bits = 0;
+       }
+
+       /*
+        * we have to unlock before freeing the table, since PT_FREE
+        * calls kmem_free or zfree, which will invoke another pmap routine
+        */
+       PMAP_UNLOCK(pmap, spl);
+       PT_FREE(gdttbl);
+       PMAP_LOCK(pmap, spl);
+
+    } /* Segment table Loop */
+
+    PMAP_UNLOCK(pmap, spl);
+
+#if    DBG
+    if ((pmap_con_dbg & (CD_COL | CD_NORM)) == (CD_COL | CD_NORM))
+      printf  ("(pmap_collect :%x) done \n", curproc);
+#endif
+
+    CHECK_PMAP_CONSISTENCY("pmap_collect");
+} /* pmap collect() */
+
+
+
+/*
+ *     Routine:        PMAP_ACTIVATE
+ *
+ *     Function:
+ *             Binds the given physical map to the given
+ *             processor, and returns a hardware map description.
+ *             In a mono-processor implementation the my_cpu
+ *             argument is ignored, and the PMAP_ACTIVATE macro
+ *             simply sets the MMU root pointer element of the PCB
+ *             to the physical address of the segment descriptor table.
+ *
+ *     Parameters:
+ *             pmap            pointer to pmap structure
+ *             pcbp            pointer to current pcb
+ *             cpu             CPU number
+ */
+void
+pmap_activate(pmap_t pmap, pcb_t pcb)
+{
+#ifdef lint
+       my_cpu++;
+#endif
+       PMAP_ACTIVATE(pmap, pcb, 0);
+} /* pmap_activate() */
+
+
+
+/*
+ *     Routine:        PMAP_DEACTIVATE
+ *
+ *     Function:
+ *             Unbinds the given physical map from the given processor,
+ *             i.e. the pmap i no longer is use on the processor.
+ *             In a mono-processor the PMAP_DEACTIVATE macro is null.
+ *
+ *     Parameters:
+ *             pmap            pointer to pmap structure
+ *             pcb             pointer to pcb
+ */
+void
+pmap_deactivate(pmap_t pmap, pcb_t pcb)
+{
+#ifdef lint
+       pmap++; th++; which_cpu++;
+#endif
+       PMAP_DEACTIVATE(pmap, pcb, 0);
+} /* pmap_deactivate() */
+
+
+
+/*
+ *     Routine:        PMAP_KERNEL
+ *
+ *     Function:
+ *             Retruns a pointer to the kernel pmap.
+ */
+pmap_t
+pmap_kernel(void)
+{
+       return (kernel_pmap);
+}/* pmap_kernel() */
+
+
+/*
+ *     Routine:        PMAP_COPY_PAGE
+ *
+ *     Function:
+ *             Copies the specified (machine independent) pages.
+ *
+ *     Parameters:
+ *             src             PA of source page
+ *             dst             PA of destination page
+ *
+ *     Extern/Global:
+ *             phys_map_vaddr1
+ *             phys_map_vaddr2
+ *
+ *     Calls:
+ *             m88kprotection
+ *             M88K_TRUNC_PAGE
+ *             cmmu_sflush_page
+ *             DO_PTES
+ *             bcopy
+ *
+ *     Special Assumptions:
+ *             no locking reauired
+ *
+ *     This routine maps the phsical pages at the 'phys_map' virtual
+ * addresses set up in pmap_bootstrap. It flushes the TLB to make the
+ * new mappings effective, and performs the copy.
+ */
+void
+pmap_copy_page(vm_offset_t src, vm_offset_t dst)
+{
+       vm_offset_t     dstva, srcva;
+       unsigned int spl_sav;
+       int i;
+       int             aprot;
+       pte_template_t  template;
+       pt_entry_t      *dstpte, *srcpte;
+       int             my_cpu = cpu_number();
+
+       /*
+        *      Map source physical address.
+        */
+       aprot = m88k_protection (kernel_pmap, VM_PROT_READ | VM_PROT_WRITE);
+
+       srcva = (vm_offset_t)(phys_map_vaddr1 + (cpu_number() * PAGE_SIZE));
+       dstva = (vm_offset_t)(phys_map_vaddr2 + (cpu_number() * PAGE_SIZE));
+
+       srcpte = pmap_pte(kernel_pmap, srcva);
+       dstpte = pmap_pte(kernel_pmap, dstva);
+
+       for (i=0; i < ptes_per_vm_page; i++, src += M88K_PGBYTES, dst += M88K_PGBYTES)
+         {
+           template.bits = M88K_TRUNC_PAGE(src) | aprot | DT_VALID | CACHE_GLOBAL;
+
+           /* do we need to write back dirty bits */
+           spl_sav = splimp();
+           cmmu_flush_tlb(1, srcva, M88K_PGBYTES);
+           *srcpte = template.pte;
+
+           /*
+            *  Map destination physical address.
+            */
+           template.bits = M88K_TRUNC_PAGE(dst) | aprot | CACHE_GLOBAL | DT_VALID;
+           cmmu_flush_tlb(1, dstva, M88K_PGBYTES);
+           *dstpte  = template.pte;
+           splx(spl_sav);
+
+           bcopy((void*)srcva, (void*)dstva, M88K_PGBYTES);
+           /* flush source, dest out of cache? */
+           cmmu_flush_remote_data_cache(my_cpu, src, M88K_PGBYTES);
+           cmmu_flush_remote_data_cache(my_cpu, dst, M88K_PGBYTES);
+         }
+
+} /* pmap_copy_page() */
+
+
+/*
+ *     copy_to_phys
+ *
+ *     Copy virtual memory to physical memory by mapping the physical
+ *     memory into virtual memory and then doing a virtual to virtual
+ *     copy with bcopy.
+ *
+ *     Parameters:
+ *             srcva           VA of source page
+ *             dstpa           PA of destination page
+ *             bytecount       copy byte size
+ *
+ *     Extern/Global:
+ *             phys_map_vaddr2
+ *
+ *     Calls:
+ *             m88kprotection
+ *             M88K_TRUNC_PAGE
+ *             cmmu_sflush_page
+ *             DO_PTES
+ *             bcopy
+ *
+ */
+void
+copy_to_phys(vm_offset_t srcva, vm_offset_t dstpa, int bytecount)
+{
+    vm_offset_t        dstva;
+    pt_entry_t *dstpte;
+    int                copy_size,
+               offset,
+               aprot;
+    unsigned int i;
+    pte_template_t  template;
+
+    dstva = (vm_offset_t)(phys_map_vaddr2 + (cpu_number() * PAGE_SIZE));
+    dstpte = pmap_pte(kernel_pmap, dstva);
+    copy_size = M88K_PGBYTES;
+    offset = dstpa - M88K_TRUNC_PAGE(dstpa);
+    dstpa -= offset;
+
+    aprot = m88k_protection(kernel_pmap, VM_PROT_READ | VM_PROT_WRITE);
+    while (bytecount > 0){
+       copy_size = M88K_PGBYTES - offset;
+       if (copy_size > bytecount)
+         copy_size = bytecount;
+
+       /*
+        *      Map distation physical address. 
+        */
+
+       for (i = 0; i < ptes_per_vm_page; i++)
+         {
+           template.bits = M88K_TRUNC_PAGE(dstpa) | aprot | CACHE_WT | DT_VALID;
+           cmmu_flush_tlb(1, dstva, M88K_PGBYTES);
+           *dstpte = template.pte;
+
+           dstva += offset;
+           bcopy((void*)srcva, (void*)dstva, copy_size);
+           srcva += copy_size;
+           dstva += copy_size;
+           dstpa += M88K_PGBYTES;
+           bytecount -= copy_size;
+           offset = 0;
+         }
+      }
+}
+
+/*
+ *     copy_from_phys
+ *
+ *     Copy physical memory to virtual memory by mapping the physical
+ *     memory into virtual memory and then doing a virtual to virtual
+ *     copy with bcopy.
+ *
+ *     Parameters:
+ *             srcpa           PA of source page
+ *             dstva           VA of destination page
+ *             bytecount       copy byte size
+ *
+ *     Extern/Global:
+ *             phys_map_vaddr2
+ *
+ *     Calls:
+ *             m88kprotection
+ *             M88K_TRUNC_PAGE
+ *             cmmu_sflush_page
+ *             DO_PTES
+ *             bcopy
+ *
+ */
+void
+copy_from_phys(vm_offset_t srcpa, vm_offset_t dstva, int bytecount)
+{
+    register vm_offset_t       srcva;
+    register pt_entry_t        *srcpte;
+    register int               copy_size, offset;
+    int             aprot;
+    unsigned int i;
+    pte_template_t  template;
+
+    srcva = (vm_offset_t)(phys_map_vaddr2 + (cpu_number() * PAGE_SIZE));
+    srcpte = pmap_pte(kernel_pmap, srcva);
+    copy_size = M88K_PGBYTES;
+    offset = srcpa - M88K_TRUNC_PAGE(srcpa);
+    srcpa -= offset;
+
+    aprot = m88k_protection(kernel_pmap, VM_PROT_READ | VM_PROT_WRITE);
+    while (bytecount > 0){
+       copy_size = M88K_PGBYTES - offset;
+       if (copy_size > bytecount)
+         copy_size = bytecount;
+
+       /*
+        *      Map destnation physical address.
+        */
+
+       for (i=0; i < ptes_per_vm_page; i++)
+         {
+           template.bits = M88K_TRUNC_PAGE(srcpa) | aprot | CACHE_WT | DT_VALID;
+           cmmu_flush_tlb(1, srcva, M88K_PGBYTES);
+           *srcpte = template.pte;
+
+           srcva += offset;
+           bcopy((void*)srcva, (void*)dstva, copy_size);
+           srcpa += M88K_PGBYTES;
+           dstva += copy_size;
+           srcva += copy_size;
+           bytecount -= copy_size;
+           offset = 0;
+           /* cache flush source? */
+         }
+      }
+}
+
+/*
+ * Routine:    PMAP_PAGEABLE
+ *
+ * History:
+ *     '90.7.16        Fuzzy
+ *
+ * Function:
+ *     Make the specified pages (by pmap, offset) pageable (or not) as
+ *     requested. A page which is not pageable may not take a fault;
+ *     therefore, its page table entry must remain valid for the duration.
+ *     this routine is merely advisory; pmap_enter will specify that
+ *     these pages are to be wired down (or not) as appropriate.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *     start           virtual address of start of range
+ *     end             virtual address of end of range
+ *     pageable        flag indicating whether range is to be pageable.
+ *
+ *     This routine currently does nothing in the 88100 implemetation.
+ */
+void
+pmap_pageable(pmap_t pmap, vm_offset_t start, vm_offset_t end,
+                                                       boolean_t pageable)
+{
+#ifdef lint
+       pmap++; start++; end++; pageable++;
+#endif
+} /* pmap_pagealbe() */
+
+
+
+/*
+ * Routine:    PMAP_REDZONE
+ *
+ * Function:
+ *     Give the kernel read-only access to the specified address. This
+ *     is used to detect stack overflows. It is assumed that the address
+ *     specified is the last possible kernel stack address. Therefore, we
+ *     round up to the nearest machine dependent page.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap structure
+ *     addr            virtual address of page to which access should
+ *                     be restricted to read-only
+ *
+ * Calls:
+ *     M88K_ROUND_PAGE
+ *     PMAP_LOCK
+ *     pmap_pte
+ *     PDT_VALID
+ *
+ *     This function calls pmap_pte to obtain a pointer to the page
+ * table entry associated with the given virtual address. If there is a
+ * page entry, and it is valid, its write protect bit will be set.
+ */
+void
+pmap_redzone(pmap_t pmap, vm_offset_t va)
+{
+    pt_entry_t         *pte;
+    int                        spl, spl_sav;
+    int                        i;
+    unsigned           users;
+    pte_template_t     opte;
+    int                        kflush;
+
+    va = M88K_ROUND_PAGE(va);
+    PMAP_LOCK(pmap, spl);
+
+    users = 0;
+    if (pmap == kernel_pmap) {
+       kflush = 1;
+    } else {
+       kflush = 0;
+    }
+
+    if ((pte = pmap_pte(pmap, va)) != PT_ENTRY_NULL && PDT_VALID(pte))
+      for (i = ptes_per_vm_page; i > 0; i--) {
+
+         /*
+          * Invalidate pte temporarily to avoid being written back
+          * the modified bit and/or the reference bit by other cpu.
+          */
+         spl_sav = splimp();
+         opte.bits = invalidate_pte(pte);
+         opte.pte.prot = M88K_RO;
+         ((pte_template_t *)pte)->bits = opte.bits;
+         flush_atc_entry(users, va, kflush);
+         splx(spl_sav);
+         pte++;
+         va +=M88K_PGBYTES;
+      }
+
+    PMAP_UNLOCK(pmap, spl);
+
+} /* pmap_redzone() */
+
+
+
+/*
+ *     Routine:        PMAP_CLEAR_MODIFY
+ *
+ *     Function:
+ *             Clear the modify bits on the specified physical page.
+ *
+ *     Parameters:
+ *             phys    physical address of page
+ *
+ *     Extern/Global:
+ *             pv_head_table, pv_lists
+ *             pmap_modify_list
+ *
+ *     Calls:
+ *             PMAP_MANAGED
+ *             SPLVM, SPLX
+ *             PFIDX
+ *             PFIDX_TO_PVH
+ *             CHECK_PV_LIST
+ *             simple_lock, simple_unlock
+ *             pmap_pte
+ *             panic
+ *
+ *     For managed pages, the modify_list entry corresponding to the
+ * page's frame index will be zeroed. The PV list will be traversed.
+ * For each pmap/va the hardware 'modified' bit in the page descripter table
+ * entry inspected - and turned off if  necessary. If any of the
+ * inspected bits were found on, an TLB flush will be performed.
+ */
+void
+pmap_clear_modify(vm_offset_t phys)
+{
+    pv_entry_t         pvl;
+    int                        pfi;
+    pv_entry_t         pvep;
+    pt_entry_t         *pte;
+    pmap_t             pmap;
+    int                        spl, spl_sav;
+    vm_offset_t                va;
+    int                        i;
+    unsigned           users;
+    pte_template_t     opte;
+    int                        kflush;
+
+    if (!PMAP_MANAGED(phys)) {
+#ifdef DBG
+       if (pmap_con_dbg & CD_CMOD)
+         printf("(pmap_clear_modify :%x) phys addr 0x%x not managed \n", curproc, phys);
+#endif
+       return;
+    }
+
+    SPLVM(spl);
+
+clear_modify_Retry:
+    pfi = PFIDX(phys);
+    pvl = PFIDX_TO_PVH(pfi);
+    CHECK_PV_LIST (phys, pvl, "pmap_clear_modify");
+
+    /* update correspoinding pmap_modify_list element */
+    pmap_modify_list[pfi] = 0;
+
+    if (pvl->pmap == PMAP_NULL) {
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_CMOD | CD_NORM)) == (CD_CMOD | CD_NORM))
+         printf("(pmap_clear_modify :%x) phys addr 0x%x not mapped\n", curproc, phys);
+#endif
+
+       SPLX(spl);
+       return;
+    }
+
+    /* for each listed pmap, trun off the page modified bit */
+    pvep = pvl;
+    while (pvep != PV_ENTRY_NULL) {
+       pmap = pvep->pmap;
+       va = pvep->va;
+       if (!simple_lock_try(&pmap->lock)) {
+               goto clear_modify_Retry;
+       }
+
+       users = 0;
+       if (pmap == kernel_pmap) {
+           kflush = 1;
+       } else {
+           kflush = 0;
+       }
+
+       pte = pmap_pte(pmap, va);
+       if (pte == PT_ENTRY_NULL)
+         panic("pmap_clear_modify: bad pv list entry.");
+
+       for (i = ptes_per_vm_page; i > 0; i--) {
+
+           /*
+            * Invalidate pte temporarily to avoid being written back
+            * the modified bit and/or the reference bit by other cpu.
+            */
+           spl_sav = splimp();
+           opte.bits = invalidate_pte(pte);
+           /* clear modified bit */
+           opte.pte.modified = 0;
+           ((pte_template_t *)pte)->bits = opte.bits;
+           flush_atc_entry(users, va, kflush);
+           splx(spl_sav);
+           pte++;
+           va += M88K_PGBYTES;
+       }
+
+       simple_unlock(&pmap->lock);
+
+       pvep = pvep->next;
+    }
+
+    SPLX(spl);
+
+} /* pmap_clear_modify() */
+
+
+
+/*
+ *     Routine:        PMAP_IS_MODIFIED
+ *
+ *     Function:
+ *             Return whether or not the specified physical page is modified
+ *             by any physical maps. That is, whether the hardware has
+ *             stored data into the page.
+ *
+ *     Parameters:
+ *             phys            physical address og a page
+ *
+ *     Extern/Global:
+ *             pv_head_array, pv lists
+ *             pmap_modify_list
+ *
+ *     Calls:
+ *             simple_lock, simple_unlock
+ *             SPLVM, SPLX
+ *             PMAP_MANAGED
+ *             PFIDX
+ *             PFIDX_TO_PVH
+ *             pmap_pte
+ *
+ *     If the physical address specified is not a managed page, this
+ * routine simply returns TRUE (looks like it is returning FALSE XXX).
+ *
+ *     If the entry in the modify list, corresponding to the given page,
+ * is TRUE, this routine return TRUE. (This means at least one mapping
+ * has been invalidated where the MMU had set the modified bit in the
+ * page descripter table entry (PTE).
+ *
+ *     Otherwise, this routine walks the PV list corresponding to the
+ * given page. For each pmap/va pair, the page descripter table entry is
+ * examined. If a modified bit is found on, the function returns TRUE
+ * immediately (doesn't need to walk remainder of list).
+ */
+boolean_t
+pmap_is_modified(vm_offset_t phys)
+{
+       pv_entry_t      pvl;
+       int             pfi;
+       pv_entry_t      pvep;
+       pt_entry_t      *ptep;
+       int             spl;
+       int             i;
+       boolean_t       modified_flag;
+
+       if (!PMAP_MANAGED(phys)) {
+#ifdef DBG
+           if (pmap_con_dbg & CD_IMOD)
+               printf("(pmap_is_modified :%x) phys addr 0x%x not managed\n", curproc, phys);
+#endif
+               return(FALSE);
+       }
+
+       SPLVM(spl);
+
+       pfi = PFIDX(phys);
+       pvl = PFIDX_TO_PVH(pfi);
+       CHECK_PV_LIST (phys, pvl, "pmap_is_modified");
+is_mod_Retry:
+
+       if ((boolean_t) pmap_modify_list[pfi]) {
+               /* we've already cached a modify flag for this page,
+                       no use looking further... */
+#ifdef DBG
+           if ((pmap_con_dbg & (CD_IMOD | CD_NORM)) == (CD_IMOD | CD_NORM))
+               printf("(pmap_is_modified :%x) already cached a modify flag for this page\n", curproc);
+#endif
+               SPLX(spl);
+               return(TRUE);
+       }
+
+       if (pvl->pmap == PMAP_NULL) {
+               /* unmapped page - get info from page_modified array
+                       maintained by pmap_remove_range/ pmap_remove_all */
+               modified_flag = (boolean_t) pmap_modify_list[pfi];
+#ifdef DBG
+               if ((pmap_con_dbg & (CD_IMOD | CD_NORM)) == (CD_IMOD | CD_NORM))
+                 printf("(pmap_is_modified :%x) phys addr 0x%x not mapped\n", curproc, phys);
+#endif
+               SPLX(spl);
+               return(modified_flag);
+       }
+
+       /* for each listed pmap, check modified bit for given page */
+       pvep = pvl;
+       while (pvep != PV_ENTRY_NULL) {
+               if (!simple_lock_try(&pvep->pmap->lock)) {
+                       UNLOCK_PVH(pfi);
+                       goto is_mod_Retry;
+               }
+
+               ptep = pmap_pte(pvep->pmap, pvep->va);
+               if (ptep == PT_ENTRY_NULL) {
+                       printf("pmap_is_modified: pte from pv_list not in map virt = 0x%x\n", pvep->va);
+                       panic("pmap_is_modified: bad pv list entry");
+               }
+               for (i = ptes_per_vm_page; i > 0; i--) {
+                       if (ptep->modified) {
+                               simple_unlock(&pvep->pmap->lock);
+#ifdef DBG
+                               if ((pmap_con_dbg & (CD_IMOD | CD_FULL)) == (CD_IMOD | CD_FULL))
+                                 printf("(pmap_is_modified :%x) modified page pte@0x%x\n", curproc, (unsigned)ptep);
+#endif
+                               SPLX(spl);
+                               return(TRUE);
+                       }
+                       ptep++;
+               }
+               simple_unlock(&pvep->pmap->lock);
+
+               pvep = pvep->next;
+       }
+
+       SPLX(spl);
+       return(FALSE);
+
+} /* pmap_is_modified() */
+
+
+
+/*
+ *     Routine:        PMAP_CLEAR_REFERECE
+ *
+ *     History:
+ *             '90. 7.16       Fuzzy   unchanged
+ *             '90. 7.19       Fuzzy   comment "Calls:' add
+ *             '90. 8.21       Fuzzy   Debugging message add
+ *             '93. 3. 1       jfriedl Added call to LOCK_PVH
+ *
+ *     Function:
+ *             Clear the reference bits on the specified physical page.
+ *
+ *     Parameters:
+ *             phys            physical address of page
+ *
+ *     Calls:
+ *             PMAP_MANAGED
+ *             SPLVM, SPLX
+ *             PFIDX
+ *             PFIDX_TO_PVH
+ *             CHECK_PV_LIST
+ *             simple_lock
+ *             pmap_pte
+ *             panic
+ *
+ *     Extern/Global:
+ *             pv_head_array, pv lists
+ *
+ *     For managed pages, the coressponding PV list will be traversed.
+ * For each pmap/va the hardware 'used' bit in the page table entry
+ * inspected - and turned off if necessary. If any of the inspected bits
+ * werw found on, an TLB flush will be performed.
+ */
+void
+pmap_clear_reference(vm_offset_t phys)
+{
+    pv_entry_t         pvl;
+    int                        pfi;
+    pv_entry_t         pvep;
+    pt_entry_t         *pte;
+    pmap_t             pmap;
+    int                        spl, spl_sav;
+    vm_offset_t                va;
+    int                        i;
+    unsigned           users;
+    pte_template_t     opte;
+    int                        kflush;
+
+    if (!PMAP_MANAGED(phys)) {
+#ifdef DBG
+       if (pmap_con_dbg & CD_CREF) {
+           printf("(pmap_clear_reference :%x) phys addr 0x%x not managed\n", curproc,phys);
+       }
+#endif
+       return;
+    }
+
+    SPLVM(spl);
+
+clear_reference_Retry:
+    pfi = PFIDX(phys);
+    pvl = PFIDX_TO_PVH(pfi);
+    CHECK_PV_LIST(phys, pvl, "pmap_clear_reference");
+
+
+    if (pvl->pmap == PMAP_NULL) {
+#ifdef DBG
+       if ((pmap_con_dbg & (CD_CREF | CD_NORM)) == (CD_CREF | CD_NORM))
+         printf("(pmap_clear_reference :%x) phys addr 0x%x not mapped\n", curproc,phys);
+#endif
+       SPLX(spl);
+       return;
+    }
+
+    /* for each listed pmap, turn off the page refrenced bit */
+    pvep = pvl;
+    while (pvep != PV_ENTRY_NULL) {
+       pmap = pvep->pmap;
+       va = pvep->va;
+       if (!simple_lock_try(&pmap->lock)) {
+               goto clear_reference_Retry;
+       }
+
+       users = 0;
+       if (pmap == kernel_pmap) {
+           kflush = 1;
+       } else {
+           kflush = 0;
+       }
+
+       pte = pmap_pte(pmap, va);
+       if (pte == PT_ENTRY_NULL)
+         panic("pmap_clear_reference: bad pv list entry.");
+
+       for (i = ptes_per_vm_page; i > 0; i--) {
+
+           /*
+            * Invalidate pte temporarily to avoid being written back
+            * the modified bit and/or the reference bit by other cpu.
+            */
+           spl_sav = splimp();
+           opte.bits = invalidate_pte(pte);
+           /* clear reference bit */
+           opte.pte.pg_used = 0;
+           ((pte_template_t *)pte)->bits = opte.bits;
+           flush_atc_entry(users, va, kflush);
+           splx(spl_sav);
+           pte++;
+           va += M88K_PGBYTES;
+       }
+
+       simple_unlock(&pmap->lock);
+
+       pvep = pvep->next;
+    }
+
+    SPLX(spl);
+
+} /* pmap_clear_reference() */
+
+
+
+/*
+ * Routine:    PMAP_IS_REFERENCED
+ *
+ * History:
+ *     '90. 7.16       Fuzzy
+ *     '90. 7.19       Fuzzy   comment 'Calls:' add
+ *
+ * Function:
+ *     Retrun whether or not the specifeid physical page is referenced by
+ *     any physical maps. That is, whether the hardware has touched the page.
+ *
+ * Parameters:
+ *     phys            physical address of a page
+ *
+ * Extern/Global:
+ *     pv_head_array, pv lists
+ *
+ * Calls:
+ *     PMAP_MANAGED
+ *     SPLVM
+ *     PFIDX
+ *     PFIDX_TO_PVH
+ *     CHECK_PV_LIST
+ *     simple_lock
+ *     pmap_pte
+ *
+ *     If the physical address specified is not a managed page, this
+ * routine simply returns TRUE.
+ *
+ *     Otherwise, this routine walks the PV list corresponding to the
+ * given page. For each pmap/va/ pair, the page descripter table entry is
+ * examined. If a used bit is found on, the function returns TRUE
+ * immediately (doesn't need to walk remainder of list).
+ */
+boolean_t
+pmap_is_referenced(vm_offset_t phys)
+{
+    pv_entry_t pvl;
+    int                pfi;
+    pv_entry_t pvep;
+    pt_entry_t *ptep;
+    int                spl;
+    int                i;
+    
+    if (!PMAP_MANAGED(phys))
+      return(FALSE);
+    
+    SPLVM(spl);
+    
+    pfi = PFIDX(phys);
+    pvl = PFIDX_TO_PVH(pfi);
+    CHECK_PV_LIST(phys, pvl, "pmap_is_referenced");
+    
+is_ref_Retry:
+
+    if (pvl->pmap == PMAP_NULL) {
+       SPLX(spl);
+       return(FALSE);
+    }
+
+    /* for each listed pmap, check used bit for given page */
+    pvep = pvl;
+    while (pvep != PV_ENTRY_NULL) {
+       if (!simple_lock_try(&pvep->pmap->lock)) {
+               UNLOCK_PVH(pfi);
+               goto is_ref_Retry;
+       }
+
+       ptep = pmap_pte(pvep->pmap, pvep->va);
+       if (ptep == PT_ENTRY_NULL)
+         panic("pmap_is_referenced: bad pv list entry.");
+       for (i = ptes_per_vm_page; i > 0; i--) {
+           if (ptep->pg_used) {
+               simple_unlock(&pvep->pmap->lock);
+               SPLX(spl);
+               return(TRUE);
+           }
+           ptep++;
+       }
+       simple_unlock(&pvep->pmap->lock);
+
+       pvep = pvep->next;
+    }
+    
+    SPLX(spl);
+    return(FALSE);
+} /* pmap_is referenced() */
+
+/*
+ *     Routine:        PMAP_VERIFY_FREE
+ *
+ *     History:
+ *     '90. 7.17       Fuzzy   This routine extract vax's pmap.c.
+ *                             This do not exit in m68k's pmap.c.
+ *                             vm_page_alloc calls this.
+ *                             Variables changed below,
+ *                                     vm_first_phys --> pmap_phys_start
+ *                                     vm_last_phys  --> pmap_phys_end
+ *                             Macro chnged below,
+ *                                     pa_index   --> PFIDX
+ *                                     pai_to_pvh --> PFI_TO_PVH
+ *
+ *     Calls:
+ *             SPLVM, SPLX
+ *             PFIDX
+ *             PFI_TO_PVH
+ *
+ *     Global/Extern:
+ *             pmap_initialized
+ *             pmap_phys_start
+ *             pmap_phys_end
+ *             TRUE, FALSE
+ *             PMAP_NULL
+ *
+ *     This routine check physical address if that have pmap modules.
+ *     It returns TRUE/FALSE.
+ */
+
+boolean_t
+pmap_verify_free(vm_offset_t phys)
+{
+       pv_entry_t      pv_h;
+       int             spl;
+       boolean_t       result;
+
+       if (!pmap_initialized)
+               return(TRUE);
+
+       if (!PMAP_MANAGED(phys))
+               return(FALSE);
+
+       SPLVM(spl);
+
+       pv_h = PFIDX_TO_PVH(PFIDX(phys));
+
+       result = (pv_h->pmap == PMAP_NULL);
+       SPLX(spl);
+
+       return(result);
+
+} /* pmap_verify_free */
+
+
+/*
+ *     Routine:        PMAP_VALID_PAGE
+ *
+ *     The physical address space is dense... there are no holes.
+ *     All addresses provided to vm_page_startup() are valid.
+ */
+boolean_t
+pmap_valid_page(vm_offset_t p)
+{
+#ifdef lint
+       p++;
+#endif
+       return(TRUE);
+}      /* pmap_valid_page() */
+
+/*
+ * Routine:    PMAP_PAGE_PROTECT
+ *
+ * Calls:
+ *     pmap_copy_on_write
+ *     pmap_remove_all
+ *
+ *     Lower the permission for all mappings to a given page.
+ */
+void
+pmap_page_protect(vm_offset_t phys, vm_prot_t prot)
+{
+       switch (prot) {
+               case VM_PROT_READ:
+               case VM_PROT_READ|VM_PROT_EXECUTE:
+                       pmap_copy_on_write(phys);
+                       break;
+               case VM_PROT_ALL:
+                       break;
+               default:
+                       pmap_remove_all(phys);
+                       break;
+       }
+}
+
+#if FUTURE_MAYBE
+/*
+ * Routine:    PAGEMOVE
+ *
+ * Function:
+ *     Move pages from one kernel virtual address to another.
+ *
+ * Parameters:
+ *     from    kernel virtual address of source
+ *     to      kernel virtual address of distination
+ *     size    size in bytes
+ *
+ * Calls:
+ *     PMAP_LOCK
+ *     PMAP_UNLOCK
+ *     LOCK_PVH
+ *     UNLOCK_PVH
+ *     CHECK_PV_LIST
+ *     pmap_pte
+ *     pmap_expand_kmap
+ *     cmmu_sflush
+ *
+ * Special Assumptions:
+ *     size must be a multiple of CLBYTES (?)
+ */
+void
+pagemove(vm_offset_t from, vm_offset_t to, int size)
+{
+    vm_offset_t                pa;
+    pt_entry_t         *srcpte, *dstpte;
+    int                        pfi;
+    pv_entry_t         pvl;
+    int                        spl;
+    int                        i;
+    unsigned           users;
+    pte_template_t     opte;
+
+    PMAP_LOCK(kernel_pmap, spl);
+
+    users = 0;
+
+    while (size > 0) {
+
+       /*
+        * check if the source addr is mapped
+        */
+       if ((srcpte = pmap_pte(kernel_pmap, (vm_offset_t)from)) == PT_ENTRY_NULL) {
+           printf("pagemove: source vaddr 0x%x\n", from);
+           panic("pagemove: Source addr not mapped");
+       }
+
+       /*
+        *
+        */
+       if ((dstpte = pmap_pte(kernel_pmap, (vm_offset_t)to)) == PT_ENTRY_NULL)
+         if ((dstpte = pmap_expand_kmap((vm_offset_t)to, VM_PROT_READ | VM_PROT_WRITE))
+             == PT_ENTRY_NULL)
+           panic("pagemove: Cannot allocate distination pte");
+       /*
+        *
+        */
+       if (dstpte->dtype == DT_VALID) {
+           printf("pagemove: distination vaddr 0x%x, pte = 0x%x\n", to, *((unsigned *)dstpte));
+           panic("pagemove: Distination pte already valid");
+       }
+
+#ifdef DEBUG
+       if ((pmap_con_dbg & (CD_PGMV | CD_NORM)) == (CD_PGMV | CD_NORM))
+         printf("(pagemove :%x) from 0x%x to 0x%x\n", curproc, from, to);
+       if ((pmap_con_dbg & (CD_PGMV | CD_FULL)) == (CD_PGMV | CD_FULL))
+         printf("(pagemove :%x) srcpte @ 0x%x = %x dstpte @ 0x%x = %x\n", curproc, (unsigned)srcpte, *(unsigned *)srcpte, (unsigned)dstpte, *(unsigned *)dstpte);
+
+#endif /* DEBUG */
+
+       /*
+        * Update pv_list
+        */
+       pa = M88K_PTOB(srcpte->pfn);
+       if (PMAP_MANAGED(pa)) {
+           pfi = PFIDX(pa);
+           pvl = PFIDX_TO_PVH(pfi);
+           CHECK_PV_LIST(pa, pvl, "pagemove");
+           pvl->va = (vm_offset_t)to;
+       }
+
+       /*
+        * copy pte
+        */
+       for (i = ptes_per_vm_page; i > 0; i--) {
+           /*
+            * Invalidate pte temporarily to avoid being written back
+            * the modified bit and/or the reference bit by other cpu.
+            */
+           opte.bits = invalidate_pte(srcpte);
+           flush_atc_entry(users, from, 1);
+           ((pte_template_t *)dstpte)->bits = opte.bits;
+           from += M88K_PGBYTES;
+           to += M88K_PGBYTES;
+           srcpte++; dstpte++;
+       }
+       size -= PAGE_SIZE;
+    }
+
+    PMAP_UNLOCK(kernel_pmap, spl);
+
+} /* pagemove */
+
+#endif /* FUTURE_MAYBE */
+/*
+ *     Routine:        icache_flush
+ *
+ *     Function:
+ *             Invalidate instruction cache for all CPUs on specified
+ *             physical address.  Called when a page is removed from a
+ *             vm_map.  This is done because the Instruction CMMUs are not
+ *             snooped, and if a page is subsequently used as a text page,
+ *             we want the CMMUs to re-load the cache for the page.
+ *
+ *     Parameters:
+ *             pa      physical address of the (vm) page
+ *
+ *     Extern/globals:
+ *             ptes_per_vm_page
+ *
+ *     Calls:
+ *             cachefall
+ *
+ *     Called by:
+ *             vm_remove_page
+ *
+ */
+void
+icache_flush(vm_offset_t pa)
+{
+    int        i;
+    int        cpu = 0;
+
+    for (i = ptes_per_vm_page; i > 0; i--, pa += M88K_PGBYTES) {
+        cmmu_flush_remote_inst_cache(cpu, pa, M88K_PGBYTES);
+    }
+
+} /* icache_flush */
+
+/*
+ *     Routine:        pmap_dcache_flush
+ *
+ *     Function:
+ *             Flush DATA cache on specified virtual address.
+ *
+ *     Parameters:
+ *             pmap    specify pmap
+ *             va      virtual address of the (vm) page to be flushed
+ *
+ *     Extern/globals:
+ *             pmap_pte
+ *             ptes_per_vm_page
+ *
+ *     Calls:
+ *             dcacheflush
+ *
+ */
+void
+pmap_dcache_flush(pmap_t pmap, vm_offset_t va)
+{
+    vm_offset_t pa;
+    int        i;
+    int                spl;
+
+    if (pmap == PMAP_NULL)
+       panic("pmap_dcache_flush: pmap is NULL");
+
+    PMAP_LOCK(pmap, spl);
+
+    pa = M88K_PTOB((pmap_pte(pmap, va))->pfn);
+    for (i = ptes_per_vm_page; i > 0; i--, pa += M88K_PGBYTES) {
+       cmmu_flush_data_cache(pa, M88K_PGBYTES);
+    }
+
+    PMAP_UNLOCK(pmap, spl);
+
+
+} /* pmap_dcache_flush */
+
+STATIC void
+cache_flush_loop(int mode, vm_offset_t pa, int size)
+{
+    int                i;
+    int                ncpus;
+    void       (*cfunc)(int cpu, vm_offset_t physaddr, int size);
+
+    switch (mode) {
+    default:
+       panic("bad cache_flush_loop mode");
+       return;
+
+    case FLUSH_CACHE:  /* All caches, all CPUs */
+       ncpus = NCPUS;
+       cfunc = cmmu_flush_remote_cache;
+       break;
+
+    case FLUSH_CODE_CACHE:     /* Instruction caches, all CPUs */
+       ncpus = NCPUS;
+       cfunc = cmmu_flush_remote_inst_cache;
+       break;
+    
+    case FLUSH_DATA_CACHE:     /* Data caches, all CPUs */
+       ncpus = NCPUS;
+       cfunc = cmmu_flush_remote_data_cache;
+       break;
+
+    case FLUSH_LOCAL_CACHE:            /* Both caches, my CPU */
+       ncpus = 1;
+       cfunc = cmmu_flush_remote_cache;
+       break;
+    
+    case FLUSH_LOCAL_CODE_CACHE:       /* Instruction cache, my CPU */
+       ncpus = 1;
+       cfunc = cmmu_flush_remote_inst_cache;
+       break;
+
+    case FLUSH_LOCAL_DATA_CACHE:       /* Data cache, my CPU */
+       ncpus = 1;
+       cfunc = cmmu_flush_remote_data_cache;
+       break;
+    }
+
+    if (ncpus == 1) {
+       (*cfunc)(cpu_number(), pa, size);
+    }
+    else {
+       for (i=0; i<NCPUS; i++) {
+               (*cfunc)(i, pa, size);
+       }
+    }
+}
+
+/*
+ * pmap_cache_flush
+ *     Internal function.
+ */
+void
+pmap_cache_flush(pmap_t pmap, vm_offset_t virt, int bytes, int mode)
+{
+    vm_offset_t pa;
+    vm_offset_t va;
+    int        i;
+    int                spl;
+
+    if (pmap == PMAP_NULL)
+       panic("pmap_dcache_flush: NULL pmap");
+
+    /*
+     * If it is more than a couple of pages, just blow the whole cache
+     * because of the number of cycles involved.
+     */
+    if (bytes > 2*M88K_PGBYTES) {
+       cache_flush_loop(mode, 0, -1);
+       return;
+    }
+
+    PMAP_LOCK(pmap, spl);
+    for(va = virt; bytes > 0; bytes -= M88K_PGBYTES,va += M88K_PGBYTES) {
+        pa = M88K_PTOB((pmap_pte(pmap, va))->pfn);
+        for (i = ptes_per_vm_page; i > 0; i--, pa += M88K_PGBYTES) {
+           cache_flush_loop(mode, pa, M88K_PGBYTES);
+        }
+    }
+    PMAP_UNLOCK(pmap, spl);
+} /* pmap_cache_flush */
+
+#ifdef DEBUG
+/*
+ *  DEBUGGING ROUTINES - check_pv_list and check_pmp_consistency are used
+ *             only for debugging.  They are invoked only
+ *             through the macros CHECK_PV_LIST AND CHECK_PMAP_CONSISTENCY
+ *             defined early in this sourcefile.
+ */
+
+/*
+ *     Routine:        CHECK_PV_LIST (internal)
+ *
+ *     Function:
+ *             Debug-mode routine to check consistency of a PV list. First, it
+ *             makes sure every map thinks the physical page is the same. This
+ *             should be called by all routines which touch a PV list.
+ *
+ *     Parameters:
+ *             phys    physical address of page whose PV list is
+ *                     to be checked
+ *             pv_h    pointer to head to the PV list
+ *             who     string containing caller's name to be
+ *                     printed if a panic arises
+ *
+ *     Extern/Global:
+ *             pv_head_array, pv lists
+ *
+ *     Calls:
+ *             pmap_extract
+ *
+ *     Special Assumptions:
+ *             No locking is required.
+ *
+ *     This function walks the given PV list. For each pmap/va pair,
+ * pmap_extract is called to obtain the physical address of the page from
+ * the pmap in question. If the retruned physical address does not match
+ * that for the PV list being perused, the function panics.
+ */
+
+STATIC void
+check_pv_list(vm_offset_t phys, pv_entry_t pv_h, char *who)
+{
+       pv_entry_t      pv_e;
+       pt_entry_t      *pte;
+       vm_offset_t     pa;
+
+       if (pv_h != PFIDX_TO_PVH(PFIDX(phys))) {
+               printf("check_pv_list: incorrect pv_h supplied.\n");
+               panic(who);
+       }
+
+       if (!PAGE_ALIGNED(phys)) {
+               printf("check_pv_list: supplied phys addr not page aligned.\n");
+               panic(who);
+       }
+
+       if (pv_h->pmap == PMAP_NULL) {
+               if (pv_h->next != PV_ENTRY_NULL) {
+                       printf("check_pv_list: first entry has null pmap, but list non-empty.\n");
+                       panic(who);
+               }
+               else    return;         /* proper empry lst */
+       }
+
+       pv_e = pv_h;
+       while (pv_e != PV_ENTRY_NULL) {
+               if (!PAGE_ALIGNED(pv_e->va)) {
+                       printf("check_pv_list: non-aligned VA in entry at 0x%x.\n", pv_e);
+                       panic(who);
+               }
+               /*
+                * We can't call pmap_extract since it requires lock.
+                */
+               if ((pte = pmap_pte(pv_e->pmap, pv_e->va)) == PT_ENTRY_NULL)
+                 pa = (vm_offset_t)0;
+               else
+                 pa = M88K_PTOB(pte->pfn) | (pv_e->va & M88K_PGOFSET);
+
+               if (pa != phys) {
+                       printf("check_pv_list: phys addr diff in entry at 0x%x.\n", pv_e);
+                       panic(who);
+               }
+
+               pv_e = pv_e->next;
+       }
+
+} /* check_pv_list() */
+
+/*
+ *     Routine:        CHECK_MAP (itnernal)
+ *
+ *     Function:
+ *             Debug mode routine to check consistency of map.
+ *             Called by check_pmap_consistency only.
+ *
+ *     Parameters:
+ *             map     pointer to pmap structure
+ *             s       start of range to be checked
+ *             e       end of range to be checked
+ *             who     string containing caller's name to be
+ *                     printed if a panic arises
+ *
+ *     Extern/Global:
+ *             pv_head_array, pv lists
+ *
+ *     Calls:
+ *             pmap_pte
+ *
+ *     Special Assumptions:
+ *             No locking required.
+ *
+ *     This function sequences through the given range of  addresses. For
+ * each page, pmap_pte is called to obtain the page table entry. If
+ * its valid, and the physical page it maps is managed, the PV list is
+ * searched for the corresponding pmap/va entry. If not found, the
+ * function panics. If duplicate PV list entries are found, the function
+ * panics.
+ */
+
+STATIC void
+check_map(pmap_t map, vm_offset_t s, vm_offset_t e, char *who)
+{
+       vm_offset_t     va,
+                       old_va,
+                       phys;
+       pv_entry_t      pv_h,
+                       pv_e,
+                       saved_pv_e;
+       pt_entry_t      *ptep;
+       boolean_t       found;
+       int             loopcnt;
+
+
+       /*
+        * for each page in the address space, check to see if there's
+        * a valid mapping. If so makes sure it's listed in the PV_list.
+        */
+
+       if ((pmap_con_dbg & (CD_CHKM | CD_NORM)) == (CD_CHKM | CD_NORM))
+               printf("(check_map) checking map at 0x%x\n", map);
+
+       old_va = s;
+       for (va = s; va < e; va += PAGE_SIZE) {
+               /* check for overflow - happens if e=0xffffffff */
+               if (va < old_va)
+                       break;
+               else
+                       old_va = va;
+
+               if (va == phys_map_vaddr1 || va == phys_map_vaddr2)
+                       /* don't try anything with these */
+                       continue;
+
+               ptep = pmap_pte(map, va);
+
+               if (ptep == PT_ENTRY_NULL) {
+                       /* no page table, skip to next segment entry */
+                       va = SDT_NEXT(va)-PAGE_SIZE;
+                       continue;
+               }
+
+               if (!PDT_VALID(ptep))
+                       continue;               /* no page mapping */
+
+               phys = M88K_PTOB(ptep->pfn);    /* pick up phys addr */
+
+               if (!PMAP_MANAGED(phys))
+                       continue;               /* no PV list */
+
+               /* note: vm_page_startup allocates some memory for itself
+                       through pmap_map before pmap_init is run. However,
+                       it doesn't adjust the physical start of memory.
+                       So, pmap thinks those pages are managed - but they're
+                       not actually under it's control. So, the following
+                       conditional is a hack to avoid those addresses
+                       reserved by vm_page_startup */
+               /* pmap_init also allocate some memory for itself. */
+
+               if (map == kernel_pmap &&
+                   va < round_page((vm_offset_t)(pmap_modify_list + (pmap_phys_end - pmap_phys_start))))
+                       continue;
+
+               pv_h = PFIDX_TO_PVH(PFIDX(phys));
+               found = FALSE;
+
+               if (pv_h->pmap != PMAP_NULL) {
+
+                       loopcnt = 10000;        /* loop limit */
+                       pv_e = pv_h;
+                       while(pv_e != PV_ENTRY_NULL) {
+
+                               if (loopcnt-- < 0) {
+                                       printf("check_map: loop in PV list at PVH 0x%x (for phys 0x%x)\n", pv_h, phys);
+                                       panic(who);
+                               }
+
+                               if (pv_e->pmap == map && pv_e->va == va) {
+                                       if (found) {
+                                               printf("check_map: Duplicate PV list entries at 0x%x and 0x%x in PV list 0x%x.\n", saved_pv_e, pv_e, pv_h);
+                                               printf("check_map: for pmap 0x%x, VA 0x%x,phys 0x%x.\n", map, va, phys);
+                                               panic(who);
+                                       }
+                                       else {
+                                               found = TRUE;
+                                               saved_pv_e = pv_e;
+                                       }
+                               }
+                               pv_e = pv_e->next;
+                       }
+               }
+
+               if (!found) {
+                               printf("check_map: Mapping for pmap 0x%x VA 0x%x Phys 0x%x does not appear in PV list 0x%x.\n", map, va, phys, pv_h);
+               }
+       }
+
+       if ((pmap_con_dbg & (CD_CHKM | CD_NORM)) == (CD_CHKM | CD_NORM))
+               printf("(check_map) done \n");
+
+} /* check_map() */
+
+/*
+ *     Routine:        CHECK_PMAP_CONSISTENCY (internal)
+ *
+ *     Function:
+ *             Debug mode routine which walks all pmap, checking for internal
+ *             consistency. We are called UNLOCKED, so we'll take the write
+ *             lock.
+ *
+ *     Parameters:
+ *             who             string containing caller's name tobe
+ *                             printed if a panic arises
+ *
+ *     Extern/Global:
+ *             list of pmap structures
+ *
+ *     Calls:
+ *             check map
+ *             check pv_list
+ *
+ *     This function obtains the pmap write lock. Then, for each pmap
+ * structure in the pmap struct queue, it calls check_map to verify the
+ * consistency of its translation table hierarchy.
+ *
+ *     Once all pmaps have been checked, check_pv_list is called to check
+ * consistency of the PV lists for each managed page.
+ *
+ *     NOTE: Added by Sugai 10/29/90
+ *     There are some pages do not appaer in PV list. These pages are
+ * allocated for pv structures by kmem_alloc called in pmap_init.
+ * Though they are in the range of pmap_phys_start to pmap_phys_end,
+ * PV maniupulations had not been activated when these pages were alloceted.
+ *
+ */
+
+STATIC void
+check_pmap_consistency(char *who)
+{
+       pmap_t          p;
+       int             i;
+       vm_offset_t     phys;
+       pv_entry_t      pv_h;
+       int             spl;
+
+       if ((pmap_con_dbg & (CD_CHKPM | CD_NORM)) == (CD_CHKPM | CD_NORM))
+               printf("check_pmap_consistency (%s :%x) start.\n", who, curproc);
+
+       if (pv_head_table == PV_ENTRY_NULL) {
+
+               printf("check_pmap_consistency (%s) PV head table not initialized.\n", who);
+               return;
+       }
+
+       SPLVM(spl);
+
+       p = kernel_pmap;
+       check_map(p, VM_MIN_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS, who);
+
+       /* run through all pmaps. check consistency of each one... */
+       i = PMAP_MAX;
+       for (p = kernel_pmap->next;p != kernel_pmap; p = p->next) {
+               if (i == 0) { /* can not read pmap list */
+                       printf("check_pmap_consistency: pmap strcut loop error.\n");
+                       panic(who);
+               }
+               check_map(p, VM_MIN_USER_ADDRESS, VM_MAX_USER_ADDRESS, who);
+       }
+
+       /* run through all managed paes, check pv_list for each one */
+       for (phys = pmap_phys_start; phys < pmap_phys_end; phys += PAGE_SIZE) {
+               pv_h = PFIDX_TO_PVH(PFIDX(phys));
+               check_pv_list(phys, pv_h, who);
+       }
+
+       SPLX(spl);
+
+       if ((pmap_con_dbg & (CD_CHKPM | CD_NORM)) == (CD_CHKPM | CD_NORM))
+               printf("check_pmap consistency (%s :%x): done.\n",who, curproc);
+
+} /* check_pmap_consistency() */
+#endif /* DEBUG */
+
+/*
+ * PMAP PRINT MACROS AND ROUTINES FOR DEBUGGING
+ * These routines are called only from the debugger.
+ */
+
+#define        PRINT_SDT(p)                                                    \
+               printf("%08x : ",                                       \
+                       ((sdt_entry_template_t *)p)-> bits);            \
+               printf("table adress=0x%x, prot=%d, dtype=%d\n",        \
+                       M88K_PTOB(p->table_addr),                       \
+                       p->prot,                                        \
+                       p->dtype);
+
+#define        PRINT_PDT(p)                                                    \
+               printf("%08x : ",                                       \
+                       ((pte_template_t *)p)-> bits);                  \
+               printf("frame num=0x%x, prot=%d, dtype=%d, wired=%d, modified=%d, pg_used=%d\n",        \
+                       p->pfn,                                         \
+                       p->prot,                                        \
+                       p->dtype,                                       \
+                       p->wired,                                       \
+                       p->modified,                            \
+                       p->pg_used);
+
+/*
+ *     Routine:        PMAP_PRINT
+ *
+ *     History:
+ *
+ *     Function:
+ *             Print pmap stucture, including segment table.
+ *
+ *     Parameters:
+ *             pmap            pointer to pmap structure
+ *
+ *     Special Assumptions:
+ *             No locking required.
+ *
+ *     This function prints the fields of the pmap structure, then
+ * iterates through the segment translation table, printing each entry.
+ */
+void
+pmap_print(pmap_t pmap)
+{
+    sdt_entry_t        *sdtp;
+    sdt_entry_t        *sdtv;
+    int                i;
+
+    printf("Pmap @ 0x%x:\n", (unsigned)pmap);
+    sdtp = pmap->sdt_paddr;
+    sdtv = pmap->sdt_vaddr;
+    printf("   sdt_paddr: 0x%x; sdt_vaddr: 0x%x; ref_count: %d;\n",
+           (unsigned)sdtp, (unsigned)sdtv,
+           pmap->ref_count);
+
+#ifdef statistics_not_yet_maintained
+    printf("   statistics: pagesize %d: free_count %d; "
+          "active_count %d; inactive_count %d; wire_count %d\n",
+               pmap->stats.pagesize,
+               pmap->stats.free_count,
+               pmap->stats.active_count,
+               pmap->stats.inactive_count,
+               pmap->stats.wire_count);
+
+    printf("   zero_fill_count %d; reactiveations %d; "
+          "pageins %d; pageouts %d; faults %d\n",
+               pmap->stats.zero_fill_count,
+               pmap->stats.reactivations,
+               pmap->stats.pageins,
+               pmap->stats.pageouts,
+               pmap->stats.fault);
+
+    printf("   cow_faults %d, lookups %d, hits %d\n",
+               pmap->stats.cow_faults,
+               pmap->stats.loopups,
+               pmap->stats.faults);
+#endif
+
+    sdtp = (sdt_entry_t *) pmap->sdt_vaddr;    /* addr of physical table */
+    sdtv = sdtp + SDT_ENTRIES;         /* shadow table with virt address */
+    if (sdtp == (sdt_entry_t *)0)
+       printf("Error in pmap - sdt_paddr is null.\n");
+    else {
+       int     count = 0;
+       printf("        Segment table at 0x%x (0x%x):\n",
+           (unsigned)sdtp, (unsigned)sdtv);
+       for (i = 0; i < SDT_ENTRIES; i++, sdtp++, sdtv++) {
+           if ((sdtp->table_addr != 0 ) || (sdtv->table_addr != 0)) {
+               if (count != 0)
+                       printf("sdt entry %d skip !!\n", count);
+               count = 0;
+               printf("   (%x)phys: ", i);
+               PRINT_SDT(sdtp);
+               printf("   (%x)virt: ", i);
+               PRINT_SDT(sdtv);
+           }
+           else
+               count++;
+       }
+       if (count != 0)
+           printf("sdt entry %d skip !!\n", count);
+    }
+
+} /* pmap_print() */
+
+/*
+ * Routine:    PMAP_PRINT_TRACE
+ *
+ * Function:
+ *     Using virt addr, derive phys addr, printing pmap tables along the way.
+ *
+ * Parameters:
+ *     pmap            pointer to pmap strucuture
+ *     va              virtual address whose translation is to be trace
+ *     long_format     flag indicating long from output is desired
+ *
+ * Special Assumptions:
+ *     No locking required.
+ *
+ *     This function chases down through the translation tree as
+ * appropriate for the given virtual address. each table entry
+ * encoutered is printed. If the long_format is desired, all entries of
+ * each table are printed, with special indication of the entries used in
+ * the translation.
+ */
+void
+pmap_print_trace (pmap_t pmap, vm_offset_t va, boolean_t long_format)
+{
+    sdt_entry_t        *sdtp;  /* ptr to sdt table of physical addresses */
+    sdt_entry_t        *sdtv;  /* ptr to sdt shadow table of virtual addresses */
+    pt_entry_t *ptep;  /* ptr to pte table of physical page addresses */
+
+    int                i;      /* table loop index */
+    unsigned long prev_entry;  /* keep track of value of previous table entry */
+    int                n_dup_entries;  /* count contiguous duplicate entries */
+
+    printf("Trace of virtual address 0x%08x. Pmap @ 0x%08x.\n",
+       va, (unsigned)pmap);
+
+    /*** SDT TABLES ***/
+    /* get addrs of sdt tables */
+    sdtp = (sdt_entry_t *)pmap->sdt_vaddr;
+    sdtv = sdtp + SDT_ENTRIES;
+
+    if (sdtp == SDT_ENTRY_NULL) {
+       printf("    Segment table pointer (pmap.sdt_paddr) null, trace stops.\n");
+       return;
+    }
+
+    n_dup_entries = 0;
+    prev_entry = 0xFFFFFFFF;
+
+    if (long_format) {
+       printf("    Segment table at 0x%08x (virt shadow at 0x%08x)\n",
+               (unsigned)sdtp, (unsigned)sdtv);
+       for (i = 0; i < SDT_ENTRIES; i++, sdtp++, sdtv++) {
+           if (prev_entry == ((sdt_entry_template_t *)sdtp)->bits
+               && SDTIDX(va) != i && i != SDT_ENTRIES-1) {
+                   n_dup_entries++;
+                   continue;   /* suppress duplicate entry */
+           }
+           if (n_dup_entries != 0) {
+               printf("    - %d duplicate entries skipped -\n",n_dup_entries);
+               n_dup_entries = 0;
+           }
+           prev_entry = ((pte_template_t *)sdtp)->bits;
+           if (SDTIDX(va) == i) {
+               printf("    >> (%x)phys: ", i);
+           } else {
+               printf("       (%x)phys: ", i);
+           }
+           PRINT_SDT(sdtp);
+           if (SDTIDX(va) == i) {
+               printf("    >> (%x)virt: ", i);
+           } else {
+               printf("       (%x)virt: ", i);
+           }
+           PRINT_SDT(sdtv);
+       } /* for */
+    } else {
+       /* index into both tables for given VA */
+       sdtp += SDTIDX(va);
+       sdtv += SDTIDX(va);
+       printf("    SDT entry index 0x%x at 0x%x (virt shadow at 0x%x)\n",
+              SDTIDX(va), (unsigned)sdtp, (unsigned)sdtv);
+       printf("    phys:  ");
+       PRINT_SDT(sdtp);
+       printf("    virt:  ");
+       PRINT_SDT(sdtv);
+    }
+
+    /*** PTE TABLES ***/
+    /* get addrs of page (pte) table (no shadow table) */
+
+    sdtp = ((sdt_entry_t *)pmap->sdt_vaddr) + SDTIDX(va);
+    #ifdef DBG
+           printf("*** DEBUG (sdtp) ");
+           PRINT_SDT(sdtp);
+    #endif
+    sdtv = sdtp + SDT_ENTRIES;
+    ptep = (pt_entry_t *)(M88K_PTOB(sdtv->table_addr));
+    if (sdtp->dtype != DT_VALID) {
+       printf("    segment table entry invlid, trace stops.\n");
+       return;
+    }
+
+    n_dup_entries = 0;
+    prev_entry = 0xFFFFFFFF;
+    if (long_format) {
+       printf("        page table (ptes) at 0x%x\n", (unsigned)ptep);
+       for (i = 0; i < PDT_ENTRIES; i++, ptep++) {
+           if (prev_entry == ((pte_template_t *)ptep)->bits
+               && PDTIDX(va) != i && i != PDT_ENTRIES-1) {
+                   n_dup_entries++;
+                   continue;   /* suppress suplicate entry */
+           }
+           if (n_dup_entries != 0) {
+               printf("    - %d duplicate entries skipped -\n",n_dup_entries);
+               n_dup_entries = 0;
+           }
+           prev_entry = ((pte_template_t *)ptep)->bits;
+           if (PDTIDX(va) == i) {
+               printf("    >> (%x)pte: ", i);
+           } else      {
+               printf("       (%x)pte: ", i);
+           }
+           PRINT_PDT(ptep);
+       } /* for */
+    } else {
+       /* index into page table */
+       ptep += PDTIDX(va);
+       printf("    pte index 0x%x\n", PDTIDX(va));
+       printf("    pte: ");
+       PRINT_PDT(ptep);
+    }
+} /* pmap_print_trace() */
+
+/*
+ * Check whether the current transaction being looked at by dodexc()
+ *  could have been the one that caused a fault.  Given the virtual
+ *  address, map, and transaction type, checks whether the page at that
+ *  address is valid, and, for write transactions, whether it has write
+ *  permission.
+ */
+boolean_t
+pmap_check_transaction(pmap_t pmap, vm_offset_t va, vm_prot_t type)
+{
+    pt_entry_t *pte;
+    sdt_entry_t        *sdt;
+    int                         spl;
+
+    PMAP_LOCK(pmap, spl);
+
+    if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL) {
+       PMAP_UNLOCK(pmap, spl);
+       return FALSE;
+    }
+    
+    if (!PDT_VALID(pte)) {
+       PMAP_UNLOCK(pmap, spl);
+       return FALSE;
+    }
+
+    /*
+     * Valid pte.  If the transaction was a read, there is no way it
+     *  could have been a fault, so return true.  For now, assume
+     *  that a write transaction could have caused a fault.  We need
+     *  to check pte and sdt entries for write permission to really
+     *  tell.
+     */
+
+    if (type == VM_PROT_READ) {
+       PMAP_UNLOCK(pmap, spl);
+       return TRUE;
+    } else {
+       sdt = SDTENT(pmap,va);
+       if (sdt->prot || pte->prot) {
+           PMAP_UNLOCK(pmap, spl);
+           return FALSE;
+       } else {
+           PMAP_UNLOCK(pmap, spl);
+           return TRUE;
+       }
+    }
+}
+
+/* New functions to satisfy rpd - contributed by danner */
+
+void
+pmap_virtual_space(vm_offset_t *startp, vm_offset_t *endp)
+{
+    *startp = virtual_avail;
+    *endp = virtual_end;
+}
+
+unsigned int
+pmap_free_pages(void)
+{
+        return atop(avail_end - avail_next);
+}
+
+boolean_t
+pmap_next_page(vm_offset_t *addrp)
+{
+        if (avail_next == avail_end)
+                return FALSE;
+
+        *addrp = avail_next;
+        avail_next += PAGE_SIZE;
+        return TRUE;
+}
+
+#if USING_BATC
+#ifdef OMRON_PMAP
+/*
+ *      Set BATC
+ */
+void
+pmap_set_batc(
+    pmap_t pmap,
+    boolean_t data,
+    int i,
+    vm_offset_t va,
+    vm_offset_t pa,
+    boolean_t super,
+    boolean_t wt,
+    boolean_t global,
+    boolean_t ci,
+    boolean_t wp,
+    boolean_t valid)
+{
+    register batc_template_t batctmp;
+
+    if (i < 0 || i > (BATC_MAX - 1)) {
+        panic("pmap_set_batc: illegal batc number\n");
+        /* bad number */
+        return;
+    }
+
+    batctmp.field.lba = va >> 19;
+    batctmp.field.pba = pa >> 19;
+    batctmp.field.sup = super;
+    batctmp.field.wt = wt;
+    batctmp.field.g = global;
+    batctmp.field.ci = ci;
+    batctmp.field.wp = wp;
+    batctmp.field.v = valid;
+
+    if (data) {
+        pmap->d_batc[i].bits = batctmp.bits;
+    } else {
+        pmap->i_batc[i].bits = batctmp.bits;
+    }
+}
+
+void use_batc(
+    task_t task,       
+    boolean_t data,         /* for data-cmmu ? */
+    int i,                  /* batc number */
+    vm_offset_t va,         /* virtual address */
+    vm_offset_t pa,         /* physical address */
+    boolean_t s,            /* for super-mode ? */
+    boolean_t wt,           /* is writethrough */
+    boolean_t g,            /* is global ? */
+    boolean_t ci,           /* is cache inhibited ? */
+    boolean_t wp,           /* is write-protected ? */
+    boolean_t v)            /* is valid ? */
+{
+    pmap_t pmap;
+    pmap = vm_map_pmap(task->map);
+    pmap_set_batc(pmap, data, i, va, pa, s, wt, g, ci, wp, v);
+}
+
+#endif
+#endif /* USING_BATC */
+#if FUTURE_MAYBE
+/*
+ *     Machine-level page attributes
+ *
+ *     The only attribute that may be controlled right now is cacheability.
+ *
+ *     Obviously these attributes will be used in a sparse
+ *     fashion, so we use a simple sorted list of address ranges
+ *     which possess the attribute.
+ */
+
+/*
+ *     Destroy an attribute list.
+ */
+void
+pmap_destroy_ranges(pmap_range_t *ranges)
+{
+       pmap_range_t this, next;
+
+       this = *ranges;
+       while (this != 0) {
+               next = this->next;
+               pmap_range_free(this);
+               this = next;
+             }
+       *ranges = 0;
+}
+
+/*
+ *     Lookup an address in a sorted range list.
+ */
+boolean_t
+pmap_range_lookup(pmap_range_t *ranges, vm_offset_t address)
+{
+       pmap_range_t range;
+
+       for (range = *ranges; range != 0; range = range->next) {
+               if (address < range->start)
+                       return FALSE;
+               if (address < range->end)
+                       return TRUE;
+       }
+       return FALSE;
+}
+
+/*
+ *     Add a range to a list.
+ *     The pmap must be locked.
+ */
+void
+pmap_range_add(pmap_range_t *ranges, vm_offset_t start, vm_offset_t end)
+{
+       pmap_range_t range, *prev;
+
+       /* look for the start address */
+
+       for (prev = ranges; (range = *prev) != 0; prev = &range->next) {
+               if (start < range->start)
+                       break;
+               if (start <= range->end)
+                       goto start_overlaps;
+       }
+
+       /* start address is not present */
+
+       if ((range == 0) || (end < range->start)) {
+               /* no overlap; allocate a new range */
+
+               range = pmap_range_alloc();
+               range->start = start;
+               range->end = end;
+               range->next = *prev;
+               *prev = range;
+               return;
+       }
+
+       /* extend existing range forward to start */
+
+       range->start = start;
+
+    start_overlaps:
+       assert((range->start <= start) && (start <= range->end));
+
+       /* delete redundant ranges */
+
+       while ((range->next != 0) && (range->next->start <= end)) {
+               pmap_range_t old;
+
+               old = range->next;
+               range->next = old->next;
+               range->end = old->end;
+               pmap_range_free(old);
+       }
+
+       /* extend existing range backward to end */
+
+       if (range->end < end)
+               range->end = end;
+}
+
+/*
+ *     Remove a range from a list.
+ *     The pmap must be locked.
+ */
+void
+pmap_range_remove(pmap_range_t *ranges, vm_offset_t start, vm_offset_t end)
+{
+       pmap_range_t range, *prev;
+
+       /* look for start address */
+
+       for (prev = ranges; (range = *prev) != 0; prev = &range->next) {
+               if (start <= range->start)
+                       break;
+               if (start < range->end) {
+                       if (end < range->end) {
+                               pmap_range_t new;
+
+                               /* split this range */
+
+                               new = pmap_range_alloc();
+                               new->next = range->next;
+                               new->start = end;
+                               new->end = range->end;
+
+                               range->next = new;
+                               range->end = start;
+                               return;
+                       }
+
+                       /* truncate this range */
+
+                       range->end = start;
+               }
+       }
+
+       /* start address is not in the middle of a range */
+
+       while ((range != 0) && (range->end <= end)) {
+               *prev = range->next;
+               pmap_range_free(range);
+               range = *prev;
+       }
+
+       if ((range != 0) && (range->start < end))
+               range->start = end;
+}
+#endif /* FUTURE_MAYBE */
diff --git a/sys/arch/mvme88k/mvme88k/process.S b/sys/arch/mvme88k/mvme88k/process.S
new file mode 100644 (file)
index 0000000..38db2e8
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * 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.
+ *
+ */
+#ifndef ASSEMBLER
+#define ASSEMBLER
+#endif
+
+#include "machine/asm.h"
+#include "machine/psl.h"
+
+#ifndef NBPG
+#define        NBPG 4096
+#endif /* NBPG */
+
+       data
+       align 4
+Lsw0:
+       string  "cpu_switch\n"
+       align 4
+swchanpanic:
+       string  "switch wchan %x\n"
+       align 4
+swsrunpanic:
+       string  "switch SRUN %x\n"
+
+       text
+       align 8
+Lswchanpanic:
+       or.u r2, r0, hi16(swchanpanic)
+       or   r2, r2, lo16(swchanpanic)
+       or   r3, r0, r9
+       bsr  _panic
+
+Lswsrunpanic:
+       or.u r2, r0, hi16(swsrunpanic)
+       or   r2, r2, lo16(swsrunpanic)
+       or   r3, r0, r9
+       bsr  _panic
+/*
+ * 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.
+ */
+
+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.
+        */
+       or.u    r30, r0, hi16(_idle_u)
+       or      r30, r30,lo16(_idle_u)
+       addu    r31, r30, UPAGES * NBPG /* now on idle_u stack */
+       or.u    r10, r0, hi16(_curpcb)
+       st      r30, r10,lo16(_curpcb)  /* curpcb = &idle_u */
+       or.u    r10, r0, hi16(_curproc)
+       st      r0, r10, lo16(_curproc) /* curproc = NULL */
+       bsr.n   _cpu_switch
+       or      r2, r0, r10
+
+#if 0
+/*
+ * When no processes are on the runq, switch
+ * idles here watiing for something to come ready.
+ */
+LABEL(idle)
+       or.u    r10, r0, hi16(_curproc)
+       st      r0, r10, lo16(_curproc) /* curproc = NULL */
+
+       bsr.n   _setipl                 /* unblock all interrupts */
+       or      r2, r0, 0
+                                       /* spin reading whichqs until != 0 */
+1:
+       or.u    r10, r0, hi16(_whichqs)
+       ld      r11, r10,lo16(_whichqs) 
+       bcnd    eq0, r11, 1b
+       bsr.n   _setipl
+       or      r2, r0, IPL_HIGH        /* block all ints */
+       br      Lsw1
+#endif /* 0 */
+/*
+ * 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    r10, r0, hi16(_curpcb)
+       ld      r10,r10, lo16(_curpcb)
+       st      r1, r10, PCB_PC         /*  save r1 in pcb */
+       st.d    r14,r10, PCB_R14
+       st.d    r16,r10, PCB_R16
+       st.d    r18,r10, PCB_R18
+       st.d    r20,r10, PCB_R20
+       st.d    r22,r10, PCB_R22
+       st.d    r24,r10, PCB_R24
+       st.d    r26,r10, PCB_R26
+       st.d    r28,r10, PCB_R28
+       st.d    r30,r10, PCB_R30        /* save frame pointer & stack pointer */
+
+       or      r14,r10, 0              /* save r10 in r14 */
+
+       bsr     _getipl
+
+       st      r2, r14, PCB_IPL        /* save ipl in pcb */
+
+       or.u    r11, r0, hi16(_curproc)
+       ld      r11,r11, lo16(_curproc)
+
+       or.u    r12, r0, hi16(_lastproc)
+       st      r11, r12, lo16(_lastproc)/* lastproc = curproc */
+
+       or.u    r11, r0, hi16(_curproc)
+       st      r0, r11, lo16(_curproc) /* curproc = NULL */
+
+       or.u    r11, r0, hi16(_curpcb)
+       st      r0, r11, lo16(_curpcb)  /* curpcb = NULL */
+
+Lidleloop:
+
+       /*
+        * Find the highest-priority queue that isn't empty,
+        * then take the first proc from that queue.
+        */
+
+       or.u    r7, r0, hi16(_whichqs)
+       ld      r7, r7, lo16(_whichqs)
+
+       bcnd    ne0, r7, Ldoneloop
+
+Lloopchk:                              /* if whichqs is zero, keep checking */
+       bsr.n   _setipl                 /* enable all ints */   
+       or      r2, r0, 0
+
+       br      Lidleloop
+
+Ldoneloop:
+
+       bsr.n   _setipl                 /* disable ints */
+       or      r2, r0, IPL_HIGH
+
+       or.u    r7, r0, hi16(_whichqs)  /* reload whichqs */
+       ld      r7, r7, lo16(_whichqs)
+
+       bcnd    eq0, r7, 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, Lsw2  /* 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(_whichqs)
+       ld      r8,  r7, lo16(_whichqs)
+       and.c   r8,  r8, r12    /* whichqs &= ~the bit */
+       st      r8,  r7, lo16(_whichqs) /* reset bit in whichqs */
+Lsw2:
+       ld      r2, r9, P_WCHAN
+       bcnd    ne0, r2, Lswchanpanic
+       ld.b    r2, r9, P_STAT
+       cmp     r2, r2, SRUN
+       bb1     ne, r2, Lswsrunpanic
+
+       or.u    r11, r0, hi16(_want_resched)
+       st      r0, r11, lo16(_want_resched)    /* clear want_resched */
+
+       or.u    r11, r0, hi16(_curproc)
+       st      r9,  r11,lo16(_curproc)         /* curproc = p */
+       
+#ifdef notyet
+       or.u    r2, r0, hi16(_lastproc)
+       ld      r2, r2, lo16(_lastproc)
+#endif /* notyet */
+
+       /* huh??? */
+       or.u    r10, r0, hi16(_curpcb)
+       ld      r10,r10, lo16(_curpcb)
+
+#ifdef notyet
+       cmp     r2, r2, r9
+       bb1     eq, r2, Lswsameproc
+#endif /* notyet */
+
+       /*  r9 is curproc */
+       st      r0, r9, P_BACK                  /* p->p_back = 0 */
+       ld      r3, r9, P_ADDR
+       or.u    r10, r0, hi16(_curpcb)
+       st      r3, r10, lo16(_curpcb)          /* curpcb = p->p_addr */
+
+       /* see if pmap_activate needs to be called */
+       ld      r2, r9, P_VMSPACE       /* vmspace = p->p_vmspace */
+       addu    r2, r2, VM_PMAP         /* pmap = &vmspace.vm_pmap */
+#ifdef notyet 
+       ld      r5, r2, PM_STCHG        /* pmap->st_changed? */
+       bcnd    eq0, r5, Lswnochg       /* no, skip */
+#endif /* notyet */
+       or      r14, r0, r9             /* save p in r14 */
+       subu    r31, r31,48
+       bsr     _pmap_activate          /* pmap_activate(pmap, pcb) */
+       addu    r31, r31,48
+       or      r9, r0, r14             /* restore p saved in r14 */
+
+Lswnochg:
+       or.u    r31, r0, hi16(_intstack_end)
+       or      r31,r31, lo16(_intstack_end)/* now goto a tmp stack for NMI */
+       subu    r31, r31,48
+       bsr.n    _load_u_area               /* load_u_area(p) */
+       or      r2, r0, r9
+       addu    r31, r31,48
+                                       /* flush tlb of any user addresses */
+       or      r2, r0, 0
+       or      r3, r0, 0
+       subu    r31, r31,48
+       bsr.n   _cmmu_flush_tlb
+       or      r4, r0, 0xffff          /* cmmu_flush_tlb flushes entire tlb */
+                                       /* for sizes > 4096                  */
+       addu    r31, r31,48
+       or.u    r10, r0,  hi16(_curpcb)
+       ld      r10, r10,  lo16(_curpcb)
+       /* XXX Is this correct/necessary? */
+       st      r10, r14, P_ADDR        /* p->p_addr = curpcb; restore p_addr */
+
+       /* restore from the current context */
+       ld      r1,r10,  PCB_PC 
+       ld.d    r14,r10, PCB_R14
+       ld.d    r16,r10, PCB_R16
+       ld.d    r18,r10, PCB_R18
+       ld.d    r20,r10, PCB_R20
+       ld.d    r22,r10, PCB_R22
+       ld.d    r24,r10, PCB_R24
+       ld.d    r26,r10, PCB_R26
+       ld.d    r28,r10, PCB_R28
+       ld.d    r30,r10, PCB_R30        /* restore frame pointer & stack */
+
+/* XXX should we postpone restoring stack till after ipl is restored? The
+stack access could fault */
+Lswsameproc:
+       subu    r31,r31,48
+       st      r1, r31,36              /* save r1 on stack */
+       ld      r2, r10, PCB_IPL        /* restore interrupt mask */
+       bsr     _setipl                 /* restore ipl */
+       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)
+       /* get the spl mask */
+       subu    r31,r31,48              /* allocate stack for r1 and args */
+       st      r1,r31,36               /* save return address */
+       st      r2,r31,32               /* save r2 */
+       bsr     _getipl                 /* get the current interrupt mask */
+       ld      r1,r31,36               /* recover return address */
+       ld      r10,r31,32              /* recover r2 into r10 */
+       addu    r31,r31,48              /* put stack pointer back */
+       st      r1, r10, PCB_PC         /* save return address */
+       st.d    r14,r10, PCB_R14
+       st.d    r16,r10, PCB_R16
+       st.d    r18,r10, PCB_R18
+       st.d    r20,r10, PCB_R20
+       st.d    r22,r10, PCB_R22
+       st.d    r24,r10, PCB_R24
+       st.d    r26,r10, PCB_R26
+       st.d    r28,r10, PCB_R28
+       st.d    r30,r10, PCB_R30        /* save frame pointer and sp */
+       st      r2, r10, PCB_IPL        /* save interrupt mask */
+       jmp.n   r1
+       or      r2,r0,r0
diff --git a/sys/arch/mvme88k/mvme88k/process_machdep.c b/sys/arch/mvme88k/mvme88k/process_machdep.c
new file mode 100644 (file)
index 0000000..62a3ba8
--- /dev/null
@@ -0,0 +1,155 @@
+/*     $NetBSD: process_machdep.c,v 1.5 1994/11/20 20:54:37 deraadt 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
+ */
+
+/*
+ * 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>
+#if 0
+#include <machine/frame.h>
+#endif
+#include <sys/ptrace.h>
+
+int
+process_read_regs(p, regs)
+       struct proc *p;
+       struct reg *regs;
+{
+#if 0
+       /* NOTE: struct reg == struct trapframe */
+       bcopy(p->p_md.md_tf, (caddr_t)regs, sizeof(struct reg));
+#endif
+       return (0);
+}
+
+int
+process_write_regs(p, regs)
+       struct proc *p;
+       struct reg *regs;
+{
+#if 0
+       int     psr = p->p_md.md_tf->tf_psr & ~PSR_ICC;
+       bcopy((caddr_t)regs, p->p_md.md_tf, sizeof(struct reg));
+       p->p_md.md_tf->tf_psr = psr | (regs->r_psr & PSR_ICC);
+#endif
+       return (0);
+}
+
+int
+process_sstep(p, sstep)
+       struct proc *p;
+{
+#if 0
+       if (sstep)
+               return EINVAL;
+#endif
+       return (0);
+}
+
+int
+process_set_pc(p, addr)
+       struct proc *p;
+       caddr_t addr;
+{
+#if 0
+       p->p_md.md_tf->tf_pc = (u_int)addr;
+       p->p_md.md_tf->tf_npc = (u_int)addr + 4;
+#endif
+       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;
+}
+
+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;
+}
diff --git a/sys/arch/mvme88k/mvme88k/swapgeneric.c b/sys/arch/mvme88k/mvme88k/swapgeneric.c
new file mode 100644 (file)
index 0000000..1172a18
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)swapgeneric.c       7.5 (Berkeley) 5/7/91
+ *     $Id: swapgeneric.c,v 1.3 1997/03/03 20:21:50 rahnds Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/fcntl.h>         /* XXXX and all that uses it */
+#include <sys/proc.h>          /* XXXX and all that uses it */
+#include <sys/disk.h>
+
+#include "sd.h"
+#include "cd.h"
+
+/*
+ * Only boot on ufs. (XXX?)
+ */
+int ffs_mountroot();
+int (*mountroot)() = ffs_mountroot;
+
+/*
+ * Generic configuration;  all in one
+ */
+dev_t  rootdev = NODEV;
+dev_t  dumpdev = NODEV;
+
+struct swdevt swdevt[] = {
+       { NODEV,        1,      0 },
+       { NODEV,        0,      0 },
+};
+
+#if NSD > 0
+extern struct cfdriver sdcd;
+#endif
+#if NCD > 0
+extern struct cfdriver cdcd;
+#endif
+
+struct genericconf {
+       struct cfdriver *gc_driver;
+       dev_t gc_root;
+};
+
+/*
+ * the system will assign rootdev to the first partition 'a' 
+ * found with FS_BSDFFS fstype. so these should be ordered
+ * in prefernece of boot. however it does walk units backwards
+ * to remain compatible with the old amiga method of picking
+ * the last root found.
+ */
+struct genericconf genericconf[] = {
+#if NSD > 0
+       {&sdcd, makedev(4, 0)},
+#endif
+#if NCD > 0
+       {&cdcd, makedev(6, 0)},
+#endif
+       { 0 },
+};
+
+struct genericconf *
+getgenconf(bp)
+       char *bp;
+{
+       char *cp;
+       struct genericconf *gc;
+
+       for (;;) {
+               printf("root device> ");
+               gets(bp);
+               for (gc = genericconf; gc->gc_driver; gc++)
+                       if (gc->gc_driver->cd_name[0] == bp[0] &&
+                           gc->gc_driver->cd_name[1] == bp[1])
+                               break;
+               if (gc->gc_driver == NULL) {
+                       printf("use one of:");
+                       for (gc = genericconf; gc->gc_driver; gc++)
+                               printf(" %s%%d", gc->gc_driver->cd_name);
+                       printf("\n");
+                       continue;
+               }
+               cp = bp + 2;
+               if (*cp >= '0' && *cp <= '9')
+                       break;
+               printf("bad/missing unit number\n");
+       }
+       return(gc);
+}
+
+setconf()
+{
+       struct dkdevice *dkp;
+       struct partition *pp;
+       struct genericconf *gc;
+       struct bdevsw *bdp;
+       int unit, swaponroot;
+       char name[128];
+       char *cp;
+       
+       swaponroot = 0;
+
+       if (rootdev != NODEV)
+               goto justdoswap;
+
+       unit = 0;
+       if (boothowto & RB_ASKNAME) {
+               gc = getgenconf(name);
+               cp = name + 2;
+               while (*cp >= '0' && *cp <= '9')
+                       unit = 10 * unit + *cp++ - '0';
+               if (*cp == '*')
+                       swaponroot = 1;
+               unit &= 0x7;
+               goto found;
+       }
+       for (gc = genericconf; gc->gc_driver; gc++) {
+               for (unit = gc->gc_driver->cd_ndevs - 1; unit >= 0; unit--) { 
+                       if (gc->gc_driver->cd_devs[unit] == NULL)
+                               continue;
+                       /*
+                        * this is a hack these drivers should use
+                        * dk_dev and not another instance directly above.
+                        */
+                       dkp = (struct dkdevice *)
+                          ((struct device *)gc->gc_driver->cd_devs[unit] + 1);
+                       if (dkp->dk_driver == NULL ||
+                           dkp->dk_driver->d_strategy == NULL)
+                               continue;
+                       for (bdp = bdevsw; bdp < (bdevsw + nblkdev); bdp++)
+                               if (bdp->d_strategy ==
+                                   dkp->dk_driver->d_strategy)
+                                       break;
+                       if (bdp->d_open(MAKEDISKDEV(major(gc->gc_root),
+                           unit, 0), FREAD | FNONBLOCK, 0, curproc))
+                               continue;
+                       bdp->d_close(MAKEDISKDEV(major(gc->gc_root), unit, 
+                           0), FREAD | FNONBLOCK, 0, curproc);
+                       pp = &dkp->dk_label.d_partitions[0];
+                       if (pp->p_size == 0 || pp->p_fstype != FS_BSDFFS)
+                               continue;
+                       goto found;
+               }
+       }
+       printf("no suitable root\n");
+       asm("or r9,r0,0x0063");
+       asm("tb0 0,r0,0x1f0");
+       /*NOTREACHED*/
+found:
+
+       gc->gc_root = MAKEDISKDEV(major(gc->gc_root), unit, 0);
+       rootdev = gc->gc_root;
+
+justdoswap:
+       swdevt[0].sw_dev = MAKEDISKDEV(major(rootdev), 
+           DISKUNIT(rootdev), 1);
+       /*
+       swdevt[0].sw_dev = dumpdev = MAKEDISKDEV(major(rootdev), 
+           DISKUNIT(rootdev), 1);
+    */
+       /* swap size and dumplo set during autoconfigure */
+       if (swaponroot)
+               rootdev = swdevt[0].sw_dev;
+}
+
+gets(cp)
+       char *cp;
+{
+       register char *lp;
+       register c;
+
+       lp = cp;
+       for (;;) {
+               cnputc(c = cngetc());
+               switch (c) {
+               case '\n':
+               case '\r':
+                       *lp = 0;
+                       return;
+               case '\b':
+               case '\177':
+                       if (lp > cp) {
+                               lp--;
+                               cnputc(' ');
+                               cnputc('\b');
+                       }
+                       continue;
+               case '#':
+                       lp--;
+                       if (lp < cp)
+                               lp = cp;
+                       continue;
+               case '@':
+               case 'u'&037:
+                       lp = cp;
+                       cnputc('\n');
+                       continue;
+               default:
+                       *lp++ = c;
+               }
+       }
+}
diff --git a/sys/arch/mvme88k/mvme88k/syscall.stub b/sys/arch/mvme88k/mvme88k/syscall.stub
new file mode 100644 (file)
index 0000000..4a10555
--- /dev/null
@@ -0,0 +1,29 @@
+       /*
+        * 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> <- xip
+        *       br err           <- nip
+        *       jmp r1           <- fip
+        *  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 or EJUSTRETURN,
+        *    we need to rexecute the trap instruction. Back up the pipe
+        *    line.
+        *     fip = nip, nip = xip
+        */
diff --git a/sys/arch/mvme88k/mvme88k/timerreg.h b/sys/arch/mvme88k/mvme88k/timerreg.h
new file mode 100644 (file)
index 0000000..3bafa84
--- /dev/null
@@ -0,0 +1,8 @@
+struct ticktimer {
+       u_int ttcmpreg;         /* Timer compare register */
+       u_int ttcounter;        /* Timer counter */
+       u_int tticr;            /* Timer control register */
+};
+
+struct timers {
+};
diff --git a/sys/arch/mvme88k/mvme88k/trap.c b/sys/arch/mvme88k/mvme88k/trap.c
new file mode 100644 (file)
index 0000000..bcd3397
--- /dev/null
@@ -0,0 +1,723 @@
+/*
+ * 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 <vm/vm.h>
+#include <vm/vm_kern.h>                        /* kernel_map */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/syscall.h>
+#include <sys/ktrace.h>
+#include <machine/cpu.h>               /* DMT_VALID, etc. */
+#include <machine/m88100.h>            /* DMT_VALID, etc. */
+#include <machine/trap.h>
+#include <machine/psl.h>               /* FIP_E, etc. */
+
+#include <sys/systm.h>
+
+#if (DDB)
+#include <machine/db_machdep.h>
+#endif /* DDB */
+
+#define TRAPTRACE
+#if defined(TRAPTRACE)
+unsigned traptrace = 0;
+#endif
+
+#if DDB
+#define DEBUG_MSG db_printf
+#else
+#define DEBUG_MSG printf
+#endif /* DDB */
+
+#define USERMODE(PSR)   (((struct psr*)&(PSR))->psr_mode == 0)
+#define SYSTEMMODE(PSR) (((struct psr*)&(PSR))->psr_mode != 0)
+
+/* XXX MAJOR CLEANUP REQUIRED TO PORT TO BSD */
+
+char   *trap_type[] = {
+       "Reset",
+       "Interrupt Exception",
+       "Instruction Access",
+       "Data Access Exception",
+       "Misaligned Access",
+       "Unimplemented Opcode",
+       "Privileg Violation",
+       "Bounds Check Violation",
+       "Illegal Integer Divide",
+       "Integer Overflow",
+       "Error Exception",
+};
+
+char   *pbus_exception_type[] = {
+       "Success (No Fault)",
+       "",
+       "",
+       "Bus Error",
+       "Segment Fault",
+       "Page Fault",
+       "Supervisor Violation",
+       "Write Violation",
+};
+
+int    trap_types = sizeof trap_type / sizeof trap_type[0];
+
+static inline void
+userret(struct proc *p, struct m88100_saved_state *frame, u_quad_t oticks)
+{
+       int sig;
+       int s;
+
+       /* take pending signals */
+       while ((sig = CURSIG(p)) != 0)
+               postsig(sig);
+       p->p_priority = p->p_usrpri;
+
+       if (want_resched) {
+               /*
+                * Since we are curproc, clock will normally just change
+                * our priority without moving us from one queue to another
+                * (since the running process is not on a queue.)
+                * If that happened after we put ourselves on the run queue
+                * but before we switched, we might not be on the queue
+                * indicated by our priority.
+                */
+               s = splstatclock();
+               setrunqueue(p);
+               p->p_stats->p_ru.ru_nivcsw++;
+               mi_switch();
+               (void) splx(s);
+               while ((sig = CURSIG(p)) != 0)
+                       postsig(sig);
+       }
+
+       /*
+        * If profiling, charge recent system time to the trapped pc.
+        */
+       if (p->p_flag & P_PROFIL)
+               addupc_task(p, frame->sxip & ~3,
+                        (int)(p->p_sticks - oticks));
+
+       curpriority = p->p_priority;
+}
+
+void
+panictrap(int type, struct m88100_saved_state *frame)
+{
+       static int panicing = 0;
+
+       if (panicing++ == 0) {
+               if (type == 2) {        /* instruction exception */
+                       printf("Instr access fault (%s) v = %x, frame %x\n",
+                               pbus_exception_type[(frame->ipfsr >> 16) & 0x7],
+                               frame->sxip & ~3, frame);
+               } else if (type == 3) { /* data access exception */
+                       printf("Data access fault (%s) v = %x, frame %x\n",
+                               pbus_exception_type[(frame->dpfsr >> 16) & 0x7],
+                               frame->sxip & ~3, frame);
+               } else
+                       printf("trap type %d, v = %x, frame %x\n", type, frame->sxip & ~3, frame);
+               regdump(frame);
+       }
+       if ((u_int)type < trap_types)
+               panic(trap_type[type]);
+       panic("trap");
+       /*NOTREACHED*/
+}
+
+/*ARGSUSED*/
+void
+trap(unsigned type, struct m88100_saved_state *frame)
+{
+    struct proc *p;
+    u_quad_t sticks = 0;
+    vm_map_t map;
+    vm_offset_t va;
+    vm_prot_t ftype;
+    int fault_type;
+    u_long fault_code;
+    unsigned nss, fault_addr;
+    struct vmspace *vm;
+    int result;
+    int sig = 0;
+
+    extern vm_map_t kernel_map;
+    extern int fubail(), subail();
+    extern unsigned guarded_access_start;
+    extern unsigned guarded_access_end;
+    extern unsigned guarded_access_bad;
+
+    cnt.v_trap++;
+    if ((p = curproc) == NULL)
+       p = &proc0;
+
+    if (USERMODE(frame->epsr)) {
+       sticks = p->p_sticks;
+       type += T_USER;
+       p->p_md.md_tf = frame;  /* for ptrace/signals */
+       fault_type = 0;
+       fault_code = 0;
+    }
+
+    switch(type)
+    {
+    default:
+       panictrap(frame->vector, frame);
+       /*NOTREACHED*/
+
+#if defined(DDB)
+    case T_KDB_BREAK:
+       /*FALLTHRU*/
+    case T_KDB_BREAK+T_USER:
+    {
+        int s = db_splhigh();
+       db_enable_interrupt();
+        ddb_break_trap(T_KDB_BREAK,(db_regs_t*)frame);
+       db_disable_interrupt();
+        db_splx(s);
+        return;
+    }
+    case T_KDB_ENTRY:
+       /*FALLTHRU*/
+    case T_KDB_ENTRY+T_USER:
+    {
+        int s = db_splhigh();
+       db_enable_interrupt();
+        ddb_entry_trap(T_KDB_ENTRY,(db_regs_t*)frame);
+       db_disable_interrupt();
+        db_splx(s);
+        return;
+    }
+
+#if 0
+    case T_ILLFLT:
+    {
+        int s = db_splhigh();
+       db_enable_interrupt();
+        ddb_error_trap(type == T_ILLFLT ? "unimplemented opcode" :
+            "error fault", (db_regs_t*)frame);
+       db_disable_interrupt();
+        db_splx(s);
+        return;
+    }
+#endif /* 0 */
+#endif /* DDB */
+
+    case T_MISALGNFLT:
+        DEBUG_MSG("kernel misalgined "
+               "access exception @ 0x%08x\n", frame->sxip);
+       panictrap(frame->vector, frame);
+       break;
+
+    case T_INSTFLT:
+       /* kernel mode instruction access fault.
+        * Should never, never happen for a non-paged kernel.
+        */
+        DEBUG_MSG("kernel mode instruction "
+               "page fault @ 0x%08x\n", frame->sxip);
+       panictrap(frame->vector, frame);
+       break;
+
+    case T_DATAFLT:
+       /* kernel mode data fault */
+       /*
+        * If the faulting address is in user space, handle it in
+        * the context of the user process. Else, use kernel map.
+        */
+
+       if (type == T_DATAFLT) {
+               fault_addr = frame->dma0;
+               if (frame->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;
+               }
+       } else {
+               fault_addr = frame->sxip & XIP_ADDR;
+               ftype = VM_PROT_READ;
+               fault_code = VM_PROT_READ;
+       }
+
+       va = trunc_page((vm_offset_t)fault_addr);
+
+       vm = p->p_vmspace;
+       map = &vm->vm_map;
+
+       /* data fault on a kernel address... */
+       if (frame->dmt0 & DMT_DAS)
+               map = kernel_map;
+
+       /* 
+        * We don't want to call vm_fault() if it is fuwintr() or
+        * suwintr(). These routines are for copying from interrupt
+        * context and vm_fault() can potentially sleep. You may
+        * wonder if it isn't bad karma for an interrupt handler to     
+        * touch the current process. Indeed it is, but clock interrupt
+        * does it while doing profiling. It is OK in that context.
+        */
+
+       if (p->p_addr->u_pcb.pcb_onfault == (int)fubail ||
+               p->p_addr->u_pcb.pcb_onfault == (int)subail)
+               goto outtahere;
+
+       /* data fault on the user address */
+       if (type == T_DATAFLT && (frame->dmt0 & DMT_DAS) == 0)
+       {
+               type = T_DATAFLT + T_USER;
+               goto user_fault;
+       }
+
+       /*
+        *      If it is a guarded access, bus error is OK.
+        */
+
+       if ((frame->dpfsr >> 16 & 0x7) == 0x3) {
+#ifdef DIAGNOSTIC 
+               printf("sxip %x dpfsr %x\n", frame->sxip, frame->dpfsr);
+               gimmeabreak();
+#endif
+       }
+
+       if ((frame->dpfsr >> 16 & 0x7) == 0x3 &&                /* bus error */
+               (frame->sxip & ~3) >= (unsigned)&guarded_access_start &&
+               (frame->sxip & ~3) <= (unsigned)&guarded_access_end) {
+
+               frame->snip = ((unsigned)&guarded_access_bad    ) | FIP_V;
+               frame->sfip = ((unsigned)&guarded_access_bad + 4) | FIP_V;
+               frame->sxip = 0;
+               frame->dmt0 = 0;/* XXX what about other trans. in data unit */
+               frame->dpfsr = 0;
+               return;
+       }
+       /*
+        *      On a segment or a page fault, call vm_fault() to resolve
+        *      the fault.
+        */
+
+       if ((frame->dpfsr >> 16 & 0x7) == 0x4                   /* seg fault */
+                       || (frame->dpfsr >> 16 & 0x7) == 0x5) { /* page fault */
+               result = vm_fault(map, va, ftype, FALSE); 
+
+               if (result == KERN_SUCCESS) {
+                       /*
+                        * 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. For inst faults, back up the pipe line.
+                        */
+                       if (type == T_DATAFLT) {
+                           data_access_emulation(frame);
+                           frame->dmt0 = 0;
+                           frame->dpfsr = 0;
+                       } else {
+                           frame->sfip = frame->snip & ~FIP_E;
+                           frame->snip = frame->sxip & ~NIP_E;
+                       }       
+                       return;
+               }
+       }
+
+       /*
+        * if still the fault is not resolved ...
+        */
+       if (!p->p_addr->u_pcb.pcb_onfault)
+               panictrap(frame->vector, frame);
+
+    outtahere:
+       frame->snip = ((unsigned)p->p_addr->u_pcb.pcb_onfault    ) | FIP_V;
+       frame->sfip = ((unsigned)p->p_addr->u_pcb.pcb_onfault + 4) | FIP_V;
+       frame->sxip = 0;
+       frame->dmt0 = 0;        /* XXX what about other trans. in data unit */
+       frame->dpfsr = 0;
+       return;
+
+    case T_INSTFLT+T_USER:
+       /* User mode instruction access fault */
+       /*FALLTHRU*/
+    case T_DATAFLT+T_USER:
+    user_fault:
+
+       if (type == T_INSTFLT+T_USER)
+               fault_addr = frame->sxip & XIP_ADDR;
+       else
+               fault_addr = frame->dma0;
+
+       if (frame->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((vm_offset_t)fault_addr);
+
+       vm = p->p_vmspace;
+       map = &vm->vm_map;
+
+       /* Call vm_fault() to resolve non-bus error faults */
+
+       if ((frame->ipfsr >> 16 & 0x7) != 0x3 &&
+               (frame->dpfsr >> 16 & 0x7) != 0x3) {
+
+               result = vm_fault(map, va, ftype, FALSE); 
+               frame->ipfsr = frame->dpfsr = 0;
+
+       }
+
+
+       if ((caddr_t)va >= vm->vm_maxsaddr) {
+               if (result == KERN_SUCCESS) {
+                       nss = clrnd(btoc(USRSTACK - va));/* XXX check this */
+                       if (nss > vm->vm_ssize)
+                               vm->vm_ssize = nss;
+               } else if (result == KERN_PROTECTION_FAILURE)
+                       result = KERN_INVALID_ADDRESS;
+       }
+
+        if (result == KERN_SUCCESS) {
+               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(frame);
+                       frame->dmt0 = 0;
+                       frame->dpfsr = 0;
+               } else {
+                   /* back up SXIP, SNIP clearing the the Error bit */
+                   frame->sfip = frame->snip & ~FIP_E;
+                   frame->snip = frame->sxip & ~NIP_E;
+               }
+       } else {
+               sig = result == KERN_PROTECTION_FAILURE ? SIGBUS : SIGSEGV;
+               fault_type = result == KERN_PROTECTION_FAILURE ? 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:
+       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_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.
+        */
+       frame->sfip = frame->snip;    /* set up next FIP */
+       frame->snip = frame->sxip;    /* set up next NIP */
+       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->sfip = frame->snip;    /* set up the next FIP */
+       frame->snip = frame->sxip;    /* set up the next NIP */
+       sig = SIGTRAP;
+       fault_type = TRAP_BRKPT;
+       break;
+
+    case T_ASTFLT+T_USER:
+       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 (SYSTEMMODE(frame->epsr))
+        return;
+
+    if (sig) {
+       trapsignal(p, sig, fault_code, fault_type, (caddr_t)fault_addr);
+       /*
+         * don't want multiple faults - we are going to
+        * deliver signal.
+        */
+       frame->dmt0 = 0;
+       frame->dpfsr = 0;
+    }
+
+    userret(p, frame, sticks);
+}
+
+void
+error_fault(struct m88100_saved_state *frame)
+{
+    DEBUG_MSG("\n[ERROR FAULT (Bad News[tm]) frame 0x%08x]\n", frame);
+#if DDB
+    gimmeabreak();
+    DEBUG_MSG("[you really can't restart after an error fault.]\n");
+    gimmeabreak();
+#endif /* DDB */
+}
+
+syscall(register_t code, struct m88100_saved_state *tf)
+{
+       register int i, nsys, *ap, nap;
+       register struct sysent *callp;
+       register struct proc *p;
+       int error, new;
+       struct args {
+               int i[8];
+       } args;
+       int rval[2];
+       u_quad_t sticks;
+       extern struct pcb *curpcb;
+
+       cnt.v_syscall++;
+
+       p = curproc;
+
+       callp = p->p_emul->e_sysent;
+       nsys  = p->p_emul->e_nsysent;
+
+#ifdef DIAGNOSTIC
+       if (USERMODE(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->r[2];
+       nap = 6;
+
+       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 > 8)
+                       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, i * sizeof(register_t));
+       }
+#ifdef SYSCALL_DEBUG
+       scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+       if (KTRPOINT(p, KTR_SYSCALL))
+               ktrsyscall(p->p_tracep, code, callp->sy_argsize, args.i);
+#endif
+       rval[0] = 0;
+       rval[1] = 0;
+       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> <- xip
+        *       br err           <- nip
+        *       jmp r1           <- fip
+        *  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.
+        */
+
+       if (error == 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 = USER_REGS(p);
+               tf->r[2] = rval[0];
+               tf->r[3] = rval[1];
+               tf->epsr &= ~PSR_C;
+               tf->snip = tf->sfip & ~FIP_E;
+               tf->sfip = tf->snip + 4;
+       } else if (error > 0) {
+               /* error != ERESTART && error != EJUSTRETURN*/
+               tf->r[2] = error;
+               tf->epsr |= PSR_C;      /* fail */
+               tf->snip = tf->snip & ~NIP_E;
+               tf->sfip = tf->sfip & ~FIP_E;
+       } else if (error == ERESTART) {
+               /*
+                * If (error == ERESTART), back up the pipe line. This
+                * will end up reexecuting the trap.
+                */
+               tf->epsr &= ~PSR_C;
+               tf->sfip = tf->snip & ~NIP_E;
+               tf->snip = tf->sxip & ~NIP_E;
+       } else {
+               /* if (error == EJUSTRETURN), leave the ip's alone */
+               tf->epsr &= ~PSR_C;
+       }
+#ifdef SYSCALL_DEBUG
+       scdebug_ret(p, code, error, rval);
+#endif
+       userret(p, tf, sticks);
+#ifdef KTRACE
+       if (KTRPOINT(p, KTR_SYSRET))
+               ktrsysret(p->p_tracep, code, error, rval[0]);
+#endif
+}
+
+/*
+ * Set up return-value registers as fork() libc stub expects,
+ * and do normal return-to-user-mode stuff.
+ */
+void
+child_return(struct proc *p)
+{
+       struct trapframe *tf;
+
+       tf = USER_REGS(p);
+       tf->r[2] = 0;
+       tf->r[3] = 0;
+       tf->epsr &= ~PSR_C;
+       tf->snip = tf->sfip & ~3;
+       tf->sfip = tf->snip + 4;
+
+       userret(p, tf, p->p_sticks);
+#ifdef KTRACE
+       if (KTRPOINT(p, KTR_SYSRET))
+               ktrsysret(p->p_tracep, SYS_fork, 0, 0);
+#endif
+}
diff --git a/sys/arch/mvme88k/mvme88k/vm_machdep.c b/sys/arch/mvme88k/mvme88k/vm_machdep.c
new file mode 100644 (file)
index 0000000..eaba815
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 1996 Nivas Madhur
+ * Copyright (c) 1993 Adam Glass 
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: Utah $Hdr: vm_machdep.c 1.21 91/04/06$
+ *     from: @(#)vm_machdep.c  7.10 (Berkeley) 5/7/91
+ *     vm_machdep.c,v 1.3 1993/07/07 07:09:32 cgd Exp
+ *     $Id: vm_machdep.c,v 1.3 1997/03/03 20:21:54 rahnds Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/user.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+
+#include <machine/cpu.h>
+
+#ifdef XXX_FUTURE
+extern struct map *iomap;
+#endif
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the kernel stack and pcb, making the child
+ * ready to run, and marking it so that it can return differently
+ * than the parent.  Returns 1 in the child process, 0 in the parent.
+ * We currently double-map the user area so that the stack is at the same
+ * address in each process; in the future we will probably relocate
+ * the frame pointers on the stack after copying.
+ */
+
+#ifdef __FORK_BRAINDAMAGE
+int
+#else
+void
+#endif
+cpu_fork(struct proc *p1, struct proc *p2)
+{
+       struct switchframe *p2sf;
+       int off, ssz;
+       struct ksigframe {
+               void (*func)(struct proc *);
+               void *proc;
+       } *ksfp;
+       extern void proc_do_uret(), child_return();
+       extern void proc_trampoline();
+       
+       savectx(p1->p_addr);
+
+       bcopy((void *)&p1->p_addr->u_pcb, (void *)&p2->p_addr->u_pcb, sizeof(struct pcb));
+       p2->p_addr->u_pcb.kernel_state.pcb_ipl = 0;
+
+       p2->p_md.md_tf = USER_REGS(p2);
+
+       /*XXX these may not be necessary nivas */
+       save_u_area(p2, p2->p_addr);
+#ifdef notneeded
+       PMAP_ACTIVATE(&p2->p_vmspace->vm_pmap, &p2->p_addr->u_pcb, 0);
+#endif /* notneeded */
+
+       /*
+        * Create a switch frame for proc 2
+        */
+       p2sf = (struct switchframe *)((char *)p2->p_addr + USPACE - 8) - 1;
+       p2sf->sf_pc = (u_int)proc_do_uret;
+       p2sf->sf_proc = p2;
+       p2->p_addr->u_pcb.kernel_state.pcb_sp = (u_int)p2sf;
+
+       ksfp = (struct ksigframe *)p2->p_addr->u_pcb.kernel_state.pcb_sp - 1;
+
+       ksfp->func = child_return;
+       ksfp->proc = p2;
+
+       /*
+        * When this process resumes, r31 will be ksfp and
+        * the process will be at the beginning of proc_trampoline().
+        * proc_trampoline will execute the function func, pop off
+        * ksfp frame, and call the function in the switchframe
+        * now exposed.
+        */
+
+       p2->p_addr->u_pcb.kernel_state.pcb_sp = (u_int)ksfp;
+       p2->p_addr->u_pcb.kernel_state.pcb_pc = (u_int)proc_trampoline;
+
+#ifdef __FORK_BRAINDAMAGE
+       return(0);
+#else
+       return;
+#endif
+}
+
+void
+cpu_set_kpc(struct proc *p, void (*func)(struct proc *))
+{
+       /*
+        * override func pointer in ksigframe with func.
+        */
+
+       struct ksigframe {
+               void (*func)(struct proc *);
+               void *proc;
+       } *ksfp;
+
+       ksfp = (struct ksigframe *)p->p_addr->u_pcb.kernel_state.pcb_sp;
+
+       ksfp->func = func;
+
+}
+
+/*
+ * cpu_exit is called as the last action during exit.
+ * We release the address space and machine-dependent resources,
+ * including the memory for the user structure and kernel stack.
+ * Once finished, we call switch_exit, which switches to a temporary
+ * pcb and stack and never returns.  We block memory allocation
+ * until switch_exit has made things safe again.
+ */
+volatile void
+cpu_exit(struct proc *p)
+{
+       extern volatile void switch_exit();
+       vmspace_free(p->p_vmspace);
+
+       (void) splimp();
+       kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
+       switch_exit(p);
+       /* NOTREACHED */
+}
+
+int
+cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred, struct core *corep)
+{
+
+       return (vn_rdwr(UIO_WRITE, vp, (caddr_t) p->p_addr, ctob(UPAGES),
+           (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL,
+           p));
+}
+
+/*
+ * Finish a swapin operation.
+ * We neded to update the cached PTEs for the user area in the
+ * machine dependent part of the proc structure.
+ */
+
+void
+cpu_swapin(struct proc *p)
+{
+       save_u_area(p, (vm_offset_t)p->p_addr);
+}
+
+extern vm_map_t phys_map;
+
+/*
+ * Map an IO request into kernel virtual address space.  Requests fall into
+ * one of five catagories:
+ *
+ *     B_PHYS|B_UAREA: User u-area swap.
+ *                     Address is relative to start of u-area (p_addr).
+ *     B_PHYS|B_PAGET: User page table swap.
+ *                     Address is a kernel VA in usrpt (Usrptmap).
+ *     B_PHYS|B_DIRTY: Dirty page push.
+ *                     Address is a VA in proc2's address space.
+ *     B_PHYS|B_PGIN:  Kernel pagein of user pages.
+ *                     Address is VA in user's address space.
+ *     B_PHYS:         User "raw" IO request.
+ *                     Address is VA in user's address space.
+ *
+ * All requests are (re)mapped into kernel VA space via phys_map
+ *
+ * XXX we allocate KVA space by using kmem_alloc_wait which we know
+ * allocates space without backing physical memory.  This implementation
+ * is a total crock, the multiple mappings of these physical pages should
+ * be reflected in the higher-level VM structures to avoid problems.
+ */
+void
+vmapbuf(struct buf *bp, vm_size_t len)
+{
+       register caddr_t addr;
+       register vm_offset_t pa, kva, off;
+       struct proc *p;
+
+       if ((bp->b_flags & B_PHYS) == 0)
+               panic("vmapbuf");
+
+       addr = (caddr_t)trunc_page(bp->b_saveaddr = bp->b_data);
+       off = (vm_offset_t)bp->b_saveaddr & PGOFSET;
+       len = round_page(off + len);
+       p = bp->b_proc;
+
+       /*
+        * You may ask: Why phys_map? kernel_map should be OK - after all,
+        * we are mapping user va to kernel va or remapping some
+        * kernel va to another kernel va. The answer is TLB flushing
+        * when the address gets a new mapping.
+        */
+
+       kva = kmem_alloc_wait(phys_map, len);
+       
+       /*
+        * Flush the TLB for the range [kva, kva + off]. Strictly speaking,
+        * we should do this in vunmapbuf(), but we do it lazily here, when
+        * new pages get mapped in.
+        */
+
+       cmmu_flush_tlb(1, kva, len);
+
+       bp->b_data = (caddr_t)(kva + off);
+       while (len > 0) {
+               pa = pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),
+                   (vm_offset_t)addr);
+               if (pa == 0)
+                       panic("vmapbuf: null page frame");
+               pmap_enter(vm_map_pmap(phys_map), kva, pa,
+                          VM_PROT_READ|VM_PROT_WRITE, TRUE);
+               addr += PAGE_SIZE;
+               kva += PAGE_SIZE;
+               len -= PAGE_SIZE;
+       }
+}
+
+/*
+ * Free the io map PTEs associated with this IO operation.
+ * We also restore the original b_addr.
+ */
+void
+vunmapbuf(struct buf *bp, vm_size_t len)
+{
+       register vm_offset_t addr, off;
+
+       if ((bp->b_flags & B_PHYS) == 0)
+               panic("vunmapbuf");
+
+       addr = trunc_page(bp->b_data);
+       off = (vm_offset_t)bp->b_data & PGOFSET;
+       len = round_page(off + len);
+       kmem_free_wakeup(phys_map, addr, len);
+       bp->b_data = bp->b_saveaddr;
+       bp->b_saveaddr = 0;
+}
+
+#ifdef XXX_FUTURE
+/*
+ * Map a range [pa, pa+len] in the given map to a kernel address
+ * in iomap space.
+ *
+ * Note: To be flexible, I did not put a restriction on the alignment
+ * of pa. However, it is advisable to have pa page aligned since otherwise,
+ * we might have several mappings for a given chunk of the IO page.
+ */
+vm_offset_t
+iomap_mapin(vm_offset_t pa, vm_size_t len, boolean_t canwait)
+{
+       vm_offset_t             iova, tva, off;
+       register int            npf, s;
+
+       if (len == 0)
+               return NULL;
+
+       off = (u_long)pa & PGOFSET;
+
+       len = round_page(off + len);
+
+       s = splimp();
+       for (;;) {
+               iova = rmalloc(iomap, len);
+               if (iova != 0)
+                       break;
+               if (canwait) {
+                       (void)tsleep(iomap, PRIBIO+1, "iomapin", 0);
+                       continue;
+               }
+               splx(s);
+               return NULL;
+       }
+       splx(s);
+
+       tva = iova;
+       pa = trunc_page(pa);
+
+       while (len) {
+               pmap_enter(kernel_pmap, tva, pa,
+                       VM_PROT_READ|VM_PROT_WRITE, 1);
+               len -= PAGE_SIZE;
+               tva += PAGE_SIZE;
+               pa += PAGE_SIZE;
+       }
+       return (iova + off);
+}
+
+/*
+ * Free up the mapping in iomap.
+ */
+int
+iomap_mapout(vm_offset_t kva, vm_size_t len)
+{
+       register int            s;
+       vm_offset_t             off;
+
+       off = kva & PGOFSET;
+       kva = trunc_page(kva);
+       len = round_page(off + len);
+
+       pmap_remove(pmap_kernel(), kva, kva + len);
+
+       s = splimp();
+       rmfree(iomap, len, kva);
+       wakeup(iomap);
+       splx(s);
+}
+#endif /* XXX_FUTURE */
+/*
+ * Map the given physical IO address into the kernel temporarily.
+ * Maps one page.
+ * Should have some sort of lockig for the use of phys_map_vaddr. XXX nivas
+ */
+
+vm_offset_t
+mapiospace(caddr_t pa, int len)
+{
+       int off = (u_long)pa & PGOFSET;
+       extern vm_offset_t phys_map_vaddr1;
+
+       pa = (caddr_t)trunc_page(pa);
+
+       pmap_enter(kernel_pmap, phys_map_vaddr1, (vm_offset_t)pa,
+                  VM_PROT_READ|VM_PROT_WRITE, 1);
+       
+       return (phys_map_vaddr1 + off);
+}
+
+/*
+ * Unmap the address from above.
+ */
+
+void
+unmapiospace(vm_offset_t va)
+{
+       va = trunc_page(va);
+
+       pmap_remove(kernel_pmap, va, va + NBPG);
+}
+
+int
+badvaddr(vm_offset_t va, int size)
+{
+       register int    x;
+
+       if (badaddr(va, size)) {
+               return -1;
+       }
+
+       switch (size) {
+       case 1:
+               x = *(volatile unsigned char *)va;
+               break;
+       case 2:
+               x = *(volatile unsigned short *)va;
+               break;
+       case 4:
+               x = *(volatile unsigned long *)va;
+               break;
+       default:
+               break;  
+       }
+       return(x);
+}
+
+int
+badpaddr(caddr_t pa, int size)
+{
+       vm_offset_t va;
+       int val;
+
+       /*
+        * Do not allow crossing the page boundary.
+        */
+       if (((int)pa & PGOFSET) + size > NBPG) {
+               return -1;
+       }
+
+       va = mapiospace(pa, NBPG);
+       val = badvaddr(va, size);
+       unmapiospace(va);
+       return (val);
+}
+
+/*
+ * Move pages from one kernel virtual address to another.
+ * Size must be a multiple of CLSIZE.
+ */
+void
+pagemove(caddr_t from, caddr_t to, size_t size)
+{
+       register vm_offset_t pa;
+
+#ifdef DEBUG
+       if (size & CLOFSET)
+               panic("pagemove");
+#endif
+       while (size > 0) {
+               pa = pmap_extract(kernel_pmap, (vm_offset_t)from);
+#ifdef DEBUG
+               if (pa == 0)
+                       panic("pagemove 2");
+               if (pmap_extract(kernel_pmap, (vm_offset_t)to) != 0)
+                       panic("pagemove 3");
+#endif
+               pmap_remove(kernel_pmap,
+                           (vm_offset_t)from, (vm_offset_t)from + NBPG);
+               pmap_enter(kernel_pmap,
+                          (vm_offset_t)to, pa, VM_PROT_READ|VM_PROT_WRITE, 1);
+               from += NBPG;
+               to += NBPG;
+               size -= NBPG;
+       }
+}
+
+u_int
+kvtop(vm_offset_t va)
+{
+       extern pmap_t kernel_pmap;
+
+       return ((u_int)pmap_extract(kernel_pmap, va));
+}
diff --git a/sys/arch/mvme88k/stand/Makefile b/sys/arch/mvme88k/stand/Makefile
new file mode 100644 (file)
index 0000000..63fc38c
--- /dev/null
@@ -0,0 +1,5 @@
+#      $Id: Makefile,v 1.3 1997/03/03 20:21:57 rahnds Exp $
+
+SUBDIR=  netboot sboot bootsd bootst libsa bugcrt libbug wrtvid
+
+.include <bsd.subdir.mk>
diff --git a/sys/arch/mvme88k/stand/boot/Makefile b/sys/arch/mvme88k/stand/boot/Makefile
new file mode 100644 (file)
index 0000000..df343d8
--- /dev/null
@@ -0,0 +1,30 @@
+all:   boot boot.out
+CFLAGS+=-fwritable-strings -I${.CURDIR}/../include
+CFLAGS+=-I${.CURDIR}/../.. -I${.CURDIR}/../../machine
+CFLAGS+=-I/usr/src/sys
+LDFLAGS+= -L ${.CURDIR}/../libbug -L/usr/local/lib
+BOOT=FC0000
+#BOOT=1000000
+
+LIBBUG!= cd $(.CURDIR)/../libbug; \
+     printf "xxx:\n\techo \$${.OBJDIR}/libbug.a\n" | ${MAKE} -r -s -f - xxx
+
+LDADD+=${LIBBUG} #/usr/local/lib/libgcc.a
+SRCS+=bugcrt.c bugio.c main.c
+
+.PATH:    ${.CURDIR}/../bugcrt ${.CURDIR}/../libbug ${.CURDIR}/../../../../lib/libc_sa ${.CURDIR}/${MACHINE_ARCH}
+
+boot:  bugcrt.o main.o bcopy.o memset.o printf.o ${LIBBUG}
+#      ld -o {.TARGET} -x -n -Ttext ${BOOT} bugcrt.o bugio.o main.o bcopy.o memset.o printf.o /usr/local/lib/libgcc.a
+       ld -o ${.TARGET} -x -N -Ttext ${BOOT} ${.ALLSRC} ${LDADD}
+
+boot.out:
+       ${.CURDIR}/wrtvid ${.OBJDIR}/boot && mv ${.OBJDIR}/boot.? ${.CURDIR}
+
+#main.o: main.c
+#      ${CC} ${CFLAGS} -c -O ${.ALLSRC}
+#      ${LD} -x -r ${.TARGET}
+#      ${LD} -x  ${.TARGET}
+#      mv a.out ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/mvme88k/stand/boot/main.c b/sys/arch/mvme88k/stand/boot/main.c
new file mode 100644 (file)
index 0000000..1fbc9f6
--- /dev/null
@@ -0,0 +1,267 @@
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include "bug.h"
+#include "bugio.h"
+#include "machine/exec.h"
+
+int    readblk         __P((int, char *));
+int    loados          __P((void));    
+void   putchar         __P((char));
+void   _main           __P((void));
+void   tapefileseek    __P((int));
+
+char Clun, Dlun;
+
+#define        DEV_BSIZE               512
+#define        KERNEL_LOAD_ADDR        0x10000
+#if !defined(BUG_BLKSIZE)
+#define        BUG_BLKSIZE             256
+#endif /* BUG_BLKSIZE */
+#define        sec2blk(x)      ((x) * (DEV_BSIZE/BUG_BLKSIZE))
+
+struct kernel {
+       void *entry;
+       void *symtab;
+       void *esym;
+       int      bflags;
+       int      bdev;
+       char *kname;
+       void *smini;
+       void *emini;
+       unsigned int end_loaded;
+} kernel;
+
+int howto = 0;
+int bootdev = 0;
+int *miniroot;
+
+void
+putchar(char c)
+{
+       bugoutchr(c);
+}
+
+main(struct bugenv *env)
+{
+       printf("Clun %x Dlun %x\n", env->clun, env->dlun);
+       Clun = (char)env->clun;
+       Dlun = (char)env->dlun;
+       loados();
+       return;
+}
+
+
+loados(void)
+{
+       int i, size;
+       register char *loadaddr = (char *)KERNEL_LOAD_ADDR; /* load addr 64k*/
+       struct exec *hdr;
+       int (*fptr)();
+       int *esym;
+       int cnt, strtablen, ret;
+       char *addr;
+
+       howto |= RB_SINGLE|RB_KDB;
+
+       tapefileseek(2);        /* seek to file 2 - the OS */
+       if (readblk(1, loadaddr) == -1) {
+               printf("Unable to read blk 0\n");
+               return 1;
+       }
+       hdr     = (struct exec *)loadaddr;
+       
+       /* We only deal with ZMAGIC files */
+       if ((int)hdr->a_entry != (int)(loadaddr + sizeof(struct exec))) {
+               printf("a_entry != loadaddr + exec size\n");
+       }
+       size = hdr->a_text + hdr->a_data;
+       size -= DEV_BSIZE; /* account for the block already read */
+
+       printf("Loading [%x+%x", hdr->a_text, hdr->a_data);
+       if (readblk(size / DEV_BSIZE, loadaddr + DEV_BSIZE) == -1) {
+               printf("Error reading the OS\n");
+               return 1;
+       }
+
+       /* zero out BSS */
+
+       printf("+%x]", hdr->a_bss);
+       printf("zero'd out %x (%x)\n", loadaddr + hdr->a_text + hdr->a_data,
+                       hdr->a_bss);
+       /*memset(loadaddr + hdr->a_text + hdr->a_data, 0, hdr->a_bss); */
+       bzero(loadaddr + hdr->a_text + hdr->a_data, hdr->a_bss);
+
+       addr = loadaddr + hdr->a_text + hdr->a_data + hdr->a_bss;
+
+       if (hdr->a_syms != 0 /* && !(kernel.bflags & RB_NOSYM)*/) {
+               /*
+                * DDB expects the following layout:
+                *      no. of syms
+                *      symbols
+                *      size of strtab
+                *      entries of strtab
+                * esym->...
+                * Where as size of strtab is part of strtab, we need
+                * to prepend the size of symtab to satisfy ddb.
+                * esym is expected to point past the last byte of
+                * string table, rouded up to an int.
+                */
+               bcopy(&hdr->a_syms, addr, sizeof(hdr->a_syms));
+               addr += 4;  /* account for a_syms copied above */
+               printf (" + [ %x",hdr->a_syms);
+
+               cnt = (hdr->a_syms + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
+
+               ret = readblk(cnt / DEV_BSIZE, addr);
+               if (ret != 0) {
+                       printf("unable to load kernel\n");
+                       return 1;
+               }
+
+               esym = (void *) ((int)addr + hdr->a_syms);
+
+               if ((int)addr + cnt <= (int)esym) {
+                       printf("missed loading count of symbols\n\r");
+                       return 1;
+               }
+
+               addr += cnt;
+
+               strtablen = *esym;
+#if 0
+               printf("start load %x end load %x %x\n", addr,
+                       len, addr +len);
+               printf("esym %x *esym %x\n",esym, len);
+#endif
+               /*
+                * If symbol table size is not a sector multiple, we
+                * already read part of the string table. Look at the
+                * part already read, and figure out the string table
+                * size. Also, adjust the size yet to read.
+                */
+               if (hdr->a_syms != cnt) {
+                       /* already read part of the string table */
+                       strtablen -= (cnt - hdr->a_syms);
+               }
+
+               if (strtablen > 0) {
+                       printf(" + %x",*esym);
+
+                       cnt = (strtablen + DEV_BSIZE -1) & ~(DEV_BSIZE - 1);
+
+                       ret = readblk(cnt / DEV_BSIZE, addr);
+                       if (ret != 0) {
+                               printf("unable to load kernel\n");
+                               return 1;
+                       }
+                       addr += strtablen;
+                       printf(" ]\n");
+               } else {
+                       printf("+ %x ]\n", *esym);
+               }
+               esym = (int *)(((int)esym) + *esym);
+               esym = (int *)(((int)esym + 4 - 1) & ~3);
+
+               kernel.symtab = (void *)hdr->a_syms;
+               kernel.esym = esym;
+       } else {
+               kernel.symtab = 0;
+               kernel.esym = 0;
+       }
+
+       kernel.end_loaded = (unsigned int)addr;
+       miniroot = (int *)esym;
+       miniroot = (int *)(((int)miniroot + 0x1000 - 1) & ~0xFFF);
+       tapefileseek(3);        /* seek to file 3 - minroot */
+#if 0
+       if (readblk(1000, miniroot) != 0) { /* 5 Mb */
+               printf("miniroot not loaded\n");
+               addr = (char *)miniroot;
+       } else {
+               addr = (char *)((int)miniroot + 1000 * DEV_BSIZE);
+       }
+#endif /* 0 */
+       readblk(4096, miniroot); /* 2 Mb */
+       addr = (char *)((int)miniroot + 4096 * DEV_BSIZE);
+       printf("esym %x miniroot @ %x (ends @ %x)\n", esym, miniroot, addr);
+#if 0
+       {
+               char *symaddr = (char *)0x01F00000;
+               int  i;
+
+               tapefileseek(4);        /* seek to file 4 - syms */
+               readblk(1, symaddr);
+               i = *symaddr;
+               i = (i * 0x1C + 4 + DEV_BSIZE) & ~(DEV_BSIZE - 1);
+               printf("loading %d symbols (%d sectors)\n",
+                       *symaddr, (i + 1) * DEV_BSIZE);
+               readblk(i / DEV_BSIZE, symaddr + DEV_BSIZE);
+               readblk(100, 0x01F00000);
+       }
+#endif
+
+       fptr = (int (*)())hdr->a_entry;
+       /*
+        * Args are passed as
+        *      r2 howto
+        *      r3 end addr
+        *      r4 (Clun << 8) | Dlun & FF
+        *      r5 esym
+        *      r6 miniroot
+        */
+       bootdev = ((Clun << 8) & 0xFF00 | Dlun & 0xFF) & 0xFFFF;
+#if 0
+       asm volatile ("or r2, r0, %0\n\tor r3, r0, %1\n\tor r4, r0, %2\n\tor r5, r0, %3\n\tor r6, r0, %4\n\tor r7, r0, %5"
+               : /* no outputs */
+               : "r" (howto), "r" (addr), "r" (Clun), "r" (Dlun), "r" (esym), "r" (miniroot)
+               : "r2", "r3", "r4", "r5", "r6", "r7");
+#endif /* 0 */
+       (*fptr)(howto, addr, bootdev, esym, miniroot);  
+       return 0;
+}
+
+int
+readblk(int n, char *addr)
+{
+       struct bugdisk_io io;
+
+       io.clun = Clun;
+       io.dlun = Dlun;
+       io.status = 0;
+       io.addr = (void *)addr;
+       io.fileno = 0; /* for tape reads, start io at current pos */
+       io.nblks = sec2blk(n);
+       io.flag = IGNOREFILENO;
+       io.am = 0;
+       bugdskrd(&io);
+       if (io.status)
+               return -1;
+       return 0;
+}
+
+void
+_main(void)
+{
+       return;
+}
+
+void
+tapefileseek(int i)
+{
+       struct bugdisk_io io;
+       void *addr = (void *)KERNEL_LOAD_ADDR; /* some number - don't care */
+
+       io.clun = Clun;
+       io.dlun = Dlun;
+       io.status = 0;
+       io.addr = addr;
+       io.fileno = i; /* for tape reads, this is the file no. */
+       io.nblks = 0;
+       io.flag = 0; /* we want to turn off IFN and EOF bits */
+       io.am = 0;
+       bugdskrd(&io);
+}
+
+__main()
+{
+}
diff --git a/sys/arch/mvme88k/stand/boot/obj.m88k/boot b/sys/arch/mvme88k/stand/boot/obj.m88k/boot
deleted file mode 100644 (file)
index 789b981..0000000
Binary files a/sys/arch/mvme88k/stand/boot/obj.m88k/boot and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/boot/wrtvid.c b/sys/arch/mvme88k/stand/boot/wrtvid.c
new file mode 100644 (file)
index 0000000..6161cca
--- /dev/null
@@ -0,0 +1,108 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "vid.h"
+
+#define        sec2blk(x)      ((x) * 2)
+
+main(int argc, char **argv)
+{
+       struct vid *pvid;
+       struct cfg *pcfg;
+       struct stat stat;
+       int exe_file;
+       int tape_vid;
+       int tape_exe;
+       unsigned int exe_addr;
+       unsigned short exe_addr_u;
+       unsigned short exe_addr_l;
+       char *filename;
+       char fileext[256];
+
+       if (argc == 0){
+               filename = "a.out";
+       } else {
+               filename = argv[1];
+       }
+       exe_file = open(filename, O_RDONLY,0444);
+       if (exe_file == -1)
+       {
+               printf("file %s does not exist\n",filename);
+               exit(2);
+       }
+       sprintf (fileext,"%s%s",filename,".1");
+       tape_vid = open(fileext, O_WRONLY|O_CREAT|O_TRUNC,0644);
+       sprintf (fileext,"%s%s",filename,".2");
+       tape_exe = open(fileext, O_WRONLY|O_CREAT|O_TRUNC,0644);
+
+       pvid = (struct vid *) malloc(sizeof (struct vid));
+
+       memset(pvid,0,sizeof(struct vid));
+
+       strcpy(pvid->vid_id, "NBSD");
+
+       fstat (exe_file,&stat);
+       /* size in 512 byte blocks round up after a.out header removed */
+       /* Actually, blocks == 256 bytes */
+
+       pvid->vid_oss = 1;
+       pvid->vid_osl = (short)sec2blk((stat.st_size - 0x20 + 511) / 512);
+
+       lseek(exe_file,0x14,SEEK_SET);
+       read(exe_file,&exe_addr,4);
+       {
+               union {
+                       struct {
+                               short osa_u;
+                               short osa_l;
+                       } osa_u_l; 
+                       int     osa;
+               } u;
+               u.osa = exe_addr;
+               pvid->vid_osa_u = u.osa_u_l.osa_u;
+               pvid->vid_osa_l = u.osa_u_l.osa_l;
+       }
+       pvid->vid_cas = 1;
+       pvid->vid_cal = 1;
+       /* do not want to write past end of structure, not null terminated */
+       strcpy(pvid->vid_mot,"MOTOROL");
+       pvid->vid_mot[7] = 'A';
+
+       write(tape_vid,pvid,sizeof(struct vid));
+
+       free(pvid);
+
+       pcfg = (struct cfg *) malloc (sizeof(struct cfg));
+
+       memset(pcfg,0,sizeof(struct cfg));
+
+       pcfg->cfg_rec = 0x100;
+       pcfg->cfg_psm = 0x200;
+
+       write(tape_vid,pcfg,sizeof(struct cfg));
+
+       free(pcfg);
+
+       copy_exe(exe_file,tape_exe);
+       close (exe_file);
+       close (tape_vid);
+       close (tape_exe);
+}
+
+#define BUF_SIZ 512
+copy_exe(exe_file,tape_exe)
+{
+       char *buf;
+       int cnt = 0;
+
+       buf = (char *)malloc (BUF_SIZ);
+
+       lseek (exe_file,0x20,SEEK_SET);
+       while (BUF_SIZ == (cnt = read(exe_file, buf , BUF_SIZ))) {
+               write (tape_exe,buf,cnt);
+       }
+       memset (&buf[cnt],0,BUF_SIZ-cnt);
+       write (tape_exe,buf,BUF_SIZ);
+}
diff --git a/sys/arch/mvme88k/stand/bootsd/bootsd b/sys/arch/mvme88k/stand/bootsd/bootsd
deleted file mode 100644 (file)
index b87003e..0000000
Binary files a/sys/arch/mvme88k/stand/bootsd/bootsd and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/bootsd/bootsd.bin b/sys/arch/mvme88k/stand/bootsd/bootsd.bin
deleted file mode 100644 (file)
index 1b9b345..0000000
Binary files a/sys/arch/mvme88k/stand/bootsd/bootsd.bin and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/bootsd/bootsd.bug b/sys/arch/mvme88k/stand/bootsd/bootsd.bug
deleted file mode 100644 (file)
index 7da0971..0000000
Binary files a/sys/arch/mvme88k/stand/bootsd/bootsd.bug and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/bootsd/sdboot b/sys/arch/mvme88k/stand/bootsd/sdboot
deleted file mode 100644 (file)
index a79942f..0000000
Binary files a/sys/arch/mvme88k/stand/bootsd/sdboot and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/bootst/bak.c b/sys/arch/mvme88k/stand/bootst/bak.c
deleted file mode 100644 (file)
index a93d9bc..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-#include "bug.h"
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/reboot.h>
-#include <sys/exec.h>
-/*
-#include <sys/exec_aout.h>
-*/
-
-#define KERNEL_LOAD_ADDRESS ((void *)0x4000)
-#define BUG_BLOCK_SIZE 512
-#define VERSION 0x0000
-
-#define RB_NOSYM 0x400
-
-
-
-void memset(void *,char,size_t);
-void printf(char *,...);
-void parse_args(struct bugargs *pbugargs);
-int read_tape_block(short ctrl, short dev, short *status, void *addr,
-               int *cnt, int blk_num, unsigned char *flags,int verbose);
-int load_kern();
-
-struct kernel {
-       void *entry;
-       void *symtab;
-       void *esym;
-       int      bflags;
-       int      bdev;
-       char *kname;
-       void *smini;
-       void *emini;
-       u_int end_loaded;
-} kernel;
-
-typedef (* kernel_entry)(struct bugargs *,struct kernel *);
-
-void main(struct bugargs *pbugargs)
-{
-       kernel_entry addr;
-
-       /*
-       print_bugargs(pbugargs);
-       print_time();
-       print_brdid();
-       print_memory();
-       */
-       parse_args(pbugargs);
-       if (1 == load_kern(pbugargs)) {
-               printf("unsuccessful in loading kernel\n\r");
-       } else {
-               addr = kernel.entry;
-               printf("kernel loaded at %x\n\r",addr);
-               printf("kernel.entry %x\n\r",kernel.entry);
-               printf("kernel.symtab %x\n\r",kernel.symtab);
-               printf("kernel.esym %x\n\r",kernel.esym);
-               printf("kernel.bflags %x\n\r",kernel.bflags);
-               printf("kernel.bdev %x\n\r",kernel.bdev);
-               if (kernel.kname) {
-               printf("kernel.kname <%s>\n\r",kernel.kname);
-               } else {
-               printf("kernel.kname <null>\n\r");
-               }
-               printf("kernel.end_loaded %x\n\r",kernel.end_loaded);
-
-               if (kernel.bflags & RB_MINIROOT) {
-                       loadmini(kernel.end_loaded,pbugargs);
-               }
-
-               printf("kernel.smini %x\n\r",kernel.smini);
-               printf("kernel.emini %x\n\r",kernel.emini);
-               printf("kernel.end_loaded %x\n\r",kernel.end_loaded);
-               if (kernel.bflags & RB_HALT)
-                       bug_return();
-               (addr)(pbugargs,&kernel);
-       }
-
-       return;
-}
-#define BUG_SCALE (512/BUG_BLOCK_SIZE)
-int
-read_tape_block(short ctrl, short dev, short *status, void *addr,
-               int *cnt, int blk_num, unsigned char *flags,int verbose)
-{
-       struct bug_dskio dio;
-       int ret;
-       int len, len1;
-
-       len = *cnt;
-       do {
-               if (len > 16 * 1024) {
-                       len1 = 16 * 1024;
-               }else{
-                       len1 = len;
-               }
-               dio.ctrl_lun    = ctrl;
-               dio.dev_lun     = dev;
-               dio.status      = *status;
-               dio.pbuffer     = addr;
-               dio.blk_num     = blk_num;
-               dio.blk_cnt     = len1 /(512/BUG_SCALE);
-               dio.flag        = *flags;
-               dio.addr_mod    = 0;
-
-               if (verbose){
-                       printf("saddr %x eaddr %x", dio.pbuffer, 
-                               (int)dio.pbuffer + (dio.blk_cnt * BUG_BLOCK_SIZE));
-               }
-               
-               ret     =  bug_diskrd(&dio);
-
-               *status = dio.status;
-               *cnt    += (dio.blk_cnt/BUG_SCALE)*512;
-               if (verbose) {
-                       printf("status %x ret %d ",*status, ret);
-                       printf("flags %x\n\r",*flags);
-               }
-               len -= len1;
-               addr += len1;
-               blk_num += len1 /(512/BUG_SCALE);
-       } while (len > 0);
-       return ret;
-}
-int verbose = 1;
-int
-load_kern(struct bugargs *pbugargs)
-{
-       int ret;
-       char *addr;
-       unsigned char flags;
-       short status = 0;
-       int blk_num;
-       struct exec *pexec;
-       int magic;
-       int *esym;
-       int *symtab;
-       int cnt, len;
-       char buf[512];
-
-       blk_num = 2;
-       /* flags = IGNORE_FILENUM ; */
-       flags = 0;
-       cnt = 512 ;
-       ret = read_tape_block(pbugargs->ctrl_lun, pbugargs->dev_lun, &status, buf,
-                       &cnt, blk_num, &flags, verbose);
-       if (ret != 0) {
-               printf("unable to load kernel 1\n\r");
-               return 1;
-       }
-       pexec = (struct exec *) buf;
-       if ((N_GETMID(*pexec)  != MID_M68K) && 
-               ( N_GETMID(*pexec)  != MID_M68K4K ))
-       {
-               printf("invalid mid on kernel\n\r");
-               return 1;
-       }
-       {
-               short *pversion = (void *)(KERNEL_LOAD_ADDRESS+0x20);
-               if (VERSION != *pversion) {
-                       printf("invalid version of kernel/loader\n\r");
-                       bug_return();
-               }
-       }
-       magic = N_GETMAGIC(*pexec);
-       switch (magic) {
-               case ZMAGIC:
-                       break;
-               case NMAGIC:
-                       printf ("NMAGIC not yet supported");
-               case OMAGIC:
-               case QMAGIC:
-               default:
-                       printf("Unknown or unsupported magic type <%x>\n\r",
-                               magic);
-                       return 1;
-                       break;
-       }
-       if ( magic == ZMAGIC ) {
-
-               status = 0;
-               addr = pexec->a_entry & ~0x0FFF;
-               bcopy(&buf, addr, 512);
-               /* 2nd block of exe */
-               addr += 512;
-
-               if ((int)pexec->a_entry != (int)KERNEL_LOAD_ADDRESS + 0x22) {
-                       printf ("warning kernel start address not %x, %x\n\r",
-                               (int)KERNEL_LOAD_ADDRESS + 0x22,pexec->a_entry);
-                       printf ("kernel loaded at %x\n\r",KERNEL_LOAD_ADDRESS);
-
-               }
-               printf ("text 0x%x data 0x%x bss 0x%x\n\r",
-                       pexec->a_text, pexec->a_data, pexec->a_bss);
-
-               len = (pexec->a_text - 512) ; /* XXX */
-               len += (pexec->a_data );
-
-               printf ("loading [ %x + %x ",pexec->a_text,pexec->a_data);
-
-               cnt = len;
-               flags = IGNORE_FILENUM ;
-               ret = read_tape_block(pbugargs->ctrl_lun, pbugargs->dev_lun,
-               &status, addr, &cnt, blk_num, &flags, verbose);
-               if (ret != 0 || cnt != len) {
-                       printf("unable to load kernel 2\n\r");
-                       return 1;
-               }
-               addr += len;
-
-               /* Skip over text and data and zero bss. */
-               len = pexec->a_bss;
-               printf ("+ %x",len);
-               memset (KERNEL_LOAD_ADDRESS + (pexec->a_text + pexec->a_data),
-                       0, pexec->a_bss);
-               addr +=len;
-               
-               if (pexec->a_syms != 0 && !(kernel.bflags & RB_NOSYM)) {
-                       printf (" + [ %x",pexec->a_syms);
-                       addr += 4;  /* skip over _end symbol */
-                       symtab = (void *)pexec->a_syms;
-                       len = pexec->a_syms;
-                       cnt = len;
-                       flags = IGNORE_FILENUM ;
-                       ret = read_tape_block(pbugargs->ctrl_lun,
-                               pbugargs->dev_lun, &status, addr,
-                               &cnt, blk_num, &flags, verbose);
-                       if (ret != 0 || cnt != len)
-                       {
-                               printf("unable to load kernel 3\n\r");
-                               return 1;
-                       }
-
-                       /* this value should have already been loaded XXX */
-                       esym = (void *) ((u_int)addr + pexec->a_syms);
-                       if ((int)addr +cnt <= (int) esym) {
-                               printf("missed loading count of symbols\n\r");
-                               return 1;
-                       }
-                       addr +=cnt ;
-
-
-                       len = *esym;
-#if 0
-                       printf("start load %x end load %x %x\n\r", addr,
-                               len, addr +len);
-                       printf("esym %x *esym %x\n\r",esym, len);
-#endif
-                       /* dont load tail of already loaded */
-                       len -= (u_int)addr - (u_int)esym;
-
-                       if (len > 0) {
-                               printf(" + %x",*esym);
-                               esym = (void *)(addr + len);
-                               cnt = len;
-                               flags = IGNORE_FILENUM ;
-                               ret = read_tape_block(pbugargs->ctrl_lun, pbugargs->dev_lun, &status, addr,
-                                               &cnt, blk_num, &flags, verbose);
-                               if (ret != 0 || cnt != len)
-                               {
-                                       printf("unable to load kernel 4\n\r");
-                                       return 1;
-                               }
-                               addr += len;
-                               printf(" ]");
-                       } else {
-                               printf("+ %x ]",*esym);
-                       }
-                       esym = (int *)(((int)esym) + *esym);
-
-                       kernel.symtab = symtab;
-                       kernel.esym = esym;
-               } else {
-                       kernel.symtab = 0;
-                       kernel.esym = 0;
-               }
-               kernel.end_loaded = (int)addr;
-               flags = IGNORE_FILENUM | END_OF_FILE;
-               cnt = 8192;
-               printf ("removing pad [");
-               ret = read_tape_block(pbugargs->ctrl_lun, pbugargs->dev_lun, &status, addr,
-                               &cnt, blk_num, &flags, verbose);
-               if (ret != 0) {
-                       printf("unable to load kernel 5\n\r");
-                       return 1;
-               }
-               printf (" %d ]",cnt);
-
-               printf("]\n\r");
-       }
-
-
-       kernel.entry =  (void *)pexec->a_entry;
-       return 0;
-}
-loadmini(u_int addr,struct bugargs *pbugargs)
-{
-       int ret;
-       unsigned char flags;
-       short status = 0;
-       int verbose = 0;
-       int blk_num;
-       int cnt;
-       blk_num = 3;
-       /* align addr to some boundary */
-#define ALIGN_F 0x4
-       addr = (u_int)((((int)addr + ALIGN_F -1)/ALIGN_F) * ALIGN_F);
-#undef ALIGN_F
-       flags = END_OF_FILE;
-       cnt = 6144 * 512 ; /* some abserdly large value. (3meg) */
-       printf("loading miniroot[ ");
-       ret = read_tape_block(4, pbugargs->dev_lun, &status, (void*)addr,
-                       &cnt, blk_num, &flags, verbose);
-       if (ret != 0) {
-               printf("unable to load miniroot\n\r");
-               return 1;
-       }
-       kernel.smini = (void *)addr;
-       printf("%d ]\n\r",(BUG_BLOCK_SIZE * cnt));
-       kernel.emini = (void*)((u_int)addr + (BUG_BLOCK_SIZE * cnt));
-       kernel.end_loaded = (u_int)kernel.emini;
-}
-void
-parse_args(struct bugargs *pargs)
-{
-       char * ptr = pargs->arg_start;
-       char c, *name;
-       int howto;
-       howto = ( 0 | RB_DFLTROOT );
-       name = NULL;
-
-       if (pargs->arg_start != pargs->arg_end) {
-               while (c = *ptr) {
-                       while (c == ' ')
-                               c = *++ptr;
-                       if (!c)
-                               return;
-                       if (c == '-')
-                               while ((c = *++ptr) && c != ' ') {
-                                       if (c == 'a')
-                                               howto |= RB_ASKNAME;
-                                       else if (c == 'b')
-                                               howto |= RB_HALT;
-                                       else if (c == 'y')
-                                               howto |= RB_NOSYM;
-#ifdef CHECKSUM
-                                       else if (c == 'c')
-                                               cflag = 1;
-#endif
-                                       else if (c == 'd')
-                                               howto |= RB_KDB;
-                                       else if (c == 'm')
-                                               howto |= RB_MINIROOT;
-                                       else if (c == 'r')
-/* change logic to have force root to config device UNLESS arg given */
-                                               howto &= ~RB_DFLTROOT;
-                                       else if (c == 's')
-                                               howto |= RB_SINGLE;
-                               }
-                       else {
-                               name = ptr;
-                               while ((c = *++ptr) && c != ' ');
-                               if (c)
-                                       *ptr++ = 0;
-                       }
-               }
-               if (RB_NOSYM & howto) printf("RB_NOSYM\n\r");
-               if (RB_AUTOBOOT & howto) printf("RB_AUTOBOOT\n\r");
-               if (RB_SINGLE & howto) printf("RB_SINGLE\n\r");
-               if (RB_NOSYNC & howto) printf("RB_NOSYNC\n\r");
-               if (RB_HALT & howto) printf("RB_HALT\n\r");
-               if (RB_DFLTROOT & howto) printf("RB_DFLTROOT\n\r");
-               if (RB_KDB & howto) printf("RB_KDB\n\r");
-               if (RB_RDONLY & howto) printf("RB_RDONLY\n\r");
-               if (RB_DUMP & howto) printf("RB_DUMP\n\r");
-               if (RB_MINIROOT & howto) printf("RB_MINIROOT\n\r");
-
-       }
-       kernel.bflags = howto;
-       kernel.kname = name;
-}
-
diff --git a/sys/arch/mvme88k/stand/bootst/bootst b/sys/arch/mvme88k/stand/bootst/bootst
deleted file mode 100644 (file)
index 53c7665..0000000
Binary files a/sys/arch/mvme88k/stand/bootst/bootst and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/bootst/bootst.bug b/sys/arch/mvme88k/stand/bootst/bootst.bug
deleted file mode 100644 (file)
index 34dbd27..0000000
Binary files a/sys/arch/mvme88k/stand/bootst/bootst.bug and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/bootst/stboot b/sys/arch/mvme88k/stand/bootst/stboot
deleted file mode 100644 (file)
index a6b19b3..0000000
Binary files a/sys/arch/mvme88k/stand/bootst/stboot and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/bugcrt/Makefile b/sys/arch/mvme88k/stand/bugcrt/Makefile
new file mode 100644 (file)
index 0000000..19d6add
--- /dev/null
@@ -0,0 +1,24 @@
+#    $Id: Makefile,v 1.3 1997/03/03 20:22:14 rahnds Exp $
+
+CFLAGS+=-I${.CURDIR}/../../include 
+
+.include "${MACHINE_ARCH}/Makefile.inc"
+
+.PATH:  ${.CURDIR}/${MACHINE_ARCH}
+
+OBJS=bugcrt.o
+
+CLEANFILES+=a.out
+
+all:   ${OBJS}
+
+bugcrt.o: bugcrt.c
+       ${CC} ${CFLAGS} -c ${.ALLSRC}
+       ${LD} -x -r ${.TARGET}
+       mv a.out ${.TARGET}
+
+install:
+
+lint tags:
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/mvme88k/stand/bugexec/Makefile b/sys/arch/mvme88k/stand/bugexec/Makefile
new file mode 100644 (file)
index 0000000..3ed0ff0
--- /dev/null
@@ -0,0 +1,26 @@
+all:   hello
+SRCS= hello.c
+OBJS= hello.o
+
+CFLAGS+=-I${.CURDIR}/include -I${.CURDIR}/${MACHINE_ARCH}
+CFLAGS+=-I${.CURDIR}/../include -I${.CURDIR}/../.. -I/usr/src/sys
+CFLAGS+=-fwritable-strings
+
+LIBBUG!= cd $(.CURDIR)/../libbug; \
+     printf "xxx:\n\techo \$${.OBJDIR}/libbug.a\n" | ${MAKE} -r -s -f - xxx
+
+BUGCRT!= cd $(.CURDIR)/../bugcrt; \
+     printf "xxx:\n\techo \$${.OBJDIR}/bugcrt.o\n" | ${MAKE} -r -s -f - xxx
+
+KERNCRT!= cd $(.CURDIR)/../kerncrt; \
+     printf "xxx:\n\techo \$${.OBJDIR}/kerncrt.o\n" | ${MAKE} -r -s -f - xxx
+
+LDADD+=${LIBBUG} /usr/local/lib/libgcc.a
+
+hello: $(OBJS) ${LIBBUG}
+       ${LD} -x -Ttext 10020 ${KERNCRT} $(OBJS) ${LDADD} -o ${.TARGET}
+clean:
+       rm -f a.out *.core
+       rm -f hello.o hello.bug hello.bug.1 hello.bug.2
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/mvme88k/stand/bugexec/hello.c b/sys/arch/mvme88k/stand/bugexec/hello.c
new file mode 100644 (file)
index 0000000..08ab75d
--- /dev/null
@@ -0,0 +1,54 @@
+#include "bug.h"
+#include "bugio.h"
+
+void   putchar __P((char));
+int    bcd2int __P((unsigned int));
+
+void
+putchar(char c)
+{
+       bugoutchr(c);
+}
+
+main(struct bugenv *env)
+{
+       struct bugrtc rtc;
+       struct bugbrdid brdid;
+
+       bugrtcrd(&rtc);
+       printf("From RTC:\n");
+       printf("Year %d\tMonth %d\tDay %d\tDay of Week %d\n",
+               bcd2int(rtc.Y), bcd2int(rtc.M), bcd2int(rtc.D), bcd2int(rtc.d));
+       printf("Hour %d\tMin %d\tSec %d\tCal %d\n",
+               bcd2int(rtc.H), bcd2int(rtc.m), bcd2int(rtc.s), bcd2int(rtc.c));
+       printf("From BRDID:\n");
+       bugbrdid(&brdid);
+/*     printf("Eye catcher %c%c%c%c\n", brdid.eye[0], brdid.eye[1],
+                       brdid.eye[2], brdid.eye[3]); */
+       printf("Board no %d (%d) \tsuffix %c%c\n", bcd2int(brdid.brdno),
+                brdid.brdno, brdid.brdsuf[0], brdid.brdsuf[1]);
+/*     printf("Clun %x\tdlun %x\n", brdid.clun, brdid.dlun); */
+       return 0;
+}
+
+ipow(int base, int i)
+{
+       int cnt = 1;
+       while (i--) {
+               cnt *= base;
+       }
+       return cnt;     
+}
+
+int
+bcd2int(unsigned int i)
+{
+       unsigned val = 0;
+       int     cnt = 0;
+       while (i) {
+               val += (i&0xf) * ipow(10,cnt);
+               cnt++;
+               i >>= 4;
+       }
+       return val;
+}
diff --git a/sys/arch/mvme88k/stand/bugexec/wrtos.c b/sys/arch/mvme88k/stand/bugexec/wrtos.c
new file mode 100644 (file)
index 0000000..1e01b69
--- /dev/null
@@ -0,0 +1,64 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "vid.h"
+
+#define        sec2blk(x)      ((x) * 2)
+#define BUF_SIZ 512
+
+main(int argc, char **argv)
+{
+       struct vid *pvid;
+       struct cfg *pcfg;
+       struct stat stat;
+       int exe_file;
+       int tape_vid;
+       int tape_exe;
+       char *filename;
+       char fileext[256];
+       char hdrbuf[BUF_SIZ];
+
+       if (argc == 0){
+               filename = "a.out";
+       } else {
+               filename = argv[1];
+       }
+       exe_file = open(filename, O_RDONLY,0444);
+       if (exe_file == -1)
+       {
+               printf("file %s does not exist\n",filename);
+               exit(2);
+       }
+       sprintf (fileext,"%s%s",filename,".1");
+       tape_vid = open(fileext, O_WRONLY|O_CREAT|O_TRUNC,0644);
+       sprintf (fileext,"%s%s",filename,".2");
+       tape_exe = open(fileext, O_WRONLY|O_CREAT|O_TRUNC,0644);
+
+       lseek(exe_file,0,SEEK_SET);
+       memset (hdrbuf,0,BUF_SIZ);
+       read(exe_file,hdrbuf, 0x20);    /* read the header */
+
+       write(tape_vid,hdrbuf,BUF_SIZ);
+
+       copy_exe(exe_file,tape_exe);
+       close (exe_file);
+       close (tape_vid);
+       close (tape_exe);
+}
+
+copy_exe(exe_file,tape_exe)
+{
+       char *buf;
+       int cnt = 0;
+
+       buf = (char *)malloc (BUF_SIZ);
+
+       lseek (exe_file,0x20,SEEK_SET);
+       while (BUF_SIZ == (cnt = read(exe_file, buf , BUF_SIZ))) {
+               write (tape_exe,buf,cnt);
+       }
+       memset (&buf[cnt],0,BUF_SIZ-cnt);
+       write (tape_exe,buf,BUF_SIZ);
+}
diff --git a/sys/arch/mvme88k/stand/include/bug.h b/sys/arch/mvme88k/stand/include/bug.h
new file mode 100644 (file)
index 0000000..93fe1e6
--- /dev/null
@@ -0,0 +1,8 @@
+struct bugenv {
+       int     clun;
+       int     dlun;
+       int     ipl;
+       int     (*entry)();
+       char    bootargs[256];
+};
+
diff --git a/sys/arch/mvme88k/stand/include/bugio.h b/sys/arch/mvme88k/stand/include/bugio.h
new file mode 100644 (file)
index 0000000..74bb77b
--- /dev/null
@@ -0,0 +1,62 @@
+#include "sys/cdefs.h"
+
+struct bugdisk_io {
+       char    clun;
+       char    dlun;
+       short   status;
+       void    *addr;
+       int     blkno;
+#define        fileno  blkno
+       short   nblks;
+       char    flag;
+#define        FILEMARKFLAG    0x80
+#define        IGNOREFILENO    0x02
+#define        ENDOFFILE       0x01
+       char    am;
+};     
+
+/* values are in BCD {upper nibble+lower nibble} */
+
+struct bugrtc {
+       unsigned char   Y;
+       unsigned char   M;
+       unsigned char   D;
+       unsigned char   d;
+       unsigned char   H;
+       unsigned char   m;
+       unsigned char   s;
+       unsigned char   c;
+};
+
+/* Board ID - lots of info */
+
+struct bugbrdid {
+       unsigned char   eye[4];
+       char    rev;
+       char    month;
+       char    day;
+       char    year;
+       short   packetsize;
+       short   dummy;
+       short   brdno;
+       unsigned char   brdsuf[2];
+       char    options[3];
+       char    family:4;
+       char    cpu:4;
+       short   clun;
+       short   dlun;
+       short   type;
+       short   dev;
+       int     option;
+};
+
+char buginchr  __P((void));
+int buginstat  __P((void));
+int bugoutchr  __P((unsigned char));
+int bugoutstr  __P((char *, char *));
+int bugpcrlf   __P((void));
+int bugdskrd   __P((struct bugdisk_io *));
+int bugdskwr   __P((struct bugdisk_io *));
+int bugrtcrd   __P((struct bugrtc *));
+int bugreturn  __P((void));
+int bugbrdid   __P((struct bugbrdid *));
diff --git a/sys/arch/mvme88k/stand/kerncrt/Makefile b/sys/arch/mvme88k/stand/kerncrt/Makefile
new file mode 100644 (file)
index 0000000..9645605
--- /dev/null
@@ -0,0 +1,9 @@
+OBJ=kerncrt.o
+CFLAGS+=-I${.CURDIR}/../include
+CFLAGS+=-I${.CURDIR}/../..
+CFLAGS+=-I/usr/src/sys
+
+SRCS=kerncrt.c
+all:   kerncrt.o
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/mvme88k/stand/kerncrt/kerncrt.c b/sys/arch/mvme88k/stand/kerncrt/kerncrt.c
new file mode 100644 (file)
index 0000000..a5f04d2
--- /dev/null
@@ -0,0 +1,11 @@
+#include "bug.h"
+start(struct bugenv *bugarea)
+{
+       main(bugarea);
+       bugreturn();
+}
+
+__main()
+{
+       return;
+}
diff --git a/sys/arch/mvme88k/stand/libbug/Makefile b/sys/arch/mvme88k/stand/libbug/Makefile
new file mode 100644 (file)
index 0000000..ba775e5
--- /dev/null
@@ -0,0 +1,14 @@
+LIB=bug
+
+NOPIC=
+NOPROFILE=
+
+CFLAGS+=-I${.CURDIR}/../../include
+
+SRCS=delay.c diskrd.c diskwr.c getbrdid.c instat.c outln.c outstr.c \
+       return.c rtc_rd.c
+.PATH:    ${.CURDIR}/../../../../lib/libc_sa ${.CURDIR}/${MACHINE_ARCH}
+
+install:
+
+.include <bsd.lib.mk>
diff --git a/sys/arch/mvme88k/stand/libbug/bugio.c b/sys/arch/mvme88k/stand/libbug/bugio.c
new file mode 100644 (file)
index 0000000..6406dac
--- /dev/null
@@ -0,0 +1,101 @@
+#include "bugio.h"
+
+#define INCHR  "0x0000"
+#define INSTAT "0x0001"
+#define INLN   "0x0002"
+#define READSTR        "0x0003"
+#define READLN "0x0004"
+#define        DSKRD   "0x0010"
+#define        DSKWR   "0x0011"
+#define        DSKCFIG "0x0012"
+#define        OUTCHR  "0x0020"
+#define        PCRLF   "0x0026"
+#define        TMDISP  "0x0042"
+#define        DELAY   "0x0043"
+#define        RTC_DSP "0x0052"
+#define        RTC_RD  "0x0053"
+#define        RETURN  "0x0063"
+#define        BRD_ID  "0x0070"
+#define BUGTRAP        "0x01F0"
+
+char
+buginchr(void)
+{
+       register int cc asm("r2");
+       asm("or r9,r0," INCHR);
+       asm("tb0 0,r0,0x1F0");
+       /*asm("or %0,r0,r2" : "=r" (cc) : );*/
+       return ((char)cc & 0xFF);
+}
+
+/* return 1 if not empty else 0 */
+
+buginstat(void)
+{
+       int ret;
+       asm("or r9,r0," INSTAT);
+       asm("tb0 0,r0,0x1F0");
+       asm("or %0,r0,r2" : "=r" (ret) : );
+       return (ret & 0x40 ? 1 : 0);
+}
+
+bugoutchr(unsigned char c)
+{
+       unsigned char cc;
+
+       if ((cc = c) == '\n') {
+               bugpcrlf();
+               return;
+       }
+       asm("or r2,r0,%0" : : "r" (cc));
+       asm("or r9,r0," OUTCHR);
+       asm("tb0 0,r0,0x1F0");
+}
+
+bugpcrlf(void)
+{
+       asm("or r9,r0," PCRLF);
+       asm("tb0 0,r0,0x1F0");
+}
+/* return 0 on success */
+
+bugdskrd(struct bugdisk_io *arg)
+{
+       int ret;
+       asm("or r9,r0, " DSKRD);
+       asm("tb0 0,r0,0x1F0");  
+       asm("or %0,r0,r2" : "=r" (ret) : );
+       return ((ret&0x4) == 0x4 ? 1 : 0);
+}
+
+/* return 0 on success */
+
+bugdskwr(struct bugdisk_io *arg)
+{
+       int ret;
+       asm("or r9,r0, " DSKWR);
+       asm("tb0 0,r0,0x1F0");  
+       asm("or %0,r0,r2" : "=r" (ret) : );
+       return ((ret&0x4) == 0x4 ? 1 : 0);
+}
+
+bugrtcrd(struct bugrtc *rtc)
+{
+       asm("or r9,r0, " RTC_RD);
+       asm("tb0 0,r0,0x1F0");
+}
+
+bugreturn(void)
+{
+       asm("or r9,r0, " RETURN);
+       asm("tb0 0,r0,0x1F0");
+}
+
+bugbrdid(struct bugbrdid *id)
+{
+       struct bugbrdid *ptr;
+       asm("or r9,r0, " BRD_ID);
+       asm("tb0 0,r0,0x1F0");
+       asm("or %0,r0,r2" : "=r" (ptr) : );
+       bcopy(ptr, id, sizeof(struct bugbrdid));
+}
diff --git a/sys/arch/mvme88k/stand/libbug/log1 b/sys/arch/mvme88k/stand/libbug/log1
deleted file mode 100644 (file)
index 448b6b7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-delay.o delay.o
-diskrd.o diskrd.o
-diskwr.o diskwr.o
-getbrdid.o getbrdid.o
-instat.o instat.o
-outln.o outln.o
-outstr.o outstr.o
-return.o return.o
-rtc_rd.o rtc_rd.o
diff --git a/sys/arch/mvme88k/stand/libbug/log2 b/sys/arch/mvme88k/stand/libbug/log2
deleted file mode 100644 (file)
index 7a8950e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-rtc_rd.o
-return.o
-outstr.o
-outln.o
-instat.o
-getbrdid.o
-diskwr.o
-diskrd.o
-delay.o
diff --git a/sys/arch/mvme88k/stand/libsa/log1 b/sys/arch/mvme88k/stand/libsa/log1
deleted file mode 100644 (file)
index 1704777..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-nfs.o nfs.o
-rpc.o rpc.o
-net.o net.o
-ether.o ether.o
-arp.o arp.o
-in_cksum.o in_cksum.o
-netif.o netif.o
-bootparam.o bootparam.o
-rarp.o rarp.o
-alloc.o alloc.o
-bcopy.o bcopy.o
-memcpy.o memcpy.o
-close.o close.o
-getfile.o getfile.o
-open.o open.o
-printf.o printf.o
-read.o read.o
-strerror.o strerror.o
-ufs.o ufs.o
-globals.o globals.o
-lseek.o lseek.o
-closeall.o closeall.o
-dev.o dev.o
-dkcksum.o dkcksum.o
-nullfs.o nullfs.o
-fstat.o fstat.o
-ashrdi3.o ashrdi3.o
-bcmp.o bcmp.o
-bzero.o bzero.o
-strcmp.o strcmp.o
-strlen.o strlen.o
-exec_sun.o exec_sun.o
-clock.o clock.o
-devopen.o devopen.o
-dvma.o dvma.o
-gets.o gets.o
-panic.o panic.o
-promboot.o promboot.o
-promcons.o promcons.o
-ufs.o ashrdi3.o
-dvma.o alloc.o
-nfs.o alloc.o
-ufs.o alloc.o
-net.o arp.o
-net.o arp.o
-arp.o globals.o
-ether.o globals.o
-rarp.o globals.o
-arp.o bcmp.o
-ether.o bcmp.o
-rarp.o bcmp.o
-arp.o bcopy.o
-bootparam.o bcopy.o
-ether.o bcopy.o
-exec_sun.o bcopy.o
-memcpy.o bcopy.o
-net.o bcopy.o
-nfs.o bcopy.o
-rarp.o bcopy.o
-ufs.o bcopy.o
-arp.o bzero.o
-net.o bzero.o
-netif.o bzero.o
-nfs.o bzero.o
-rarp.o bzero.o
-rpc.o bzero.o
-ufs.o bzero.o
-closeall.o close.o
-exec_sun.o close.o
-open.o devopen.o
-dvma.o alloc.o
-nfs.o alloc.o
-ufs.o alloc.o
-gets.o promcons.o
-getfile.o gets.o
-net.o clock.o
-net.o in_cksum.o
-arp.o net.o
-ether.o netif.o
-ether.o netif.o
-net.o globals.o
-rarp.o globals.o
-exec_sun.o open.o
-getfile.o open.o
-arp.o panic.o
-exec_sun.o panic.o
-net.o panic.o
-netif.o panic.o
-arp.o printf.o
-bootparam.o printf.o
-exec_sun.o printf.o
-getfile.o printf.o
-net.o printf.o
-netif.o printf.o
-nfs.o printf.o
-panic.o printf.o
-rarp.o printf.o
-rpc.o printf.o
-gets.o promcons.o
-printf.o promcons.o
-exec_sun.o read.o
-arp.o ether.o
-net.o ether.o
-rarp.o ether.o
-rpc.o net.o
-bootparam.o rpc.o
-nfs.o rpc.o
-bootparam.o rpc.o
-bootparam.o rpc.o
-bootparam.o rpc.o
-nfs.o rpc.o
-arp.o ether.o
-net.o ether.o
-rarp.o ether.o
-arp.o net.o
-rarp.o net.o
-rpc.o net.o
-rpc.o net.o
-bootparam.o netif.o
-nfs.o netif.o
-rarp.o netif.o
-strerror.o printf.o
-ufs.o strcmp.o
-rpc.o strerror.o
-bootparam.o strlen.o
-nfs.o strlen.o
-ufs.o strlen.o
-nfs.o printf.o
-read.o printf.o
-ufs.o printf.o
diff --git a/sys/arch/mvme88k/stand/libsa/log2 b/sys/arch/mvme88k/stand/libsa/log2
deleted file mode 100644 (file)
index 31ecde3..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-promboot.o
-dvma.o
-exec_sun.o
-fstat.o
-nullfs.o
-dkcksum.o
-dev.o
-closeall.o
-lseek.o
-ufs.o
-read.o
-getfile.o
-close.o
-memcpy.o
-rarp.o
-bootparam.o
-nfs.o
-gets.o
-strlen.o
-strcmp.o
-ashrdi3.o
-open.o
-alloc.o
-rpc.o
-devopen.o
-strerror.o
-arp.o
-net.o
-clock.o
-in_cksum.o
-ether.o
-bcmp.o
-globals.o
-bcopy.o
-netif.o
-panic.o
-bzero.o
-printf.o
-promcons.o
diff --git a/sys/arch/mvme88k/stand/netboot/netboot b/sys/arch/mvme88k/stand/netboot/netboot
deleted file mode 100644 (file)
index 7f5f1fa..0000000
Binary files a/sys/arch/mvme88k/stand/netboot/netboot and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/netboot/netboot.bin b/sys/arch/mvme88k/stand/netboot/netboot.bin
deleted file mode 100644 (file)
index 41093b7..0000000
Binary files a/sys/arch/mvme88k/stand/netboot/netboot.bin and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/obj.m88k/boot b/sys/arch/mvme88k/stand/obj.m88k/boot
deleted file mode 100644 (file)
index 30d5f26..0000000
Binary files a/sys/arch/mvme88k/stand/obj.m88k/boot and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/obj.m88k/boot.1 b/sys/arch/mvme88k/stand/obj.m88k/boot.1
deleted file mode 100644 (file)
index 112b445..0000000
Binary files a/sys/arch/mvme88k/stand/obj.m88k/boot.1 and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/obj.m88k/boot.2 b/sys/arch/mvme88k/stand/obj.m88k/boot.2
deleted file mode 100644 (file)
index 6248ab1..0000000
Binary files a/sys/arch/mvme88k/stand/obj.m88k/boot.2 and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd b/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd
deleted file mode 100644 (file)
index 0696f4a..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd.bin b/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd.bin
deleted file mode 100644 (file)
index 5b6558d..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd.bin and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd.bug b/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd.bug
deleted file mode 100644 (file)
index e354e4d..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/bootsd/bootsd.bug and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/bootsd/sdboot b/sys/arch/mvme88k/stand/openbsd/bootsd/sdboot
deleted file mode 100644 (file)
index baf73ee..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/bootsd/sdboot and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/bootst/bootst b/sys/arch/mvme88k/stand/openbsd/bootst/bootst
deleted file mode 100644 (file)
index 53c7665..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/bootst/bootst and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/bootst/bootst.bug b/sys/arch/mvme88k/stand/openbsd/bootst/bootst.bug
deleted file mode 100644 (file)
index 34dbd27..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/bootst/bootst.bug and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/bootst/stboot b/sys/arch/mvme88k/stand/openbsd/bootst/stboot
deleted file mode 100644 (file)
index a6b19b3..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/bootst/stboot and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/libbug/log1 b/sys/arch/mvme88k/stand/openbsd/libbug/log1
deleted file mode 100644 (file)
index 448b6b7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-delay.o delay.o
-diskrd.o diskrd.o
-diskwr.o diskwr.o
-getbrdid.o getbrdid.o
-instat.o instat.o
-outln.o outln.o
-outstr.o outstr.o
-return.o return.o
-rtc_rd.o rtc_rd.o
diff --git a/sys/arch/mvme88k/stand/openbsd/libbug/log2 b/sys/arch/mvme88k/stand/openbsd/libbug/log2
deleted file mode 100644 (file)
index 7a8950e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-rtc_rd.o
-return.o
-outstr.o
-outln.o
-instat.o
-getbrdid.o
-diskwr.o
-diskrd.o
-delay.o
diff --git a/sys/arch/mvme88k/stand/openbsd/libsa/log1 b/sys/arch/mvme88k/stand/openbsd/libsa/log1
deleted file mode 100644 (file)
index 1704777..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-nfs.o nfs.o
-rpc.o rpc.o
-net.o net.o
-ether.o ether.o
-arp.o arp.o
-in_cksum.o in_cksum.o
-netif.o netif.o
-bootparam.o bootparam.o
-rarp.o rarp.o
-alloc.o alloc.o
-bcopy.o bcopy.o
-memcpy.o memcpy.o
-close.o close.o
-getfile.o getfile.o
-open.o open.o
-printf.o printf.o
-read.o read.o
-strerror.o strerror.o
-ufs.o ufs.o
-globals.o globals.o
-lseek.o lseek.o
-closeall.o closeall.o
-dev.o dev.o
-dkcksum.o dkcksum.o
-nullfs.o nullfs.o
-fstat.o fstat.o
-ashrdi3.o ashrdi3.o
-bcmp.o bcmp.o
-bzero.o bzero.o
-strcmp.o strcmp.o
-strlen.o strlen.o
-exec_sun.o exec_sun.o
-clock.o clock.o
-devopen.o devopen.o
-dvma.o dvma.o
-gets.o gets.o
-panic.o panic.o
-promboot.o promboot.o
-promcons.o promcons.o
-ufs.o ashrdi3.o
-dvma.o alloc.o
-nfs.o alloc.o
-ufs.o alloc.o
-net.o arp.o
-net.o arp.o
-arp.o globals.o
-ether.o globals.o
-rarp.o globals.o
-arp.o bcmp.o
-ether.o bcmp.o
-rarp.o bcmp.o
-arp.o bcopy.o
-bootparam.o bcopy.o
-ether.o bcopy.o
-exec_sun.o bcopy.o
-memcpy.o bcopy.o
-net.o bcopy.o
-nfs.o bcopy.o
-rarp.o bcopy.o
-ufs.o bcopy.o
-arp.o bzero.o
-net.o bzero.o
-netif.o bzero.o
-nfs.o bzero.o
-rarp.o bzero.o
-rpc.o bzero.o
-ufs.o bzero.o
-closeall.o close.o
-exec_sun.o close.o
-open.o devopen.o
-dvma.o alloc.o
-nfs.o alloc.o
-ufs.o alloc.o
-gets.o promcons.o
-getfile.o gets.o
-net.o clock.o
-net.o in_cksum.o
-arp.o net.o
-ether.o netif.o
-ether.o netif.o
-net.o globals.o
-rarp.o globals.o
-exec_sun.o open.o
-getfile.o open.o
-arp.o panic.o
-exec_sun.o panic.o
-net.o panic.o
-netif.o panic.o
-arp.o printf.o
-bootparam.o printf.o
-exec_sun.o printf.o
-getfile.o printf.o
-net.o printf.o
-netif.o printf.o
-nfs.o printf.o
-panic.o printf.o
-rarp.o printf.o
-rpc.o printf.o
-gets.o promcons.o
-printf.o promcons.o
-exec_sun.o read.o
-arp.o ether.o
-net.o ether.o
-rarp.o ether.o
-rpc.o net.o
-bootparam.o rpc.o
-nfs.o rpc.o
-bootparam.o rpc.o
-bootparam.o rpc.o
-bootparam.o rpc.o
-nfs.o rpc.o
-arp.o ether.o
-net.o ether.o
-rarp.o ether.o
-arp.o net.o
-rarp.o net.o
-rpc.o net.o
-rpc.o net.o
-bootparam.o netif.o
-nfs.o netif.o
-rarp.o netif.o
-strerror.o printf.o
-ufs.o strcmp.o
-rpc.o strerror.o
-bootparam.o strlen.o
-nfs.o strlen.o
-ufs.o strlen.o
-nfs.o printf.o
-read.o printf.o
-ufs.o printf.o
diff --git a/sys/arch/mvme88k/stand/openbsd/libsa/log2 b/sys/arch/mvme88k/stand/openbsd/libsa/log2
deleted file mode 100644 (file)
index 31ecde3..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-promboot.o
-dvma.o
-exec_sun.o
-fstat.o
-nullfs.o
-dkcksum.o
-dev.o
-closeall.o
-lseek.o
-ufs.o
-read.o
-getfile.o
-close.o
-memcpy.o
-rarp.o
-bootparam.o
-nfs.o
-gets.o
-strlen.o
-strcmp.o
-ashrdi3.o
-open.o
-alloc.o
-rpc.o
-devopen.o
-strerror.o
-arp.o
-net.o
-clock.o
-in_cksum.o
-ether.o
-bcmp.o
-globals.o
-bcopy.o
-netif.o
-panic.o
-bzero.o
-printf.o
-promcons.o
diff --git a/sys/arch/mvme88k/stand/openbsd/netboot/netboot b/sys/arch/mvme88k/stand/openbsd/netboot/netboot
deleted file mode 100644 (file)
index 7f5f1fa..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/netboot/netboot and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/netboot/netboot.bin b/sys/arch/mvme88k/stand/openbsd/netboot/netboot.bin
deleted file mode 100644 (file)
index 41093b7..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/netboot/netboot.bin and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/sboot/rboot b/sys/arch/mvme88k/stand/openbsd/sboot/rboot
deleted file mode 100644 (file)
index e3a83b1..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-S00A0000000072626F6F74CF
-S32500004000424F4F540000003C00000044564D453134372072626F6F7420436F70797269671F
-S325000040206874202863292031393935205468656F2064652052616164740000004EF9FFA047
-S325000040400046229C0000207C000040207000421853806A00FFFA247CFFA01908227C00005C
-S325000040604000700012DA53806A00FFFA6000000213FC00000000463C600813FC00010000FD
-S32500004080463C2E7C00006FF04EB9FFA000B84E750A73626F6F743A204D564D4531343720F2
-S325000040A0626F6F7473747261702070726F6772616D0A003E3E3E20004E56FF802F0A61FF64
-S325000040C0FFFFFFCE1D7C0030FF80487AFFC461FF0000159E584F45EEFF80487AFFD761FFDE
-S325000040E00000158E2F0A61FF000013F82F0A610001CA504F584F60E24E714E5600004E4F86
-S3250000410000634E5E4E754D7920697020616464726573732069733A2025642E25642E2564B5
-S325000041202E25640A0053657276657220697020616464726573732069733A2025642E2564AC
-S325000041402E25642E25640A004661696C65642E0A0065786974696E6720746F20524F4D0A51
-S3250000416000446F776E6C6F6164204661696C65640A00446F776E6C6F61642077617320616E
-S325000041802073756363657373210A00636C69656E7420495020616464726573732025642EC0
-S325000041A025642E25642E25640A0073657276657220495020616464726573732025642E25A6
-S325000041C0642E25642E25640A005245564152503A204661696C65642E0A00726563656976D8
-S325000041E06564207365636F6E6461727920626F6F742070726F6772616D2E0A0062736400AB
-S3250000420076616C696420636F6D6D616E64730A0061202D2073656E64206120524152500AB4
-S325000042200062202D20626F6F74207468652073797374656D0A0071202D2065786974207499
-S325000042406F20524F4D0A0066202D206674702074686520626F6F742066696C650A0067202E
-S325000042602D20657865637574652074686520626F6F742066696C650A0068202D2068656CEB
-S32500004280700A0069202D20696E6974204C414E434520656E657420636869700A0073626FB3
-S325000042A06F743A2025733A20556E6B6E6F776E20636F6D6D616E640A00004E5600002F0BF2
-S325000042C02F0A246E000810120C000067670001F26E2E0C000062670000F86E180C000061BA
-S325000042E067364A00670001EC0C00003F67000192600001D40C000066670000AE600001C853
-S325000043000C000069670001B26D0001760C00007167000084600001B061FF0000054C4A8030
-S325000043206766428010390000465F2F00428010390000465E2F00428010390000465D2F0010
-S32500004340428010390000465C2F00487AFDBA45F9FFA0166E4E92428010390000463B2F0006
-S32500004360428010390000463A2F0042801039000046392F0042801039000046382F00487A4A
-S32500004380FDA54E926000014C487AFDBE61FF000012E06000013E487AFDB961FF000012D2BE
-S325000043A06100FD586000012C61FF000007127201B280660E487AFDAB61FF000012B4600032
-S325000043C00112487AFDAE61FF000012A66000010461FF00000F8061FF0000048E4A80660EBB
-S325000043E0487AFDE761FF00001288600000E6428010390000465F2F00428010390000465E43
-S325000044002F00428010390000465D2F00428010390000465C2F00487AFD7347F9FFA0166E19
-S325000044204E93428010390000463B2F00428010390000463A2F0042801039000046392F0067
-S3250000444042801039000046382F00487AFD5E4E93DEFC002861FF000006667201B2806608BF
-S32500004460487AFCFF4E93606A487AFD7061FF00001200584F524A4A12664645FAFD80604086
-S32500004480487AFD7E45F9FFA0166E4E92487AFD824E92487AFD8D4E92487AFD9C4E92487A4E
-S325000044A0FDA74E92487AFDB84E92487AFDCD4E92487AFDD14E92601A61FF00000E9860124D
-S325000044C02F0A613C600C2F0A487AFDD361FF000011A0246EFFF8266EFFFC4E5E4E756A7552
-S325000044E06D70696E6720746F20626F6F742070726F6772616D20617420307825782E0A001A
-S325000045004E56000048E7003C246E00083A7C70002F0D487AFFCA61FF0000115642804281B3
-S32500004520264A2F0A61FF0000108ED5C0284A4ED54CEE3C00FFF04E5E4E7500000000001FB1
-S32500004540003B005A0078009700B500D400F301110130014E4E56000048E73F30266E0008C5
-S325000045602C2E000C2A2E0010282E0014262E0018242E001C200BE880244045F20C00200ABF
-S32500004580720F2E0BC287244147F20A002006E880244045F20C00200A720FC286244145F2A6
-S325000045A00A002C0A2005E880244045F20C00200A720FC285244145F20A002A0A2004E88029
-S325000045C0244045F20C00200A720FC284244145F20A00280A2003E880244045F20C00200A09
-S325000045E0720FC283244145F20A00260A2002E880720FC282244045F20C00200A244145F25D
-S325000046000A44240A7E45BE826D027446200353807E0BBE80650A200453807E1EBE80640487
-S325000046204280607293C97046B4806F1C307C016E223C0000016DE8C007826604D3C8600290
-S32500004640D3C15280B4806EEE41FAFEF030703A00D1C443F098FFE8C0078266087E02BE839C
-S325000046606C02524943F19A0020092200E98192802401E9829481EF822005E7809085EB8074
-S32500004680D085E9802042D1C02006E980908641F00C002008D08B4CEE0CFCFFE04E5E4E756E
-S325000046A04E56000048E73E0020790000400010100000004010801C2800011A280002182851
-S325000046C000031628000514280006122800071010020000BF108042A71F41000342A71F4204
-S325000046E0000342A71F43000342A71F44000342A71F45000342A71F4600036100FE584CEE82
-S32500004700007CFFEC4E5E4E754E5600002F0A428020790000400411BC00FF08005280720524
-S32500004720B2806CEC487800062239000040045C812F0148790000465445F9FFA015D04E927A
-S32500004740207900004004317C8035000C20790000400830BC0001317C08000002117C0006F0
-S325000047600004207900004008117C00040005207900004008317C0003000648780006223900
-S325000047800000400850812F014879000046544E92487800067212D2B9000040082F01487981
-S325000047A0000046544E924280DEFC0024207900004008423008184230080E52807203B28045
-S325000047C06CEA4878004C48790000402861FF00000910246EFFFC4E5E4E754E5600002F0AF6
-S325000047E0487800064878060048790000402861FF00000A6E207900004004504F584F0C688F
-S325000048008035000C66562079000040080C680004000666484878000448790000465C721857
-S32500004820D2882F0145F9FFA015D04E9248780004487900004638720ED2B9000040082F01C0
-S325000048404E924878000648790000463022390000400850812F014E92700160024280246ECA
-S32500004860FFFC4E5E4E754E5600002F0242826100FE986100FF664A8067047001600A52828E
-S325000048807204B2826CE84280242EFFFC4E5E4E75000178787878787878782E6D766D6536BC
-S325000048A0386B006F6374657400003031323334353637383941424344454600004E56FFFCEF
-S325000048C048E73038242E0008663228790000401447EC001961FFFFFFFDCA33C0000046406A
-S325000048E00C7903E7000046406208067903E80000464033FC00450000462C60082679000076
-S325000049004018584B487800062F390000400448790000463045F9FFA015D04E924878000685
-S325000049202639000040045C832F034879000046544E92207900004004317C0800000C20794B
-S325000049400000400C7604EFD0300420790000400C7605EFD0310420790000400C42280001F4
-S3250000496020790000400C42680004317C40000006117C0003000820790000400C117C001190
-S32500004980000948780004760CD6B90000400C2F0348790000465C4E92DEFC00202EBC00008E
-S325000049A000047610D6B90000400C2F034879000046384E9220790000400C4268000A384B1F
-S325000049C098F90000400E314C000242A7487800142F0861FF00000A5C20790000400C46404E
-S325000049E03140000A20790000401030B90000464031790000462C000242680006DEFC00181E
-S32500004A004A82671020790000401830BC000431420002605448780004486EFFFC487900000D
-S32500004A20465C45F9FFA015D04E92487800192F3900004014487AFE5A4E927209DEFC001830
-S32500004A4043FAFE68207900004014700FC0AEFFFC11B108001800202EFFFCE8882D40FFFCD5
-S32500004A6053817601B68165DC207900004010384B98F900004012314C000497FC00004028A2
-S32500004A802F0B48790000402861FF000006544CEE1C0CFFE84E5E4E750A002578200D005413
-S32500004AA04654503A20446F776E6C6F6164206572726F722025643A2025730A004E560000E1
-S32500004AC048E73C304282283C0000700042B90000462842A76100FDE6584F428348780005D6
-S32500004AE04878060048790000402861FF00000772504F584F4A8066304AB900004628670862
-S32500004B002F3900004628600242A76100FDB0584F52827A05BA826CC4487AFF7E61FF00005B
-S32500004B200B5070016000010020790000401C3628000220037A09EBA02F00487AFF5E61FF0E
-S32500004B4000000B2E207900004004504F0C680800000C667820790000400C0C280011000901
-S32500004B60666A0C7900450000462C660C20790000401033D00000462C20790000401C0C5002
-S32500004B800005661E2A0858852F054280302800022F00487AFF0B61FF00000AD6700160001B
-S32500004BA0008620790000401C4280302800022239000046285281B28067186F042F00600603
-S32500004BC02F39000046286100FCF4584F52826000FF0C4282203900004628528023C0000082
-S32500004BE04628207900004010366800042F006100FCCC45EBFFF42F0A2F042A390000401C10
-S32500004C0058852F0561FF000009CAD88A504F504FB7FC0000020B6E00FEC4487AFE7C61FF1E
-S32500004C2000000A4E42804CEE0C3CFFE84E5E4E756C65303A206265656E20626162626C690B
-S32500004C406E672C20666F756E6420627920272573270A006C65303A206D656D6F727920658D
-S32500004C6072726F7220696E20272573270A004E5600002F0A2F02242E0008246E000C30121A
-S32500004C800800000E67142F02487AFFA661FF000009E061FFFFFFF466504F30120800000DEE
-S32500004CA0670434BC200030120800000C670434BC100030120800000B67122F02487AFF955D
-S32500004CC061FF000009AC61FFFFFFF432242EFFF8246EFFFC4E5E4E756C65303A20696E6955
-S32500004CE0742074696D656F75742C2073746174203D20307825780A004E56000048E73C3CF4
-S32500004D00246E0008287900004644267900004648283C000186A0426C000238BC00044878A8
-S32500004D2035BE2F0B61FF000008E64253176A0001000217520003176A00030004176A000262
-S32500004D400005176A00050006176A0004000742AB000842AB000C7418D48B2002424048402B
-S32500004D600040600037400012374200107458D48B2002424048403740001637420014397C55
-S32500004D8000010002388B397C00020002200B42404840388091C8504F4BF08A00200DEB804C
-S32500004DA09088E78090884BF30A60240D2208E7813782181817BC0080181A20024240484051
-S32500004DC01780181B37BCFA12181C4273181E52487A07BA886CC291C8327C2FD04BF08A008F
-S32500004DE0200DEB809088E78090884BF10A00200D240BD4802208E781378218584233185AE6
-S32500004E002002424048401780185B4273185C4273185E52484A886FC4397C0003000238BCB5
-S32500004E200004426C000238BC00015384660E2F03487AFEA661FF00000838600C30144283CB
-S32500004E4036000803000867E238BC010042B90000464C42B900004650426C000238BC000201
-S32500004E604CEE3C3CFFE04E5E4E756C655F706F6C6C006C65305F706F6C6C3A20726D642071
-S32500004E8073746174757320307825780A006C655F706F6C6C3A20636861696E6564207061FB
-S32500004EA0636B65740A0063737230207768656E20626164207468696E6773206861707065CF
-S32500004EC06E3A2025780A00004E56000048E72038267900004644287900004648426B00022B
-S32500004EE030130800000A670436BC040020390000464C45F40E18102A00026C0642806000DC
-S32500004F0000F630136C0C2F0B487AFF606100FD60504F102A0002080000066718102A00021D
-S32500004F2042A71F400003487AFF4A61FF0000074242826078102A0002020000030C00000380
-S32500004F406712487AFF4961FF0000072661FFFFFFF1AC584F302A0006428234000C820000B3
-S32500004F6005ED6F1A428230133F004267487AFF3861FF000006FC61FFFFFFF182602E4A823B
-S32500004F80672A59824A826F242F022F2E000820790000464C43F08A002009EB809088E780AF
-S32500004FA0908848740A6061FF0000062820790000464C43F08A002009EB809088E78090880C
-S32500004FC049F40A60200C34804240484015400003357CFA12000441F90000464C428072071A
-S32500004FE0B290670820390000464C52802080157C0080000220024CEE1C04FFF04E5E4E75B0
-S325000050006C655F70757428776179206265666F726520786D697429006C65303A206F757437
-S325000050207075742062756666657220627573790A006C655F707574286265666F72652078CE
-S325000050406D697429006C655F70757428616674657220786D697429006C65303A2074726167
-S325000050606E736D69742074696D656F75742C2073746174203D20307825780A006C655F7064
-S3250000508075742874696D656F757429006C655F7075743A20786D6974206572726F722C208E
-S325000050A06275662025640A006C655F70757428786D6974206572726F7229006C65303A20B9
-S325000050C07472616E736D6974206572726F722C206572726F72203D20307825780A004E5628
-S325000050E0000048E73838282E000C247900004644287900004648263C000186A0426A00021C
-S3250000510030126C0C2F0A487AFEF86100FB62504F20390000465047F40E58600C487AFEFACB
-S3250000512061FF0000054C584F102B00026DEE2F0420790000465043F08A002009EB809088AE
-S32500005140E7809088D080068000002FD0487408002F2E000861FF0000047A504F584F723FF7
-S32500005160B2846508377CFFC0000460083004444037400004426B000630126C0C2F0A487A0D
-S32500005180FEB16100FAEA504F177C0083000220790000465043F08A002009EB809088E7805F
-S325000051A09088D080068000002FD0D08C3680424048401740000334BC000830126C0C2F0A9B
-S325000051C0487AFE836100FAA8504F538366202F02487AFE8661FF000004983012504F6C1AAE
-S325000051E02F0A487AFE986100FA86504F600C3012428234000802000967D034BC0200301274
-S325000052006C2A3012024078000C40200067122F3900004650487AFE7661FF00000454504F86
-S325000052202F0A487AFE846100FA46504F42B900004650102B000208000006660420046014CD
-S32500005240302B00063F004267487AFE7161FF0000042070FF4CEE1C1CFFE84E5E4E754E566F
-S32500005260000048E73E20246E00082C2E000C242E001061FFFFFFF42C2A00DA8242844283AA
-S3250000528061FFFFFFF41E2400BA826F624A83665E2F062F0A6100FC322600504FB484670273
-S325000052A028024A8367DA1212B2390000465466CE122A0001B2390000465566C2122A0002AA
-S325000052C0B2390000465666B6122A0003B2390000465766AA122A0004B23900004658669E81
-S325000052E0122A0005B239000046596794609020034CEE047CFFE84E5E4E754552524F523AFB
-S325000053002065746865726E65742061646472657373206E6F74207365742120205573652077
-S325000053204C5341442E0A006C65303A2065746865726E657420616464726573733A20257854
-S325000053403A25783A25783A25783A25783A25780A00004E5600002F0A2F022439FFFE077823
-S32500005360200202802FFFFF000C802FFFFF006612487AFF8861FF000002F861FFFFFFED7EB9
-S32500005380584F45F90000465414BC000842390000465513FC003E00004656E08A43F900000B
-S325000053A046591282E08A41F9000046581082E08A13C200004657428010112F004280101010
-S325000053C02F002F024878003E42A748780008487AFF5761FF0000029A487800104879000013
-S325000053E0464461FF0000022823FCFFFE1800000046442239FFFE07740681FFF0000023C1A8
-S3250000540000004648DEFC00202E8A6100F8EC242EFFF8246EFFFC4E5E4E754E56000020797F
-S32500005420000046444268000230BC00044E5E4E75206F0004222F0008202F000C2F02080150
-S3250000544000006674080100016600008A2401EC8902820000003C4482023C000F4EFB284252
-S325000054602418D1822418D1822418D1822418D1822418D1822418D1822418D1822418D182AE
-S325000054802418D1822418D1822418D1822418D1822418D1822418D1822418D1822418D1828E
-S325000054A051C9FFBE22004841D1416402524002800000FFFF241F4E75080100016708428297
-S325000054C0343018FDD0824282143018FFE18AD0826000FF7A4282343018FED0826000FF6EE9
-S325000054E04E56000048E73038262E0008264349F9FFA018E261FF000003C2747FC4802F023E
-S325000055004E94584F7215B282670000886D20720AB282670000946D087208B2826738602ACE
-S32500005520720DB282677C7212B2826740601C7223B28267306D087217B2826756600C724087
-S32500005540B282674E727FB282670416C260A6487800084E94584F487800204E944878000813
-S325000055604E94504FB68B648C534B60884878000A4E942443584FB7CA6300FF7A121A49C1A0
-S325000055802F0161FF0000035E584FB7CA62EE6000FF644878000A61FF0000034A584F60005B
-S325000055A0FF4C4878000A4E9442134CEE1C0CFFEC4E5E4E754E560000226E000820494A11DD
-S325000055C0670652484A1066FA200890894E5E4E754E560000222E0010226E0008206E000C1E
-S325000055E0B1C9631AD3C1D1C1200153814A8067161121200153814A8066F6600A10D920018B
-S3250000560053814A8066F64E5E4E7500004E560000206E0008202E000C538072FFB280670C9E
-S32500005620421851C8FFFC4240538064F44E5E4E754E56000020790000402410AE000B52B965
-S32500005640000040244E5E4E754E56000023EE000800004024486E00102F2E000C487AFFD28E
-S32500005660612420790000402442104E5E4E754E560000486E000C2F2E00084879FFA018E2BC
-S3250000568061044E5E4E754E56000048E7303C2A6E0008286E000C266E0010594B600C4A822F
-S325000056A0670001782F024E95584F141C49C27625B68266EA95CA141C49C2224241E9FF9E26
-S325000056C07616B6886500013A303B8A064EFB0002003400A200CA013001300130013001307F
-S325000056E001300130002E0130013000EE01300130013000AE0130010401300130011A347C20
-S32500005700000160B2584B241B2453161A49C32F032F022F0D61000120504F584F4A82678AB7
-S3250000572091C8603A53817001E3A0C082672A703C4A886702702C2F004E95584F60082F0101
-S325000057404E95584F524A121249C17620B6816DEE307C00016008524A0C1200206EF8121A46
-S3250000576049C166C04A886700FF424878003E6000FF36584B767FC6932F036000FF2A584B97
-S325000057802453141A49C26700FF222F024E95584F141A49C266F46000FF12584B24136C0ABC
-S325000057A04878002D4E954482584F4878000A2F022F0D61000082504F584F6000FEEE584B57
-S325000057C02413487800082F022F0D616A504F584F6000FED8584B24134878000A2F022F0DFF
-S325000057E06154504F584F6000FEC2584B2413487800102F022F0D613E504F584F6000FEAC82
-S32500005800487800254E95584F4A8A6700FE984878006C4E95584F6000FE8C4CEE3C0CFFE839
-S325000058204E5E4E753031323334353637383961626364656600004E56FFF448E73038286ECD
-S325000058400008222E000C242E001045EEFFF441FAFFD44C42100014F008004A8166F447EE44
-S32500005860FFF4162249C32F034E94584FB7CA65F24CEE1C0CFFE04E5E4E757C2F2D5C000074
-S325000058804E5600002F0A7003C0B90000402041FAFFEA1030080049C02F0052B900004020CA
-S325000058A045F9FFA018E24E92487800084E92246EFFFC4E5E4E7500004E5600001F3C000088
-S325000058C04E4F0000101F49C04E5E4E754E56000042814E4F000167000004720142804E5E2D
-S325000058E04E754E5600002F02242E0008700AB08266064878000D61EA1F024E4F0020242E50
-S32500005900FFFC4E5E4E750000FFFE07F80000402800004036000040360000404A00004052AB
-S30D00005920000040520000405255
-S70300004000BB
diff --git a/sys/arch/mvme88k/stand/openbsd/sboot/rboot.tmp b/sys/arch/mvme88k/stand/openbsd/sboot/rboot.tmp
deleted file mode 100644 (file)
index db9793d..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/sboot/rboot.tmp and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/sboot/sboot b/sys/arch/mvme88k/stand/openbsd/sboot/sboot
deleted file mode 100644 (file)
index 5d797b7..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-S00A0000000073626F6F74CE
-S3250000400013FC000000005ED4600813FC000100005ED42E7C00006FF04EB9000040484E7554
-S325000040200A73626F6F743A204D564D4531343720626F6F7473747261702070726F67726175
-S325000040406D0A003E3E3E20004E56FF802F0A61FFFFFFFFCE1D7C0030FF80487AFFC461FF55
-S325000040600000159E584F45EEFF80487AFFD761FF0000158E2F0A61FF000013F82F0A610055
-S3250000408001CA504F584F60E24E714E5600004E4F00634E5E4E754D7920697020616464727B
-S325000040A06573732069733A2025642E25642E25642E25640A005365727665722069702061B0
-S325000040C06464726573732069733A2025642E25642E25642E25640A004661696C65642E0ACA
-S325000040E00065786974696E6720746F20524F4D0A00446F776E6C6F6164204661696C65640A
-S325000041000A00446F776E6C6F61642077617320612073756363657373210A00636C69656E1C
-S325000041207420495020616464726573732025642E25642E25642E25640A00736572766572D7
-S3250000414020495020616464726573732025642E25642E25642E25640A005245564152503AB8
-S32500004160204661696C65642E0A007265636569766564207365636F6E6461727920626F6F0D
-S32500004180742070726F6772616D2E0A006273640076616C696420636F6D6D616E64730A0090
-S325000041A061202D2073656E64206120524152500A0062202D20626F6F7420746865207379B1
-S325000041C07374656D0A0071202D206578697420746F20524F4D0A0066202D206674702074B2
-S325000041E0686520626F6F742066696C650A0067202D20657865637574652074686520626F35
-S325000042006F742066696C650A0068202D2068656C700A0069202D20696E6974204C414E439B
-S325000042204520656E657420636869700A0073626F6F743A2025733A20556E6B6E6F776E2016
-S32500004240636F6D6D616E640A00004E5600002F0B2F0A246E000810120C000067670001F2CF
-S325000042606E2E0C000062670000F86E180C00006167364A00670001EC0C00003F670001925C
-S32500004280600001D40C000066670000AE600001C80C000069670001B26D0001760C00007143
-S325000042A067000084600001B061FF0000054C4A8067664280103900005EF72F00428010391A
-S325000042C000005EF62F004280103900005EF52F004280103900005EF42F00487AFDBA45F985
-S325000042E0000055FE4E924280103900005ED32F004280103900005ED22F00428010390000A5
-S325000043005ED12F004280103900005ED02F00487AFDA54E926000014C487AFDBE61FF000003
-S3250000432012E06000013E487AFDB961FF000012D26100FD586000012C61FF000007127201FB
-S32500004340B280660E487AFDAB61FF000012B460000112487AFDAE61FF000012A660000104C4
-S3250000436061FF00000F8061FF0000048E4A80660E487AFDE761FF00001288600000E6428070
-S32500004380103900005EF72F004280103900005EF62F004280103900005EF52F004280103924
-S325000043A000005EF42F00487AFD7347F9000055FE4E934280103900005ED32F00428010395A
-S325000043C000005ED22F004280103900005ED12F004280103900005ED02F00487AFD5E4E93A9
-S325000043E0DEFC002861FF000006667201B2806608487AFCFF4E93606A487AFD7061FF0000DF
-S325000044001200584F524A4A12664645FAFD806040487AFD7E45F9000055FE4E92487AFD82EE
-S325000044204E92487AFD8D4E92487AFD9C4E92487AFDA74E92487AFDB84E92487AFDCD4E9226
-S32500004440487AFDD14E92601A61FF00000E9860122F0A613C600C2F0A487AFDD361FF000087
-S3250000446011A0246EFFF8266EFFFC4E5E4E756A756D70696E6720746F20626F6F742070722B
-S325000044806F6772616D20617420307825782E0A004E56000048E7003C246E00083A7C70009F
-S325000044A02F0D487AFFCA61FF0000115642804281264A2F0A61FF0000108ED5C0284A4ED512
-S325000044C04CEE3C00FFF04E5E4E7500000000001F003B005A0078009700B500D400F30111B1
-S325000044E00130014E4E56000048E73F30266E00082C2E000C2A2E0010282E0014262E0018B4
-S32500004500242E001C200BE880244045F20C00200A720F2E0BC287244147F20A002006E8808A
-S32500004520244045F20C00200A720FC286244145F20A002C0A2005E880244045F20C00200AA1
-S32500004540720FC285244145F20A002A0A2004E880244045F20C00200A720FC284244145F2F3
-S325000045600A00280A2003E880244045F20C00200A720FC283244145F20A00260A2002E88077
-S32500004580720FC282244045F20C00200A244145F20A44240A7E45BE826D0274462003538045
-S325000045A07E0BBE80650A200453807E1EBE8064044280607293C97046B4806F1C307C016E06
-S325000045C0223C0000016DE8C007826604D3C86002D3C15280B4806EEE41FAFEF030703A0078
-S325000045E0D1C443F098FFE8C0078266087E02BE836C02524943F19A0020092200E981928058
-S325000046002401E9829481EF822005E7809085EB80D085E9802042D1C02006E980908641F0EB
-S325000046200C002008D08B4CEE0CFCFFE04E5E4E754E56000048E73E0020790000589810109B
-S325000046400000004010801C2800011A280002182800031628000514280006122800071010D2
-S32500004660020000BF108042A71F41000342A71F42000342A71F43000342A71F44000342A7C4
-S325000046801F45000342A71F4600036100FE584CEE007CFFEC4E5E4E754E5600002F0A4280F6
-S325000046A020790000589C11BC00FF080052807205B2806CEC4878000622390000589C5C81CE
-S325000046C02F01487900005EEC45F9000055604E9220790000589C317C8035000C2079000032
-S325000046E058A030BC0001317C08000002117C000600042079000058A0117C000400052079C1
-S32500004700000058A0317C00030006487800062239000058A050812F01487900005EEC4E92E0
-S32500004720487800067212D2B9000058A02F01487900005EEC4E924280DEFC00242079000032
-S3250000474058A0423008184230080E52807203B2806CEA4878004C4879000058C061FF00002D
-S325000047600910246EFFFC4E5E4E754E5600002F0A48780006487806004879000058C061FF7C
-S3250000478000000A6E20790000589C504F584F0C688035000C66562079000058A00C680004CE
-S325000047A00006664848780004487900005EF47218D2882F0145F9000055604E9248780004BD
-S325000047C0487900005ED0720ED2B9000058A02F014E9248780006487900005EC822390000C9
-S325000047E058A050812F014E92700160024280246EFFFC4E5E4E754E5600002F02428261004F
-S32500004800FE986100FF664A8067047001600A52827204B2826CE84280242EFFFC4E5E4E75D6
-S32500004820000178787878787878782E6D766D6536386B006F637465740000303132333435A7
-S325000048403637383941424344454600004E56FFFC48E73038242E000866322879000058AC12
-S3250000486047EC001961FFFFFFFDCA33C000005ED80C7903E700005ED86208067903E800001F
-S325000048805ED833FC004500005EC460082679000058B0584B487800062F390000589C4879B1
-S325000048A000005EC845F9000055604E924878000626390000589C5C832F03487900005EECC4
-S325000048C04E9220790000589C317C0800000C2079000058A47604EFD030042079000058A40D
-S325000048E07605EFD031042079000058A4422800012079000058A442680004317C400000060D
-S32500004900117C000300082079000058A4117C0011000948780004760CD6B9000058A42F03BA
-S32500004920487900005EF44E92DEFC00202EBC000000047610D6B9000058A42F034879000092
-S325000049405ED04E922079000058A44268000A384B98F9000058A6314C000242A748780014AC
-S325000049602F0861FF00000A5C2079000058A446403140000A2079000058A830B900005ED8E6
-S32500004980317900005EC4000242680006DEFC00184A8267102079000058B030BC000431425A
-S325000049A00002605448780004486EFFFC487900005EF445F9000055604E92487800192F399F
-S325000049C0000058AC487AFE5A4E927209DEFC001843FAFE682079000058AC700FC0AEFFFC3E
-S325000049E011B108001800202EFFFCE8882D40FFFC53817601B68165DC2079000058A8384BCF
-S32500004A0098F9000058AA314C000497FC000058C02F0B4879000058C061FF000006544CEECA
-S32500004A201C0CFFE84E5E4E750A002578200D00544654503A20446F776E6C6F616420657257
-S32500004A40726F722025643A2025730A004E56000048E73C304282283C0000700042B9000086
-S32500004A605EC042A76100FDE6584F428348780005487806004879000058C061FF000007723C
-S32500004A80504F584F4A8066304AB900005EC067082F3900005EC0600242A76100FDB0584F54
-S32500004AA052827A05BA826CC4487AFF7E61FF00000B507001600001002079000058B4362862
-S32500004AC0000220037A09EBA02F00487AFF5E61FF00000B2E20790000589C504F0C6808000E
-S32500004AE0000C66782079000058A40C2800110009666A0C79004500005EC4660C207900001C
-S32500004B0058A833D000005EC42079000058B40C500005661E2A0858852F0542803028000281
-S32500004B202F00487AFF0B61FF00000AD67001600000862079000058B44280302800022239C1
-S32500004B4000005EC05281B28067186F042F0060062F3900005EC06100FCF4584F52826000F3
-S32500004B60FF0C4282203900005EC0528023C000005EC02079000058A8366800042F0061004B
-S32500004B80FCCC45EBFFF42F0A2F042A39000058B458852F0561FF000009CAD88A504F504F65
-S32500004BA0B7FC0000020B6E00FEC4487AFE7C61FF00000A4E42804CEE0C3CFFE84E5E4E7571
-S32500004BC06C65303A206265656E20626162626C696E672C20666F756E642062792027257347
-S32500004BE0270A006C65303A206D656D6F7279206572726F7220696E20272573270A004E5695
-S32500004C0000002F0A2F02242E0008246E000C30120800000E67142F02487AFFA661FF000061
-S32500004C2009E061FFFFFFF466504F30120800000D670434BC200030120800000C670434BCAB
-S32500004C40100030120800000B67122F02487AFF9561FF000009AC61FFFFFFF432242EFFF807
-S32500004C60246EFFFC4E5E4E756C65303A20696E69742074696D656F75742C207374617420D4
-S32500004C803D20307825780A004E56000048E73C3C246E0008287900005EDC267900005EE0C5
-S32500004CA0283C000186A0426C000238BC0004487835BE2F0B61FF000008E64253176A000169
-S32500004CC0000217520003176A00030004176A00020005176A00050006176A0004000742AB4B
-S32500004CE0000842AB000C7418D48B2002424048400040600037400012374200107458D48BB9
-S32500004D002002424048403740001637420014397C00010002388B397C00020002200B424066
-S32500004D204840388091C8504F4BF08A00200DEB809088E78090884BF30A60240D2208E781D6
-S32500004D403782181817BC0080181A2002424048401780181B37BCFA12181C4273181E524831
-S32500004D607A07BA886CC291C8327C2FD04BF08A00200DEB809088E78090884BF10A00200DCF
-S32500004D80240BD4802208E781378218584233185A2002424048401780185B4273185C4273D4
-S32500004DA0185E52484A886FC4397C0003000238BC0004426C000238BC00015384660E2F0304
-S32500004DC0487AFEA661FF00000838600C3014428336000803000867E238BC010042B90000D0
-S32500004DE05EE442B900005EE8426C000238BC00024CEE3C3CFFE04E5E4E756C655F706F6C09
-S32500004E006C006C65305F706F6C6C3A20726D642073746174757320307825780A006C655F09
-S32500004E20706F6C6C3A20636861696E6564207061636B65740A0063737230207768656E2083
-S32500004E40626164207468696E67732068617070656E3A2025780A00004E56000048E72038B0
-S32500004E60267900005EDC287900005EE0426B000230130800000A670436BC040020390000B6
-S32500004E805EE445F40E18102A00026C064280600000F630136C0C2F0B487AFF606100FD60D1
-S32500004EA0504F102A0002080000066718102A000242A71F400003487AFF4A61FF0000074249
-S32500004EC042826078102A0002020000030C0000036712487AFF4961FF0000072661FFFFFF72
-S32500004EE0F1AC584F302A0006428234000C82000005ED6F1A428230133F004267487AFF381F
-S32500004F0061FF000006FC61FFFFFFF182602E4A82672A59824A826F242F022F2E0008207904
-S32500004F2000005EE443F08A002009EB809088E780908848740A6061FF0000062820790000F4
-S32500004F405EE443F08A002009EB809088E780908849F40A60200C3480424048401540000338
-S32500004F60357CFA12000441F900005EE442807207B2906708203900005EE452802080157C64
-S32500004F800080000220024CEE1C04FFF04E5E4E756C655F70757428776179206265666F727F
-S32500004FA06520786D697429006C65303A206F75747075742062756666657220627573790AE8
-S32500004FC0006C655F707574286265666F726520786D697429006C655F70757428616674654B
-S32500004FE07220786D697429006C65303A207472616E736D69742074696D656F75742C20737B
-S32500005000746174203D20307825780A006C655F7075742874696D656F757429006C655F70F4
-S3250000502075743A20786D6974206572726F722C206275662025640A006C655F7075742878B6
-S325000050406D6974206572726F7229006C65303A207472616E736D6974206572726F722C202A
-S325000050606572726F72203D20307825780A004E56000048E73838282E000C247900005EDCB8
-S32500005080287900005EE0263C000186A0426A000230126C0C2F0A487AFEF86100FB62504FEC
-S325000050A0203900005EE847F40E58600C487AFEFA61FF0000054C584F102B00026DEE2F0461
-S325000050C0207900005EE843F08A002009EB809088E7809088D080068000002FD0487408006A
-S325000050E02F2E000861FF0000047A504F584F723FB2846508377CFFC0000460083004444037
-S3250000510037400004426B000630126C0C2F0A487AFEB16100FAEA504F177C00830002207962
-S3250000512000005EE843F08A002009EB809088E7809088D080068000002FD0D08C36804240D2
-S3250000514048401740000334BC000830126C0C2F0A487AFE836100FAA8504F538366202F020A
-S32500005160487AFE8661FF000004983012504F6C1A2F0A487AFE986100FA86504F600C3012C1
-S32500005180428234000802000967D034BC020030126C2A3012024078000C40200067122F39B4
-S325000051A000005EE8487AFE7661FF00000454504F2F0A487AFE846100FA46504F42B900005E
-S325000051C05EE8102B000208000006660420046014302B00063F004267487AFE7161FF00005C
-S325000051E0042070FF4CEE1C1CFFE84E5E4E754E56000048E73E20246E00082C2E000C242ECB
-S32500005200001061FFFFFFF42C2A00DA824284428361FFFFFFF41E2400BA826F624A83665EB7
-S325000052202F062F0A6100FC322600504FB484670228024A8367DA1212B23900005EEC66CE40
-S32500005240122A0001B23900005EED66C2122A0002B23900005EEE66B6122A0003B2390000F2
-S325000052605EEF66AA122A0004B23900005EF0669E122A0005B23900005EF1679460902003C5
-S325000052804CEE047CFFE84E5E4E754552524F523A2065746865726E65742061646472657322
-S325000052A073206E6F7420736574212020557365204C5341442E0A006C65303A20657468658D
-S325000052C0726E657420616464726573733A2025783A25783A25783A25783A25783A25780AD5
-S325000052E000004E5600002F0A2F022439FFFE0778200202802FFFFF000C802FFFFF006612BF
-S32500005300487AFF8861FF000002F861FFFFFFED7E584F45F900005EEC14BC00084239000099
-S325000053205EED13FC003E00005EEEE08A43F900005EF11282E08A41F900005EF01082E08A0C
-S3250000534013C200005EEF428010112F00428010102F002F024878003E42A748780008487A60
-S32500005360FF5761FF0000029A48780010487900005EDC61FF0000022823FCFFFE180000004C
-S325000053805EDC2239FFFE07740681FFF0000023C100005EE0DEFC00202E8A6100F8EC242E19
-S325000053A0FFF8246EFFFC4E5E4E754E560000207900005EDC4268000230BC00044E5E4E7572
-S325000053C0206F0004222F0008202F000C2F02080100006674080100016600008A2401EC89D8
-S325000053E002820000003C4482023C000F4EFB28422418D1822418D1822418D1822418D182E5
-S325000054002418D1822418D1822418D1822418D1822418D1822418D1822418D1822418D1820E
-S325000054202418D1822418D1822418D1822418D18251C9FFBE22004841D1416402524002801C
-S325000054400000FFFF241F4E750801000167084282343018FDD0824282143018FFE18AD0825E
-S325000054606000FF7A4282343018FED0826000FF6E4E56000048E73038262E0008264349F9AE
-S325000054800000587261FF000003C2747FC4802F024E94584F7215B282670000886D20720A73
-S325000054A0B282670000946D087208B2826738602A720DB282677C7212B2826740601C722365
-S325000054C0B28267306D087217B2826756600C7240B282674E727FB282670416C260A64878D7
-S325000054E000084E94584F487800204E94487800084E94504FB68B648C534B60884878000A89
-S325000055004E942443584FB7CA6300FF7A121A49C12F0161FF0000035E584FB7CA62EE600039
-S32500005520FF644878000A61FF0000034A584F6000FF4C4878000A4E9442134CEE1C0CFFECEB
-S325000055404E5E4E754E560000226E000820494A11670652484A1066FA200890894E5E4E7565
-S325000055604E560000222E0010226E0008206E000CB1C9631AD3C1D1C1200153814A80671696
-S325000055801121200153814A8066F6600A10D9200153814A8066F64E5E4E7500004E56000037
-S325000055A0206E0008202E000C538072FFB280670C421851C8FFFC4240538064F44E5E4E7582
-S325000055C04E5600002079000058BC10AE000B52B9000058BC4E5E4E754E56000023EE000860
-S325000055E0000058BC486E00102F2E000C487AFFD261242079000058BC42104E5E4E754E5638
-S325000056000000486E000C2F2E000848790000587261044E5E4E754E56000048E7303C2A6E27
-S325000056200008286E000C266E0010594B600C4A82670001782F024E95584F141C49C27625C9
-S32500005640B68266EA95CA141C49C2224241E9FF9E7616B6886500013A303B8A064EFB000247
-S32500005660003400A200CA0130013001300130013001300130002E0130013000EE013001304D
-S32500005680013000AE0130010401300130011A347C000160B2584B241B2453161A49C32F03E8
-S325000056A02F022F0D61000120504F584F4A82678A91C8603A53817001E3A0C082672A703CB8
-S325000056C04A886702702C2F004E95584F60082F014E95584F524A121249C17620B6816DEE20
-S325000056E0307C00016008524A0C1200206EF8121A49C166C04A886700FF424878003E60001B
-S32500005700FF36584B767FC6932F036000FF2A584B2453141A49C26700FF222F024E95584F0C
-S32500005720141A49C266F46000FF12584B24136C0A4878002D4E954482584F4878000A2F02D7
-S325000057402F0D61000082504F584F6000FEEE584B2413487800082F022F0D616A504F584F72
-S325000057606000FED8584B24134878000A2F022F0D6154504F584F6000FEC2584B2413487827
-S3250000578000102F022F0D613E504F584F6000FEAC487800254E95584F4A8A6700FE98487897
-S325000057A0006C4E95584F6000FE8C4CEE3C0CFFE84E5E4E753031323334353637383961625B
-S325000057C06364656600004E56FFF448E73038286E0008222E000C242E001045EEFFF441FA46
-S325000057E0FFD44C42100014F008004A8166F447EEFFF4162249C32F034E94584FB7CA65F202
-S325000058004CEE1C0CFFE04E5E4E757C2F2D5C00004E5600002F0A7003C0B9000058B841FA8A
-S32500005820FFEA1030080049C02F0052B9000058B845F9000058724E92487800084E92246EBC
-S32500005840FFFC4E5E4E7500004E5600001F3C00004E4F0000101F49C04E5E4E754E560000F1
-S3250000586042814E4F000167000004720142804E5E4E754E5600002F02242E0008700AB082D7
-S3250000588066064878000D61EA1F024E4F0020242EFFFC4E5E4E750000FFFE07F8000058C0D0
-S31D000058A0000058CE000058CE000058E2000058EA000058EA000058EA9E
-S70300004000BB
diff --git a/sys/arch/mvme88k/stand/openbsd/sboot/sboot.tmp b/sys/arch/mvme88k/stand/openbsd/sboot/sboot.tmp
deleted file mode 100644 (file)
index a55acd6..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/sboot/sboot.tmp and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/sboot/srec b/sys/arch/mvme88k/stand/openbsd/sboot/srec
deleted file mode 100644 (file)
index a60b3c7..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/sboot/srec and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/openbsd/wrtvid/wrtvid b/sys/arch/mvme88k/stand/openbsd/wrtvid/wrtvid
deleted file mode 100644 (file)
index 565965f..0000000
Binary files a/sys/arch/mvme88k/stand/openbsd/wrtvid/wrtvid and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/prtvid/chklabel b/sys/arch/mvme88k/stand/prtvid/chklabel
deleted file mode 100644 (file)
index 05637c5..0000000
Binary files a/sys/arch/mvme88k/stand/prtvid/chklabel and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/prtvid/prtvid b/sys/arch/mvme88k/stand/prtvid/prtvid
deleted file mode 100644 (file)
index 10a4f71..0000000
Binary files a/sys/arch/mvme88k/stand/prtvid/prtvid and /dev/null differ
diff --git a/sys/arch/mvme88k/stand/wrtvid/Makefile,v b/sys/arch/mvme88k/stand/wrtvid/Makefile,v
deleted file mode 100644 (file)
index 994362b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-head   1.1;
-access;
-symbols;
-locks
-       drahn:1.1; strict;
-comment        @# @;
-
-
-1.1
-date   95.09.28.19.00.28;      author drahn;   state Exp;
-branches;
-next   ;
-
-
-desc
-@@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@PROG= wrtvid
-NOMAN=
-
-install:
-
-.include <bsd.prog.mk>
-@
diff --git a/sys/arch/mvme88k/stand/wrtvid/wrtvid b/sys/arch/mvme88k/stand/wrtvid/wrtvid
deleted file mode 100644 (file)
index d27d4ef..0000000
Binary files a/sys/arch/mvme88k/stand/wrtvid/wrtvid and /dev/null differ