aboutsummaryrefslogtreecommitdiff
path: root/arch/parisc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/Kconfig199
-rw-r--r--arch/parisc/Kconfig.debug14
-rw-r--r--arch/parisc/Makefile121
-rw-r--r--arch/parisc/configs/712_defconfig891
-rw-r--r--arch/parisc/configs/a500_defconfig1010
-rw-r--r--arch/parisc/configs/b180_defconfig839
-rw-r--r--arch/parisc/configs/c3000_defconfig1126
-rw-r--r--arch/parisc/defconfig926
-rw-r--r--arch/parisc/defpalo.conf21
-rw-r--r--arch/parisc/hpux/Makefile5
-rw-r--r--arch/parisc/hpux/entry_hpux.S547
-rw-r--r--arch/parisc/hpux/fs.c199
-rw-r--r--arch/parisc/hpux/gate.S116
-rw-r--r--arch/parisc/hpux/ioctl.c73
-rw-r--r--arch/parisc/hpux/sys_hpux.c985
-rw-r--r--arch/parisc/hpux/wrappers.S257
-rw-r--r--arch/parisc/install.sh38
-rw-r--r--arch/parisc/kernel/Makefile24
-rw-r--r--arch/parisc/kernel/asm-offsets.c299
-rw-r--r--arch/parisc/kernel/binfmt_elf32.c126
-rw-r--r--arch/parisc/kernel/cache.c366
-rw-r--r--arch/parisc/kernel/drivers.c765
-rw-r--r--arch/parisc/kernel/entry.S2426
-rw-r--r--arch/parisc/kernel/firmware.c1405
-rw-r--r--arch/parisc/kernel/hardware.c1366
-rw-r--r--arch/parisc/kernel/head.S386
-rw-r--r--arch/parisc/kernel/hpmc.S304
-rw-r--r--arch/parisc/kernel/init_task.c76
-rw-r--r--arch/parisc/kernel/inventory.c612
-rw-r--r--arch/parisc/kernel/ioctl32.c625
-rw-r--r--arch/parisc/kernel/irq.c343
-rw-r--r--arch/parisc/kernel/module.c822
-rw-r--r--arch/parisc/kernel/pa7300lc.c49
-rw-r--r--arch/parisc/kernel/pacache.S1086
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c187
-rw-r--r--arch/parisc/kernel/pci-dma.c578
-rw-r--r--arch/parisc/kernel/pci.c346
-rw-r--r--arch/parisc/kernel/pdc_chassis.c245
-rw-r--r--arch/parisc/kernel/pdc_cons.c189
-rw-r--r--arch/parisc/kernel/perf.c841
-rw-r--r--arch/parisc/kernel/perf_asm.S1691
-rw-r--r--arch/parisc/kernel/perf_images.h3138
-rw-r--r--arch/parisc/kernel/process.c396
-rw-r--r--arch/parisc/kernel/processor.c400
-rw-r--r--arch/parisc/kernel/ptrace.c423
-rw-r--r--arch/parisc/kernel/real2.S304
-rw-r--r--arch/parisc/kernel/semaphore.c102
-rw-r--r--arch/parisc/kernel/setup.c368
-rw-r--r--arch/parisc/kernel/signal.c664
-rw-r--r--arch/parisc/kernel/signal32.c400
-rw-r--r--arch/parisc/kernel/signal32.h43
-rw-r--r--arch/parisc/kernel/smp.c723
-rw-r--r--arch/parisc/kernel/sys32.h48
-rw-r--r--arch/parisc/kernel/sys_parisc.c253
-rw-r--r--arch/parisc/kernel/sys_parisc32.c720
-rw-r--r--arch/parisc/kernel/syscall.S703
-rw-r--r--arch/parisc/kernel/syscall_table.S372
-rw-r--r--arch/parisc/kernel/time.c243
-rw-r--r--arch/parisc/kernel/topology.c37
-rw-r--r--arch/parisc/kernel/traps.c834
-rw-r--r--arch/parisc/kernel/unaligned.c816
-rw-r--r--arch/parisc/kernel/unwind.c393
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S207
-rw-r--r--arch/parisc/lib/Makefile9
-rw-r--r--arch/parisc/lib/bitops.c84
-rw-r--r--arch/parisc/lib/checksum.c148
-rw-r--r--arch/parisc/lib/debuglocks.c277
-rw-r--r--arch/parisc/lib/fixup.S89
-rw-r--r--arch/parisc/lib/io.c488
-rw-r--r--arch/parisc/lib/iomap.c422
-rw-r--r--arch/parisc/lib/lusercopy.S193
-rw-r--r--arch/parisc/lib/memcpy.c522
-rw-r--r--arch/parisc/lib/memset.c91
-rw-r--r--arch/parisc/math-emu/Makefile19
-rw-r--r--arch/parisc/math-emu/README11
-rw-r--r--arch/parisc/math-emu/cnv_float.h377
-rw-r--r--arch/parisc/math-emu/dbl_float.h847
-rw-r--r--arch/parisc/math-emu/decode_exc.c368
-rw-r--r--arch/parisc/math-emu/denormal.c135
-rw-r--r--arch/parisc/math-emu/dfadd.c524
-rw-r--r--arch/parisc/math-emu/dfcmp.c181
-rw-r--r--arch/parisc/math-emu/dfdiv.c400
-rw-r--r--arch/parisc/math-emu/dfmpy.c394
-rw-r--r--arch/parisc/math-emu/dfrem.c297
-rw-r--r--arch/parisc/math-emu/dfsqrt.c195
-rw-r--r--arch/parisc/math-emu/dfsub.c526
-rw-r--r--arch/parisc/math-emu/driver.c128
-rw-r--r--arch/parisc/math-emu/fcnvff.c309
-rw-r--r--arch/parisc/math-emu/fcnvfu.c536
-rw-r--r--arch/parisc/math-emu/fcnvfut.c332
-rw-r--r--arch/parisc/math-emu/fcnvfx.c501
-rw-r--r--arch/parisc/math-emu/fcnvfxt.c328
-rw-r--r--arch/parisc/math-emu/fcnvuf.c318
-rw-r--r--arch/parisc/math-emu/fcnvxf.c386
-rw-r--r--arch/parisc/math-emu/float.h582
-rw-r--r--arch/parisc/math-emu/fmpyfadd.c2655
-rw-r--r--arch/parisc/math-emu/fpbits.h65
-rw-r--r--arch/parisc/math-emu/fpu.h76
-rw-r--r--arch/parisc/math-emu/fpudispatch.c1442
-rw-r--r--arch/parisc/math-emu/frnd.c252
-rw-r--r--arch/parisc/math-emu/hppa.h42
-rw-r--r--arch/parisc/math-emu/math-emu.h27
-rw-r--r--arch/parisc/math-emu/sfadd.c518
-rw-r--r--arch/parisc/math-emu/sfcmp.c155
-rw-r--r--arch/parisc/math-emu/sfdiv.c392
-rw-r--r--arch/parisc/math-emu/sfmpy.c380
-rw-r--r--arch/parisc/math-emu/sfrem.c290
-rw-r--r--arch/parisc/math-emu/sfsqrt.c187
-rw-r--r--arch/parisc/math-emu/sfsub.c521
-rw-r--r--arch/parisc/math-emu/sgl_float.h486
-rw-r--r--arch/parisc/mm/Makefile5
-rw-r--r--arch/parisc/mm/fault.c271
-rw-r--r--arch/parisc/mm/init.c1019
-rw-r--r--arch/parisc/mm/ioremap.c207
-rw-r--r--arch/parisc/mm/kmap.c166
-rw-r--r--arch/parisc/nm6
-rw-r--r--arch/parisc/oprofile/Kconfig23
-rw-r--r--arch/parisc/oprofile/Makefile9
-rw-r--r--arch/parisc/oprofile/init.c23
119 files changed, 53345 insertions, 0 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
new file mode 100644
index 000000000000..5b5cd00d98ca
--- /dev/null
+++ b/arch/parisc/Kconfig
@@ -0,0 +1,199 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "Linux/PA-RISC Kernel Configuration"
+
+config PARISC
+ def_bool y
+ help
+ The PA-RISC microprocessor is designed by Hewlett-Packard and used
+ in many of their workstations & servers (HP9000 700 and 800 series,
+ and later HP3000 series). The PA-RISC Linux project home page is
+ at <http://www.parisc-linux.org/>.
+
+config MMU
+ def_bool y
+
+config STACK_GROWSUP
+ def_bool y
+
+config UID16
+ bool
+
+config RWSEM_GENERIC_SPINLOCK
+ def_bool y
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+
+config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+
+config GENERIC_ISA_DMA
+ bool
+
+config GENERIC_HARDIRQS
+ def_bool y
+
+config GENERIC_IRQ_PROBE
+ def_bool y
+
+# unless you want to implement ACPI on PA-RISC ... ;-)
+config PM
+ bool
+
+source "init/Kconfig"
+
+
+menu "Processor type and features"
+
+choice
+ prompt "Processor type"
+ default PA7000
+
+config PA7000
+ bool "PA7000/PA7100"
+ ---help---
+ This is the processor type of your CPU. This information is
+ used for optimizing purposes. In order to compile a kernel
+ that can run on all 32-bit PA CPUs (albeit not optimally fast),
+ you can specify "PA7000" here.
+
+ Specifying "PA8000" here will allow you to select a 64-bit kernel
+ which is required on some machines.
+
+config PA7100LC
+ bool "PA7100LC"
+ help
+ Select this option for the PCX-L processor, as used in the
+ 712, 715/64, 715/80, 715/100, 715/100XC, 725/100, 743, 748,
+ D200, D210, D300, D310 and E-class
+
+config PA7200
+ bool "PA7200"
+ help
+ Select this option for the PCX-T' processor, as used in the
+ C100, C110, J100, J110, J210XC, D250, D260, D350, D360,
+ K100, K200, K210, K220, K400, K410 and K420
+
+config PA7300LC
+ bool "PA7300LC"
+ help
+ Select this option for the PCX-L2 processor, as used in the
+ 744, A180, B132L, B160L, B180L, C132L, C160L, C180L,
+ D220, D230, D320 and D330.
+
+config PA8X00
+ bool "PA8000 and up"
+ help
+ Select this option for PCX-U to PCX-W2 processors.
+
+endchoice
+
+# Define implied options from the CPU selection here
+
+config PA20
+ def_bool y
+ depends on PA8X00
+
+config PA11
+ def_bool y
+ depends on PA7000 || PA7100LC || PA7200 || PA7300LC
+
+config PREFETCH
+ def_bool y
+ depends on PA8X00
+
+config 64BIT
+ bool "64-bit kernel"
+ depends on PA8X00
+ help
+ Enable this if you want to support 64bit kernel on PA-RISC platform.
+
+ At the moment, only people willing to use more than 2GB of RAM,
+ or having a 64bit-only capable PA-RISC machine should say Y here.
+
+ Since there is no 64bit userland on PA-RISC, there is no point to
+ enable this option otherwise. The 64bit kernel is significantly bigger
+ and slower than the 32bit one.
+
+config SMP
+ bool "Symmetric multi-processing support"
+ ---help---
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, like most personal computers, say N. If
+ you have a system with more than one CPU, say Y.
+
+ If you say N here, the kernel will run on single and multiprocessor
+ machines, but will use only one CPU of a multiprocessor machine. If
+ you say Y here, the kernel will run on many, but not all,
+ singleprocessor machines. On a singleprocessor machine, the kernel
+ will run faster if you say N here.
+
+ See also the <file:Documentation/smp.txt>,
+ <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available
+ at <http://www.tldp.org/docs.html#howto>.
+
+ If you don't know what to do here, say N.
+
+config HOTPLUG_CPU
+ bool
+ default y if SMP
+ select HOTPLUG
+
+config DISCONTIGMEM
+ bool "Discontiguous memory support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ Say Y to support efficient handling of discontiguous physical memory,
+ for architectures which are either NUMA (Non-Uniform Memory Access)
+ or have huge holes in the physical address space for other reasons.
+ See <file:Documentation/vm/numa> for more.
+
+config PREEMPT
+ bool
+# bool "Preemptible Kernel"
+ default n
+
+config COMPAT
+ def_bool y
+ depends on 64BIT
+
+config HPUX
+ bool "Support for HP-UX binaries"
+ depends on !64BIT
+
+config NR_CPUS
+ int "Maximum number of CPUs (2-32)"
+ range 2 32
+ depends on SMP
+ default "32"
+
+endmenu
+
+
+source "drivers/parisc/Kconfig"
+
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/parisc/oprofile/Kconfig"
+
+source "arch/parisc/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
new file mode 100644
index 000000000000..8caaed187a1f
--- /dev/null
+++ b/arch/parisc/Kconfig.debug
@@ -0,0 +1,14 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_RWLOCK
+ bool "Read-write spinlock debugging"
+ depends on DEBUG_KERNEL && SMP
+ help
+ If you say Y here then read-write lock processing will count how many
+ times it has tried to get the lock and issue an error message after
+ too many attempts. If you suspect a rwlock problem or a kernel
+ hacker asks for this option then say Y. Otherwise say N.
+
+endmenu
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
new file mode 100644
index 000000000000..0403d2fcb85e
--- /dev/null
+++ b/arch/parisc/Makefile
@@ -0,0 +1,121 @@
+#
+# parisc/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Portions Copyright (C) 1999 The Puffin Group
+#
+# Modified for PA-RISC Linux by Paul Lahaie, Alex deVries,
+# Mike Shaver, Helge Deller and Martin K. Petersen
+#
+NM = sh $(srctree)/arch/parisc/nm
+CHECKFLAGS += -D__hppa__=1
+
+ifdef CONFIG_64BIT
+CROSS_COMPILE := hppa64-linux-
+UTS_MACHINE := parisc64
+CHECKFLAGS += -D__LP64__=1 -m64
+else
+MACHINE := $(subst 64,,$(shell uname -m))
+ifneq ($(MACHINE),parisc)
+CROSS_COMPILE := hppa-linux-
+endif
+endif
+
+FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align
+
+OBJCOPY_FLAGS =-O binary -R .note -R .comment -S
+
+cflags-y := -pipe
+
+# These flags should be implied by an hppa-linux configuration, but they
+# are not in gcc 3.2.
+cflags-y += -mno-space-regs -mfast-indirect-calls
+
+# Currently we save and restore fpregs on all kernel entry/interruption paths.
+# If that gets optimized, we might need to disable the use of fpregs in the
+# kernel.
+#cflags-y += -mdisable-fpregs
+
+# Without this, "ld -r" results in .text sections that are too big
+# (> 0x40000) for branches to reach stubs.
+cflags-y += -ffunction-sections
+
+# select which processor to optimise for
+cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100
+cflags-$(CONFIG_PA7200) += -march=1.1 -mschedule=7200
+cflags-$(CONFIG_PA7100LC) += -march=1.1 -mschedule=7100LC
+cflags-$(CONFIG_PA7300LC) += -march=1.1 -mschedule=7300
+cflags-$(CONFIG_PA8X00) += -march=2.0 -mschedule=8000
+
+head-y := arch/parisc/kernel/head.o
+
+CFLAGS += $(cflags-y)
+
+kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o
+kernel-$(CONFIG_HPUX) += hpux/
+
+core-y += $(addprefix arch/parisc/, $(kernel-y))
+libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`
+
+drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/
+
+PALO := $(shell if which palo; then : ; \
+ elif [ -x /sbin/palo ]; then echo /sbin/palo; \
+ fi)
+
+palo: vmlinux
+ @if [ -x $PALO ]; then \
+ echo 'ERROR: Please install palo first (apt-get install palo)';\
+ echo 'or build it from source and install it somewhere in your $$PATH';\
+ false; \
+ fi
+ @if [ ! -f ./palo.conf ]; then \
+ cp arch/parisc/defpalo.conf palo.conf; \
+ echo 'A generic palo config file (./palo.conf) has been created for you.'; \
+ echo 'You should check it and re-run "make palo".'; \
+ echo 'WARNING: the "lifimage" file is now placed in this directory by default!'; \
+ false; \
+ fi
+ $(PALO) -f ./palo.conf
+
+oldpalo: vmlinux
+ export TOPDIR=`pwd`; \
+ unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage
+
+# Shorthands for known targets not supported by parisc, use palo as default
+Image zImage bzImage: palo
+
+kernel_install: vmlinux
+ sh $(src)/arch/parisc/install.sh \
+ $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
+
+install: kernel_install modules_install
+
+prepare: include/asm-parisc/offsets.h
+
+arch/parisc/kernel/asm-offsets.s: include/asm include/linux/version.h \
+ include/config/MARKER
+
+include/asm-parisc/offsets.h: arch/parisc/kernel/asm-offsets.s
+ $(call filechk,gen-asm-offsets)
+
+CLEAN_FILES += lifimage include/asm-parisc/offsets.h
+MRPROPER_FILES += palo.conf
+
+define archhelp
+ @echo '* vmlinux - Uncompressed kernel image (./vmlinux)'
+ @echo ' palo - Bootable image (./lifimage)'
+ @echo ' install - Install kernel using'
+ @echo ' (your) ~/bin/installkernel or'
+ @echo ' (distribution) /sbin/installkernel or'
+ @echo ' copy to $$(INSTALL_PATH)'
+endef
diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig
new file mode 100644
index 000000000000..872085dea8a8
--- /dev/null
+++ b/arch/parisc/configs/712_defconfig
@@ -0,0 +1,891 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-pa5
+# Wed Jan 5 13:20:32 2005
+#
+CONFIG_PARISC=y
+CONFIG_MMU=y
+CONFIG_STACK_GROWSUP=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PA7000 is not set
+CONFIG_PA7100LC=y
+# CONFIG_PA7200 is not set
+# CONFIG_PA7300LC is not set
+# CONFIG_PA8X00 is not set
+CONFIG_PA11=y
+# CONFIG_64BIT is not set
+# CONFIG_SMP is not set
+# CONFIG_DISCONTIGMEM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HPUX is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
+#
+CONFIG_GSC=y
+# CONFIG_HPPB is not set
+# CONFIG_IOMMU_CCIO is not set
+CONFIG_GSC_LASI=y
+# CONFIG_GSC_WAX is not set
+# CONFIG_EISA is not set
+# CONFIG_PCI is not set
+CONFIG_CHASSIS_LCD_LED=y
+# CONFIG_PDC_CHASSIS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_PARIDE is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+CONFIG_SCSI_LASI700=y
+CONFIG_53C700_MEM_MAPPED=y
+CONFIG_53C700_LE_ON_BE=y
+# CONFIG_SCSI_ZALON is not set
+CONFIG_SCSI_DEBUG=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+# CONFIG_IP_NF_NAT_LOCAL is not set
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_LASI_82596=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_GSCPS2=y
+CONFIG_HP_SDC=y
+CONFIG_HIL_MLC=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
+# CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_HIL is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_VSXXXAA is not set
+CONFIG_MOUSE_HIL=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MUX is not set
+CONFIG_PDC_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_GEN_RTC=y
+CONFIG_GEN_RTC_X=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_STI=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_PARISC_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# GSC devices
+#
+CONFIG_SND_HARMONY=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_TMPFS_SECURITY is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
new file mode 100644
index 000000000000..d28ebfa1070d
--- /dev/null
+++ b/arch/parisc/configs/a500_defconfig
@@ -0,0 +1,1010 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4-pa1
+# Wed Feb 16 11:32:49 2005
+#
+CONFIG_PARISC=y
+CONFIG_MMU=y
+CONFIG_STACK_GROWSUP=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+# CONFIG_PA7000 is not set
+# CONFIG_PA7100LC is not set
+# CONFIG_PA7200 is not set
+# CONFIG_PA7300LC is not set
+CONFIG_PA8X00=y
+CONFIG_PA20=y
+CONFIG_PREFETCH=y
+CONFIG_64BIT=y
+CONFIG_SMP=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_DISCONTIGMEM=y
+# CONFIG_PREEMPT is not set
+CONFIG_COMPAT=y
+CONFIG_NR_CPUS=8
+
+#
+# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
+#
+# CONFIG_GSC is not set
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_PCI_LBA=y
+CONFIG_IOSAPIC=y
+CONFIG_IOMMU_SBA=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_TCIC=m
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PA-RISC specific drivers
+#
+# CONFIG_SUPERIO is not set
+# CONFIG_CHASSIS_LCD_LED is not set
+CONFIG_PDC_CHASSIS=y
+CONFIG_PDC_STABLE=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+CONFIG_SCSI_QLOGIC_FC=m
+# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_QLOGIC_1280=m
+# CONFIG_SCSI_QLOGIC_1280_1040 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA6312=m
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_SCSI_DEBUG=m
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_PCMCIA_XIRTULIP is not set
+CONFIG_HP100=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_E100_NAPI=y
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=m
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+CONFIG_ACENIC_OMIT_TIGON_I=y
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+# CONFIG_2BUFF_MODE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+CONFIG_PCMCIA_RAYCS=m
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_PCI_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MUX is not set
+CONFIG_PDC_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_GEN_RTC=y
+CONFIG_GEN_RTC_X=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=160
+CONFIG_DUMMY_CONSOLE_ROWS=64
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+CONFIG_NLS_CODEPAGE_863=m
+# CONFIG_NLS_CODEPAGE_864 is not set
+CONFIG_NLS_CODEPAGE_865=m
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_IOREMAP is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_RWLOCK is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig
new file mode 100644
index 000000000000..1700d7aec686
--- /dev/null
+++ b/arch/parisc/configs/b180_defconfig
@@ -0,0 +1,839 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-pa5
+# Wed Jan 5 13:35:54 2005
+#
+CONFIG_PARISC=y
+CONFIG_MMU=y
+CONFIG_STACK_GROWSUP=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Processor type and features
+#
+# CONFIG_PA7000 is not set
+CONFIG_PA7100LC=y
+# CONFIG_PA7200 is not set
+# CONFIG_PA7300LC is not set
+# CONFIG_PA8X00 is not set
+CONFIG_PA11=y
+# CONFIG_64BIT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HPUX is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
+#
+CONFIG_GSC=y
+# CONFIG_HPPB is not set
+# CONFIG_IOMMU_CCIO is not set
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_EISA=y
+CONFIG_EISA_NAMES=y
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_GSC_DINO=y
+# CONFIG_PCI_LBA is not set
+CONFIG_CHASSIS_LCD_LED=y
+# CONFIG_PDC_CHASSIS is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_CML1=y
+# CONFIG_PARPORT_SERIAL is not set
+CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_LASI700=y
+CONFIG_53C700_MEM_MAPPED=y
+CONFIG_53C700_LE_ON_BE=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_ZALON is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_LASI_82596 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_AIRO is not set
+# CONFIG_HERMES is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_GSCPS2=y
+# CONFIG_HP_SDC is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_HIL_OLD is not set
+# CONFIG_KEYBOARD_HIL is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_HIL is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_HP_SDC_RTC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MUX is not set
+# CONFIG_PDC_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_STI=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=160
+CONFIG_DUMMY_CONSOLE_ROWS=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_PARISC_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_SECLVL is not set
+# CONFIG_SECURITY_SELINUX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
new file mode 100644
index 000000000000..b27980161c31
--- /dev/null
+++ b/arch/parisc/configs/c3000_defconfig
@@ -0,0 +1,1126 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-pa5
+# Wed Jan 5 13:26:49 2005
+#
+CONFIG_PARISC=y
+CONFIG_MMU=y
+CONFIG_STACK_GROWSUP=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PA7000 is not set
+# CONFIG_PA7100LC is not set
+# CONFIG_PA7200 is not set
+# CONFIG_PA7300LC is not set
+CONFIG_PA8X00=y
+CONFIG_PA20=y
+CONFIG_PREFETCH=y
+# CONFIG_PARISC64 is not set
+# CONFIG_64BIT is not set
+# CONFIG_SMP is not set
+# CONFIG_DISCONTIGMEM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HPUX is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
+#
+# CONFIG_GSC is not set
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_PCI_LBA=y
+CONFIG_IOSAPIC=y
+CONFIG_IOMMU_SBA=y
+CONFIG_SUPERIO=y
+CONFIG_CHASSIS_LCD_LED=y
+# CONFIG_PDC_CHASSIS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_UMEM=m
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_NS87415=y
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=m
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+CONFIG_SCSI_ATA_PIIX=m
+# CONFIG_SCSI_SATA_NV is not set
+CONFIG_SCSI_SATA_PROMISE=m
+# CONFIG_SCSI_SATA_SX4 is not set
+CONFIG_SCSI_SATA_SIL=m
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+CONFIG_SCSI_SATA_VIA=m
+# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+CONFIG_SCSI_QLOGIC_FC=m
+# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_QLOGIC_1280=m
+# CONFIG_SCSI_QLOGIC_1280_1040 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+CONFIG_SCSI_DEBUG=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+CONFIG_MD_MULTIPATH=y
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+# CONFIG_IP_NF_RAW is not set
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+CONFIG_IP_NF_COMPAT_IPFWADM=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+# CONFIG_AMD8111_ETH is not set
+CONFIG_ADAPTEC_STARFIRE=m
+# CONFIG_ADAPTEC_STARFIRE_NAPI is not set
+CONFIG_B44=m
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=m
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_IXGB=y
+CONFIG_IXGB_NAPI=y
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1600
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1200
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MUX is not set
+# CONFIG_PDC_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_GEN_RTC=y
+CONFIG_GEN_RTC_X=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_STI=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=160
+CONFIG_DUMMY_CONSOLE_ROWS=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_PARISC_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_HPUSBSCSI=m
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig
new file mode 100644
index 000000000000..ebd6301aa599
--- /dev/null
+++ b/arch/parisc/defconfig
@@ -0,0 +1,926 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_PARISC=y
+CONFIG_MMU=y
+CONFIG_STACK_GROWSUP=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_HOTPLUG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor type and features
+#
+CONFIG_PA7000=y
+# CONFIG_PA7100LC is not set
+# CONFIG_PA7200 is not set
+# CONFIG_PA8X00 is not set
+CONFIG_PA11=y
+# CONFIG_64BIT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HPUX is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
+#
+CONFIG_GSC=y
+CONFIG_HPPB=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_EISA=y
+CONFIG_EISA_NAMES=y
+# CONFIG_ISA is not set
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_IOSAPIC=y
+CONFIG_IOMMU_SBA=y
+CONFIG_SUPERIO=y
+CONFIG_CHASSIS_LCD_LED=y
+CONFIG_PDC_CHASSIS=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_CML1=y
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+CONFIG_SCSI_LASI700=y
+CONFIG_53C700_MEM_MAPPED=y
+CONFIG_53C700_LE_ON_BE=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_LASI_82596=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+CONFIG_DL2K=y
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_AIRO=y
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_GSCPS2=y
+CONFIG_HP_SDC=y
+CONFIG_HIL_MLC=y
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_HIL=y
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_HIL is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+# CONFIG_INPUT_JOYDUMP is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_HP_SDC_RTC=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MUX is not set
+# CONFIG_PDC_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_STI=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=160
+CONFIG_DUMMY_CONSOLE_ROWS=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_PCI_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_SOUND_HARMONY is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_XPAD is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_RWLOCK is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_INFO is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
diff --git a/arch/parisc/defpalo.conf b/arch/parisc/defpalo.conf
new file mode 100644
index 000000000000..4e1ae25b08d1
--- /dev/null
+++ b/arch/parisc/defpalo.conf
@@ -0,0 +1,21 @@
+# This a generic Palo configuration file. For more information about how
+# it works try 'palo -?'.
+#
+# Most people using 'make palo' want a bootable file, usable for
+# network or tape booting for example.
+--init-tape=lifimage
+--recoverykernel=vmlinux
+
+########## Pick your ROOT here! ##########
+# You need at least one 'root='!
+#
+# If you want a root ramdisk, use the next 2 lines
+# (Edit the ramdisk image name!!!!)
+--ramdisk=ram-disk-image-file
+--commandline=0/vmlinux HOME=/ root=/dev/ram initrd=0/ramdisk
+
+# If you want NFS root, use the following command line (Edit the HOSTNAME!!!)
+#--commandline=0/vmlinux HOME=/ root=/dev/nfs nfsroot=HOSTNAME ip=bootp
+
+# If you have root on a disk partition, use this (Edit the partition name!!!)
+#--commandline=0/vmlinux HOME=/ root=/dev/sda1
diff --git a/arch/parisc/hpux/Makefile b/arch/parisc/hpux/Makefile
new file mode 100644
index 000000000000..1048fb69f06d
--- /dev/null
+++ b/arch/parisc/hpux/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for HPUX emulation
+#
+
+obj-y := entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o
diff --git a/arch/parisc/hpux/entry_hpux.S b/arch/parisc/hpux/entry_hpux.S
new file mode 100644
index 000000000000..fa9bf38787e7
--- /dev/null
+++ b/arch/parisc/hpux/entry_hpux.S
@@ -0,0 +1,547 @@
+/* syscall table for HPUX specific syscalls
+ *
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ * Copyright (C) 1999 Matthew Wilcox <willy at debian . org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+ .text
+
+#define ENTRY_NAME(_name_) .word _name_
+
+ .align 4
+ .export hpux_call_table
+ .import hpux_unimplemented_wrapper
+hpux_call_table:
+ ENTRY_NAME(sys_ni_syscall) /* 0 */
+ ENTRY_NAME(sys_exit)
+ ENTRY_NAME(hpux_fork_wrapper)
+ ENTRY_NAME(sys_read)
+ ENTRY_NAME(sys_write)
+ ENTRY_NAME(sys_open) /* 5 */
+ ENTRY_NAME(sys_close)
+ ENTRY_NAME(hpux_wait)
+ ENTRY_NAME(sys_creat)
+ ENTRY_NAME(sys_link)
+ ENTRY_NAME(sys_unlink) /* 10 */
+ ENTRY_NAME(hpux_execv_wrapper)
+ ENTRY_NAME(sys_chdir)
+ ENTRY_NAME(sys_time)
+ ENTRY_NAME(sys_mknod)
+ ENTRY_NAME(sys_chmod) /* 15 */
+ ENTRY_NAME(sys_chown)
+ ENTRY_NAME(hpux_brk)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_lseek)
+ ENTRY_NAME(sys_getpid) /* 20 */
+ ENTRY_NAME(hpux_mount)
+ ENTRY_NAME(sys_oldumount)
+ ENTRY_NAME(sys_setuid)
+ ENTRY_NAME(sys_getuid)
+ ENTRY_NAME(sys_stime) /* 25 */
+ ENTRY_NAME(hpux_ptrace)
+ ENTRY_NAME(sys_alarm)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_pause)
+ ENTRY_NAME(sys_utime) /* 30 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_access)
+ ENTRY_NAME(hpux_nice)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 35 */
+ ENTRY_NAME(sys_sync)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_newstat)
+ ENTRY_NAME(hpux_setpgrp3)
+ ENTRY_NAME(sys_newlstat) /* 40 */
+ ENTRY_NAME(sys_dup)
+ ENTRY_NAME(hpux_pipe_wrapper)
+ ENTRY_NAME(sys_times)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 45 */
+ ENTRY_NAME(sys_setgid)
+ ENTRY_NAME(sys_getgid)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 50 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_ioctl)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 55 */
+ ENTRY_NAME(sys_symlink)
+ ENTRY_NAME(hpux_utssys)
+ ENTRY_NAME(sys_readlink)
+ ENTRY_NAME(hpux_execve_wrapper)
+ ENTRY_NAME(sys_umask) /* 60 */
+ ENTRY_NAME(sys_chroot)
+ ENTRY_NAME(sys_fcntl)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 65 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_sbrk)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 70 */
+ ENTRY_NAME(sys_mmap)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 75 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 80 */
+ ENTRY_NAME(sys_getpgid)
+ ENTRY_NAME(sys_setpgid)
+ ENTRY_NAME(sys_setitimer)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 85 */
+ ENTRY_NAME(sys_getitimer)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_dup2) /* 90 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_newfstat)
+ ENTRY_NAME(sys_select)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 95 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 100 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 105 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 110 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 115 */
+ ENTRY_NAME(sys_gettimeofday)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 120 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_fchown)
+ ENTRY_NAME(sys_fchmod)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 125 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_rename)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 130 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_sysconf)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 135 */
+ ENTRY_NAME(sys_mkdir)
+ ENTRY_NAME(sys_rmdir)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 140 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_getrlimit)
+ ENTRY_NAME(sys_setrlimit) /* 145 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 150 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_lockf) /* 155 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 160 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 165 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 170 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 175 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 180 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_sigprocmask) /* 185 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 190 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_getdomainname)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 195 */
+ ENTRY_NAME(hpux_statfs)
+ ENTRY_NAME(hpux_fstatfs)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_waitpid) /* 200 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 205 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 210 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 215 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 220 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 225 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 230 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 235 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 240 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 245 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 250 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 255 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 260 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 265 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 270 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_fchdir)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_accept) /* 275 */
+ ENTRY_NAME(sys_bind)
+ ENTRY_NAME(sys_connect)
+ ENTRY_NAME(sys_getpeername)
+ ENTRY_NAME(sys_getsockname)
+ ENTRY_NAME(sys_getsockopt) /* 280 */
+ ENTRY_NAME(sys_listen)
+ ENTRY_NAME(sys_recv)
+ ENTRY_NAME(sys_recvfrom)
+ ENTRY_NAME(sys_recvmsg)
+ ENTRY_NAME(sys_send) /* 285 */
+ ENTRY_NAME(sys_sendmsg)
+ ENTRY_NAME(sys_sendto)
+ ENTRY_NAME(sys_setsockopt)
+ ENTRY_NAME(sys_shutdown)
+ ENTRY_NAME(sys_socket) /* 290 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 295 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 300 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 305 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 310 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 315 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 320 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 325 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 330 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_lchown)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_sysfs)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 335 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 340 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 345 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 350 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(sys_nanosleep)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 355 */
+ ENTRY_NAME(hpux_getdents)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 360 */
+ ENTRY_NAME(hpux_fstat64)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 365 */
+ ENTRY_NAME(hpux_lstat64)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_stat64)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 370 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 375 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 380 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_setpgrp)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 385 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 390 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 395 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 400 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 405 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 410 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 415 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 420 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 425 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 430 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 435 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 440 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 445 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 450 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 455 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 460 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 465 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 470 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 475 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 480 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 485 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 490 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 495 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 500 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 505 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper) /* 510 */
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+ ENTRY_NAME(hpux_unimplemented_wrapper)
+.end
+
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
new file mode 100644
index 000000000000..d7c80edf4489
--- /dev/null
+++ b/arch/parisc/hpux/fs.c
@@ -0,0 +1,199 @@
+/*
+ * Implements HPUX syscalls.
+ *
+ * Copyright (C) 1999 Matthew Wilcox <willy with parisc-linux.org>
+ * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
+ * Copyright (C) 2000 John Marvin <jsm with parisc-linux.org>
+ * Copyright (C) 2000 Philipp Rumpf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/ptrace.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+int hpux_execve(struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname((char *) regs->gr[26]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+
+ error = do_execve(filename, (char **) regs->gr[25],
+ (char **)regs->gr[24], regs);
+
+ if (error == 0) {
+ task_lock(current);
+ current->ptrace &= ~PT_DTRACE;
+ task_unlock(current);
+ }
+ putname(filename);
+
+out:
+ return error;
+}
+
+struct hpux_dirent {
+ loff_t d_off;
+ ino_t d_ino;
+ short d_reclen;
+ short d_namlen;
+ char d_name[1];
+};
+
+struct getdents_callback {
+ struct hpux_dirent *current_dir;
+ struct hpux_dirent *previous;
+ int count;
+ int error;
+};
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+
+static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
+ ino_t ino, unsigned d_type)
+{
+ struct hpux_dirent * dirent;
+ struct getdents_callback * buf = (struct getdents_callback *) __buf;
+ int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
+ dirent = buf->previous;
+ if (dirent)
+ put_user(offset, &dirent->d_off);
+ dirent = buf->current_dir;
+ buf->previous = dirent;
+ put_user(ino, &dirent->d_ino);
+ put_user(reclen, &dirent->d_reclen);
+ put_user(namlen, &dirent->d_namlen);
+ copy_to_user(dirent->d_name, name, namlen);
+ put_user(0, dirent->d_name + namlen);
+ ((char *) dirent) += reclen;
+ buf->current_dir = dirent;
+ buf->count -= reclen;
+ return 0;
+}
+
+#undef NAME_OFFSET
+#undef ROUND_UP
+
+int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count)
+{
+ struct file * file;
+ struct hpux_dirent * lastdirent;
+ struct getdents_callback buf;
+ int error = -EBADF;
+
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ buf.current_dir = dirent;
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
+
+ error = vfs_readdir(file, filldir, &buf);
+ if (error < 0)
+ goto out_putf;
+ error = buf.error;
+ lastdirent = buf.previous;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
+ }
+
+out_putf:
+ fput(file);
+out:
+ return error;
+}
+
+int hpux_mount(const char *fs, const char *path, int mflag,
+ const char *fstype, const char *dataptr, int datalen)
+{
+ return -ENOSYS;
+}
+
+static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf)
+{
+ struct hpux_stat64 tmp;
+
+ /* we probably want a different split here - is hpux 12:20? */
+
+ if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
+ return -EOVERFLOW;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.st_dev = new_encode_dev(stat->dev);
+ tmp.st_ino = stat->ino;
+ tmp.st_mode = stat->mode;
+ tmp.st_nlink = stat->nlink;
+ tmp.st_uid = stat->uid;
+ tmp.st_gid = stat->gid;
+ tmp.st_rdev = new_encode_dev(stat->rdev);
+ tmp.st_size = stat->size;
+ tmp.st_atime = stat->atime.tv_sec;
+ tmp.st_mtime = stat->mtime.tv_sec;
+ tmp.st_ctime = stat->ctime.tv_sec;
+ tmp.st_blocks = stat->blocks;
+ tmp.st_blksize = stat->blksize;
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+long hpux_stat64(char *filename, struct hpux_stat64 *statbuf)
+{
+ struct kstat stat;
+ int error = vfs_stat(filename, &stat);
+
+ if (!error)
+ error = cp_hpux_stat(&stat, statbuf);
+
+ return error;
+}
+
+long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
+{
+ struct kstat stat;
+ int error = vfs_fstat(fd, &stat);
+
+ if (!error)
+ error = cp_hpux_stat(&stat, statbuf);
+
+ return error;
+}
+
+long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf)
+{
+ struct kstat stat;
+ int error = vfs_lstat(filename, &stat);
+
+ if (!error)
+ error = cp_hpux_stat(&stat, statbuf);
+
+ return error;
+}
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S
new file mode 100644
index 000000000000..2680a1c0fa77
--- /dev/null
+++ b/arch/parisc/hpux/gate.S
@@ -0,0 +1,116 @@
+/*
+ *
+ * Linux/PARISC Project (http://www.parisc-linux.org/)
+ *
+ * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
+ * Licensed under the GNU GPL.
+ * thanks to Philipp Rumpf, Mike Shaver and various others
+ * sorry about the wall, puffin..
+ */
+
+#include <asm/assembly.h>
+#include <asm/offsets.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+#ifdef __LP64__
+ .level 2.0w
+#else
+ .level 1.1
+#endif
+ .text
+
+#ifdef __LP64__
+#define FRAME_SIZE 128
+#else
+#define FRAME_SIZE 64
+#endif
+ .import hpux_call_table
+ .import hpux_syscall_exit,code
+ .export hpux_gateway_page
+
+ .align 4096
+hpux_gateway_page:
+ nop
+#ifdef __LP64__
+#warning NEEDS WORK for 64-bit
+#endif
+ ldw -64(%r30), %r29 ;! 8th argument
+ ldw -60(%r30), %r19 ;! 7th argument
+ ldw -56(%r30), %r20 ;! 6th argument
+ ldw -52(%r30), %r21 ;! 5th argument
+ gate .+8, %r0 /* become privileged */
+ mtsp %r0,%sr4 /* get kernel space into sr4 */
+ mtsp %r0,%sr5 /* get kernel space into sr5 */
+ mtsp %r0,%sr6 /* get kernel space into sr6 */
+ mfsp %sr7,%r1 /* save user sr7 */
+ mtsp %r1,%sr3 /* and store it in sr3 */
+
+ mtctl %r30,%cr28
+ mfctl %cr30,%r1
+ xor %r1,%r30,%r30 /* ye olde xor trick */
+ xor %r1,%r30,%r1
+ xor %r1,%r30,%r30
+ ldo TASK_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */
+
+ /* N.B.: It is critical that we don't set sr7 to 0 until r30
+ * contains a valid kernel stack pointer. It is also
+ * critical that we don't start using the kernel stack
+ * until after sr7 has been set to 0.
+ */
+
+ mtsp %r0,%sr7 /* get kernel space into sr7 */
+ STREG %r1,TASK_PT_GR30-TASK_SZ_ALGN-FRAME_SIZE(%r30) /* save usp */
+ ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr in %r1 */
+
+ /* Save some registers for sigcontext and potential task
+ switch (see entry.S for the details of which ones are
+ saved/restored). TASK_PT_PSW is zeroed so we can see whether
+ a process is on a syscall or not. For an interrupt the real
+ PSW value is stored. This is needed for gdb and sys_ptrace. */
+ STREG %r0, TASK_PT_PSW(%r1)
+ STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
+ STREG %r19, TASK_PT_GR19(%r1) /* 7th argument */
+ STREG %r20, TASK_PT_GR20(%r1) /* 6th argument */
+ STREG %r21, TASK_PT_GR21(%r1) /* 5th argument */
+ STREG %r22, TASK_PT_GR22(%r1) /* syscall # */
+ STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */
+ STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */
+ STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */
+ STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
+ STREG %r27, TASK_PT_GR27(%r1) /* user dp */
+ STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
+ STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */
+ STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */
+ STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
+
+ ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */
+ save_fp %r27 /* or potential task switch */
+
+ mfctl %cr11, %r27 /* i.e. SAR */
+ STREG %r27, TASK_PT_SAR(%r1)
+
+ loadgp
+
+ stw %r21, -52(%r30) ;! 5th argument
+ stw %r20, -56(%r30) ;! 6th argument
+ stw %r19, -60(%r30) ;! 7th argument
+ stw %r29, -64(%r30) ;! 8th argument
+
+ ldil L%hpux_call_table, %r21
+ ldo R%hpux_call_table(%r21), %r21
+ comiclr,>>= __NR_HPUX_syscalls, %r22, %r0
+ b,n syscall_nosys
+ ldwx,s %r22(%r21), %r21
+ ldil L%hpux_syscall_exit,%r2
+ be 0(%sr7,%r21)
+ ldo R%hpux_syscall_exit(%r2),%r2
+
+syscall_nosys:
+ ldil L%hpux_syscall_exit,%r1
+ be R%hpux_syscall_exit(%sr7,%r1)
+ ldo -ENOSYS(%r0),%r28
+
+ .align 4096
+ .export end_hpux_gateway_page
+end_hpux_gateway_page:
diff --git a/arch/parisc/hpux/ioctl.c b/arch/parisc/hpux/ioctl.c
new file mode 100644
index 000000000000..b34b4f3c60ec
--- /dev/null
+++ b/arch/parisc/hpux/ioctl.c
@@ -0,0 +1,73 @@
+/*
+ * Implements some necessary HPUX ioctls.
+ *
+ * Copyright (C) 1999-2002 Matthew Wilcox <willy with parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Supported ioctls:
+ * TCGETA
+ * TCSETA
+ * TCSETAW
+ * TCSETAF
+ * TCSBRK
+ * TCXONC
+ * TCFLSH
+ * TIOCGWINSZ
+ * TIOCSWINSZ
+ * TIOCGPGRP
+ * TIOCSPGRP
+ */
+
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/syscalls.h>
+#include <asm/errno.h>
+#include <asm/ioctl.h>
+#include <asm/termios.h>
+#include <asm/uaccess.h>
+
+static int hpux_ioctl_t(int fd, unsigned long cmd, unsigned long arg)
+{
+ int result = -EOPNOTSUPP;
+ int nr = _IOC_NR(cmd);
+ switch (nr) {
+ case 106:
+ result = sys_ioctl(fd, TIOCSWINSZ, arg);
+ break;
+ case 107:
+ result = sys_ioctl(fd, TIOCGWINSZ, arg);
+ break;
+ }
+ return result;
+}
+
+int hpux_ioctl(int fd, unsigned long cmd, unsigned long arg)
+{
+ int result = -EOPNOTSUPP;
+ int type = _IOC_TYPE(cmd);
+ switch (type) {
+ case 'T':
+ /* Our structures are now compatible with HPUX's */
+ result = sys_ioctl(fd, cmd, arg);
+ break;
+ case 't':
+ result = hpux_ioctl_t(fd, cmd, arg);
+ break;
+ }
+ return result;
+}
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
new file mode 100644
index 000000000000..a64fd48fbfb5
--- /dev/null
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -0,0 +1,985 @@
+/*
+ * Implements HPUX syscalls.
+ *
+ * Copyright (C) 1999 Matthew Wilcox <willy with parisc-linux.org>
+ * Copyright (C) 2000 Philipp Rumpf
+ * Copyright (C) 2000 John Marvin <jsm with parisc-linux.org>
+ * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
+ * Copyright (C) 2001 Nathan Neulinger <nneul at umr.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/syscalls.h>
+#include <linux/utsname.h>
+#include <linux/vfs.h>
+#include <linux/vmalloc.h>
+
+#include <asm/errno.h>
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+
+unsigned long hpux_brk(unsigned long addr)
+{
+ /* Sigh. Looks like HP/UX libc relies on kernel bugs. */
+ return sys_brk(addr + PAGE_SIZE);
+}
+
+int hpux_sbrk(void)
+{
+ return -ENOSYS;
+}
+
+/* Random other syscalls */
+
+int hpux_nice(int priority_change)
+{
+ return -ENOSYS;
+}
+
+int hpux_ptrace(void)
+{
+ return -ENOSYS;
+}
+
+int hpux_wait(int *stat_loc)
+{
+ return sys_waitpid(-1, stat_loc, 0);
+}
+
+int hpux_setpgrp(void)
+{
+ return sys_setpgid(0,0);
+}
+
+int hpux_setpgrp3(void)
+{
+ return hpux_setpgrp();
+}
+
+#define _SC_CPU_VERSION 10001
+#define _SC_OPEN_MAX 4
+#define CPU_PA_RISC1_1 0x210
+
+int hpux_sysconf(int which)
+{
+ switch (which) {
+ case _SC_CPU_VERSION:
+ return CPU_PA_RISC1_1;
+ case _SC_OPEN_MAX:
+ return INT_MAX;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*****************************************************************************/
+
+#define HPUX_UTSLEN 9
+#define HPUX_SNLEN 15
+
+struct hpux_utsname {
+ char sysname[HPUX_UTSLEN];
+ char nodename[HPUX_UTSLEN];
+ char release[HPUX_UTSLEN];
+ char version[HPUX_UTSLEN];
+ char machine[HPUX_UTSLEN];
+ char idnumber[HPUX_SNLEN];
+} ;
+
+struct hpux_ustat {
+ int32_t f_tfree; /* total free (daddr_t) */
+ u_int32_t f_tinode; /* total inodes free (ino_t) */
+ char f_fname[6]; /* filsys name */
+ char f_fpack[6]; /* filsys pack name */
+ u_int32_t f_blksize; /* filsys block size (int) */
+};
+
+/*
+ * HPUX's utssys() call. It's a collection of miscellaneous functions,
+ * alas, so there's no nice way of splitting them up.
+ */
+
+/* This function is called from hpux_utssys(); HP-UX implements
+ * ustat() as an option to utssys().
+ *
+ * Now, struct ustat on HP-UX is exactly the same as on Linux, except
+ * that it contains one addition field on the end, int32_t f_blksize.
+ * So, we could have written this function to just call the Linux
+ * sys_ustat(), (defined in linux/fs/super.c), and then just
+ * added this additional field to the user's structure. But I figure
+ * if we're gonna be digging through filesystem structures to get
+ * this, we might as well just do the whole enchilada all in one go.
+ *
+ * So, most of this function is almost identical to sys_ustat().
+ * I have placed comments at the few lines changed or added, to
+ * aid in porting forward if and when sys_ustat() is changed from
+ * its form in kernel 2.2.5.
+ */
+static int hpux_ustat(dev_t dev, struct hpux_ustat __user *ubuf)
+{
+ struct super_block *s;
+ struct hpux_ustat tmp; /* Changed to hpux_ustat */
+ struct kstatfs sbuf;
+ int err = -EINVAL;
+
+ s = user_get_super(dev);
+ if (s == NULL)
+ goto out;
+ err = vfs_statfs(s, &sbuf);
+ drop_super(s);
+ if (err)
+ goto out;
+
+ memset(&tmp,0,sizeof(tmp));
+
+ tmp.f_tfree = (int32_t)sbuf.f_bfree;
+ tmp.f_tinode = (u_int32_t)sbuf.f_ffree;
+ tmp.f_blksize = (u_int32_t)sbuf.f_bsize; /* Added this line */
+
+ err = copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+out:
+ return err;
+}
+
+/*
+ * Wrapper for hpux statfs call. At the moment, just calls the linux native one
+ * and ignores the extra fields at the end of the hpux statfs struct.
+ *
+ */
+
+typedef int32_t hpux_fsid_t[2]; /* file system ID type */
+typedef uint16_t hpux_site_t;
+
+struct hpux_statfs {
+ int32_t f_type; /* type of info, zero for now */
+ int32_t f_bsize; /* fundamental file system block size */
+ int32_t f_blocks; /* total blocks in file system */
+ int32_t f_bfree; /* free block in fs */
+ int32_t f_bavail; /* free blocks avail to non-superuser */
+ int32_t f_files; /* total file nodes in file system */
+ int32_t f_ffree; /* free file nodes in fs */
+ hpux_fsid_t f_fsid; /* file system ID */
+ int32_t f_magic; /* file system magic number */
+ int32_t f_featurebits; /* file system features */
+ int32_t f_spare[4]; /* spare for later */
+ hpux_site_t f_cnode; /* cluster node where mounted */
+ int16_t f_pad;
+};
+
+static int vfs_statfs_hpux(struct super_block *sb, struct hpux_statfs *buf)
+{
+ struct kstatfs st;
+ int retval;
+
+ retval = vfs_statfs(sb, &st);
+ if (retval)
+ return retval;
+
+ memset(buf, 0, sizeof(*buf));
+ buf->f_type = st.f_type;
+ buf->f_bsize = st.f_bsize;
+ buf->f_blocks = st.f_blocks;
+ buf->f_bfree = st.f_bfree;
+ buf->f_bavail = st.f_bavail;
+ buf->f_files = st.f_files;
+ buf->f_ffree = st.f_ffree;
+ buf->f_fsid[0] = st.f_fsid.val[0];
+ buf->f_fsid[1] = st.f_fsid.val[1];
+
+ return 0;
+}
+
+/* hpux statfs */
+asmlinkage long hpux_statfs(const char __user *path,
+ struct hpux_statfs __user *buf)
+{
+ struct nameidata nd;
+ int error;
+
+ error = user_path_walk(path, &nd);
+ if (!error) {
+ struct hpux_statfs tmp;
+ error = vfs_statfs_hpux(nd.dentry->d_inode->i_sb, &tmp);
+ if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
+ error = -EFAULT;
+ path_release(&nd);
+ }
+ return error;
+}
+
+asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
+{
+ struct file *file;
+ struct hpux_statfs tmp;
+ int error;
+
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ error = vfs_statfs_hpux(file->f_dentry->d_inode->i_sb, &tmp);
+ if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
+ error = -EFAULT;
+ fput(file);
+ out:
+ return error;
+}
+
+
+/* This function is called from hpux_utssys(); HP-UX implements
+ * uname() as an option to utssys().
+ *
+ * The form of this function is pretty much copied from sys_olduname(),
+ * defined in linux/arch/i386/kernel/sys_i386.c.
+ */
+/* TODO: Are these put_user calls OK? Should they pass an int?
+ * (I copied it from sys_i386.c like this.)
+ */
+static int hpux_uname(struct hpux_utsname *name)
+{
+ int error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct hpux_utsname)))
+ return -EFAULT;
+
+ down_read(&uts_sem);
+
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->sysname+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->nodename+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->release,&system_utsname.release,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->release+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->version,&system_utsname.version,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->version+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->machine,&system_utsname.machine,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->machine+HPUX_UTSLEN-1);
+
+ up_read(&uts_sem);
+
+ /* HP-UX utsname has no domainname field. */
+
+ /* TODO: Implement idnumber!!! */
+#if 0
+ error |= __put_user(0,name->idnumber);
+ error |= __put_user(0,name->idnumber+HPUX_SNLEN-1);
+#endif
+
+ error = error ? -EFAULT : 0;
+
+ return error;
+}
+
+/* Note: HP-UX just uses the old suser() function to check perms
+ * in this system call. We'll use capable(CAP_SYS_ADMIN).
+ */
+int hpux_utssys(char *ubuf, int n, int type)
+{
+ int len;
+ int error;
+ switch( type ) {
+ case 0:
+ /* uname(): */
+ return( hpux_uname( (struct hpux_utsname *)ubuf ) );
+ break ;
+ case 1:
+ /* Obsolete (used to be umask().) */
+ return -EFAULT ;
+ break ;
+ case 2:
+ /* ustat(): */
+ return( hpux_ustat(new_decode_dev(n), (struct hpux_ustat *)ubuf) );
+ break ;
+ case 3:
+ /* setuname():
+ *
+ * On linux (unlike HP-UX), utsname.nodename
+ * is the same as the hostname.
+ *
+ * sys_sethostname() is defined in linux/kernel/sys.c.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ return( sys_sethostname(ubuf, len) );
+ break ;
+ case 4:
+ /* sethostname():
+ *
+ * sys_sethostname() is defined in linux/kernel/sys.c.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ return( sys_sethostname(ubuf, len) );
+ break ;
+ case 5:
+ /* gethostname():
+ *
+ * sys_gethostname() is defined in linux/kernel/sys.c.
+ */
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ return( sys_gethostname(ubuf, n) );
+ break ;
+ case 6:
+ /* Supposedly called from setuname() in libc.
+ * TODO: When and why is this called?
+ * Is it ever even called?
+ *
+ * This code should look a lot like sys_sethostname(),
+ * defined in linux/kernel/sys.c. If that gets updated,
+ * update this code similarly.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ /**/
+ /* TODO: print a warning about using this? */
+ down_write(&uts_sem);
+ error = -EFAULT;
+ if (!copy_from_user(system_utsname.sysname, ubuf, len)) {
+ system_utsname.sysname[len] = 0;
+ error = 0;
+ }
+ up_write(&uts_sem);
+ return error;
+ break ;
+ case 7:
+ /* Sets utsname.release, if you're allowed.
+ * Undocumented. Used by swinstall to change the
+ * OS version, during OS updates. Yuck!!!
+ *
+ * This code should look a lot like sys_sethostname()
+ * in linux/kernel/sys.c. If that gets updated, update
+ * this code similarly.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ /**/
+ /* TODO: print a warning about this? */
+ down_write(&uts_sem);
+ error = -EFAULT;
+ if (!copy_from_user(system_utsname.release, ubuf, len)) {
+ system_utsname.release[len] = 0;
+ error = 0;
+ }
+ up_write(&uts_sem);
+ return error;
+ break ;
+ default:
+ /* This system call returns -EFAULT if given an unknown type.
+ * Why not -EINVAL? I don't know, it's just not what they did.
+ */
+ return -EFAULT ;
+ }
+}
+
+int hpux_getdomainname(char *name, int len)
+{
+ int nlen;
+ int err = -EFAULT;
+
+ down_read(&uts_sem);
+
+ nlen = strlen(system_utsname.domainname) + 1;
+
+ if (nlen < len)
+ len = nlen;
+ if(len > __NEW_UTS_LEN)
+ goto done;
+ if(copy_to_user(name, system_utsname.domainname, len))
+ goto done;
+ err = 0;
+done:
+ up_read(&uts_sem);
+ return err;
+
+}
+
+int hpux_pipe(int *kstack_fildes)
+{
+ int error;
+
+ lock_kernel();
+ error = do_pipe(kstack_fildes);
+ unlock_kernel();
+ return error;
+}
+
+/* lies - says it works, but it really didn't lock anything */
+int hpux_lockf(int fildes, int function, off_t size)
+{
+ return 0;
+}
+
+int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2)
+{
+ char *fsname = NULL;
+ int len = 0;
+ int fstype;
+
+/*Unimplemented HP-UX syscall emulation. Syscall #334 (sysfs)
+ Args: 1 80057bf4 0 400179f0 0 0 0 */
+ printk(KERN_DEBUG "in hpux_sysfs\n");
+ printk(KERN_DEBUG "hpux_sysfs called with opcode = %d\n", opcode);
+ printk(KERN_DEBUG "hpux_sysfs called with arg1='%lx'\n", arg1);
+
+ if ( opcode == 1 ) { /* GETFSIND */
+ len = strlen_user((char *)arg1);
+ printk(KERN_DEBUG "len of arg1 = %d\n", len);
+
+ fsname = (char *) kmalloc(len+1, GFP_KERNEL);
+ if ( !fsname ) {
+ printk(KERN_DEBUG "failed to kmalloc fsname\n");
+ return 0;
+ }
+
+ if ( copy_from_user(fsname, (char *)arg1, len+1) ) {
+ printk(KERN_DEBUG "failed to copy_from_user fsname\n");
+ kfree(fsname);
+ return 0;
+ }
+
+ printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname);
+ if ( !strcmp(fsname, "hfs") ) {
+ fstype = 0;
+ } else {
+ fstype = 0;
+ };
+
+ kfree(fsname);
+
+ printk(KERN_DEBUG "returning fstype=%d\n", fstype);
+ return fstype; /* something other than default */
+ }
+
+
+ return 0;
+}
+
+
+/* Table of syscall names and handle for unimplemented routines */
+static const char *syscall_names[] = {
+ "nosys", /* 0 */
+ "exit",
+ "fork",
+ "read",
+ "write",
+ "open", /* 5 */
+ "close",
+ "wait",
+ "creat",
+ "link",
+ "unlink", /* 10 */
+ "execv",
+ "chdir",
+ "time",
+ "mknod",
+ "chmod", /* 15 */
+ "chown",
+ "brk",
+ "lchmod",
+ "lseek",
+ "getpid", /* 20 */
+ "mount",
+ "umount",
+ "setuid",
+ "getuid",
+ "stime", /* 25 */
+ "ptrace",
+ "alarm",
+ NULL,
+ "pause",
+ "utime", /* 30 */
+ "stty",
+ "gtty",
+ "access",
+ "nice",
+ "ftime", /* 35 */
+ "sync",
+ "kill",
+ "stat",
+ "setpgrp3",
+ "lstat", /* 40 */
+ "dup",
+ "pipe",
+ "times",
+ "profil",
+ "ki_call", /* 45 */
+ "setgid",
+ "getgid",
+ NULL,
+ NULL,
+ NULL, /* 50 */
+ "acct",
+ "set_userthreadid",
+ NULL,
+ "ioctl",
+ "reboot", /* 55 */
+ "symlink",
+ "utssys",
+ "readlink",
+ "execve",
+ "umask", /* 60 */
+ "chroot",
+ "fcntl",
+ "ulimit",
+ NULL,
+ NULL, /* 65 */
+ "vfork",
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 70 */
+ "mmap",
+ NULL,
+ "munmap",
+ "mprotect",
+ "madvise", /* 75 */
+ "vhangup",
+ "swapoff",
+ NULL,
+ "getgroups",
+ "setgroups", /* 80 */
+ "getpgrp2",
+ "setpgid/setpgrp2",
+ "setitimer",
+ "wait3",
+ "swapon", /* 85 */
+ "getitimer",
+ NULL,
+ NULL,
+ NULL,
+ "dup2", /* 90 */
+ NULL,
+ "fstat",
+ "select",
+ NULL,
+ "fsync", /* 95 */
+ "setpriority",
+ NULL,
+ NULL,
+ NULL,
+ "getpriority", /* 100 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 105 */
+ NULL,
+ NULL,
+ "sigvector",
+ "sigblock",
+ "sigsetmask", /* 110 */
+ "sigpause",
+ "sigstack",
+ NULL,
+ NULL,
+ NULL, /* 115 */
+ "gettimeofday",
+ "getrusage",
+ NULL,
+ NULL,
+ "readv", /* 120 */
+ "writev",
+ "settimeofday",
+ "fchown",
+ "fchmod",
+ NULL, /* 125 */
+ "setresuid",
+ "setresgid",
+ "rename",
+ "truncate",
+ "ftruncate", /* 130 */
+ NULL,
+ "sysconf",
+ NULL,
+ NULL,
+ NULL, /* 135 */
+ "mkdir",
+ "rmdir",
+ NULL,
+ "sigcleanup",
+ "setcore", /* 140 */
+ NULL,
+ "gethostid",
+ "sethostid",
+ "getrlimit",
+ "setrlimit", /* 145 */
+ NULL,
+ NULL,
+ "quotactl",
+ "get_sysinfo",
+ NULL, /* 150 */
+ "privgrp",
+ "rtprio",
+ "plock",
+ NULL,
+ "lockf", /* 155 */
+ "semget",
+ NULL,
+ "semop",
+ "msgget",
+ NULL, /* 160 */
+ "msgsnd",
+ "msgrcv",
+ "shmget",
+ NULL,
+ "shmat", /* 165 */
+ "shmdt",
+ NULL,
+ "csp/nsp_init",
+ "cluster",
+ "mkrnod", /* 170 */
+ "test",
+ "unsp_open",
+ NULL,
+ "getcontext",
+ "osetcontext", /* 175 */
+ "bigio",
+ "pipenode",
+ "lsync",
+ "getmachineid",
+ "cnodeid/mysite", /* 180 */
+ "cnodes/sitels",
+ "swapclients",
+ "rmtprocess",
+ "dskless_stats",
+ "sigprocmask", /* 185 */
+ "sigpending",
+ "sigsuspend",
+ "sigaction",
+ NULL,
+ "nfssvc", /* 190 */
+ "getfh",
+ "getdomainname",
+ "setdomainname",
+ "async_daemon",
+ "getdirentries", /* 195 */
+ NULL,
+ NULL,
+ "vfsmount",
+ NULL,
+ "waitpid", /* 200 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 205 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 210 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 215 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 220 */
+ NULL,
+ NULL,
+ NULL,
+ "sigsetreturn",
+ "sigsetstatemask", /* 225 */
+ "bfactl",
+ "cs",
+ "cds",
+ NULL,
+ "pathconf", /* 230 */
+ "fpathconf",
+ NULL,
+ NULL,
+ "nfs_fcntl",
+ "ogetacl", /* 235 */
+ "ofgetacl",
+ "osetacl",
+ "ofsetacl",
+ "pstat",
+ "getaudid", /* 240 */
+ "setaudid",
+ "getaudproc",
+ "setaudproc",
+ "getevent",
+ "setevent", /* 245 */
+ "audwrite",
+ "audswitch",
+ "audctl",
+ "ogetaccess",
+ "fsctl", /* 250 */
+ "ulconnect",
+ "ulcontrol",
+ "ulcreate",
+ "uldest",
+ "ulrecv", /* 255 */
+ "ulrecvcn",
+ "ulsend",
+ "ulshutdown",
+ "swapfs",
+ "fss", /* 260 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 265 */
+ NULL,
+ "tsync",
+ "getnumfds",
+ "poll",
+ "getmsg", /* 270 */
+ "putmsg",
+ "fchdir",
+ "getmount_cnt",
+ "getmount_entry",
+ "accept", /* 275 */
+ "bind",
+ "connect",
+ "getpeername",
+ "getsockname",
+ "getsockopt", /* 280 */
+ "listen",
+ "recv",
+ "recvfrom",
+ "recvmsg",
+ "send", /* 285 */
+ "sendmsg",
+ "sendto",
+ "setsockopt",
+ "shutdown",
+ "socket", /* 290 */
+ "socketpair",
+ "proc_open",
+ "proc_close",
+ "proc_send",
+ "proc_recv", /* 295 */
+ "proc_sendrecv",
+ "proc_syscall",
+ "ipccreate",
+ "ipcname",
+ "ipcnamerase", /* 300 */
+ "ipclookup",
+ "ipcselect",
+ "ipcconnect",
+ "ipcrecvcn",
+ "ipcsend", /* 305 */
+ "ipcrecv",
+ "ipcgetnodename",
+ "ipcsetnodename",
+ "ipccontrol",
+ "ipcshutdown", /* 310 */
+ "ipcdest",
+ "semctl",
+ "msgctl",
+ "shmctl",
+ "mpctl", /* 315 */
+ "exportfs",
+ "getpmsg",
+ "putpmsg",
+ "strioctl",
+ "msync", /* 320 */
+ "msleep",
+ "mwakeup",
+ "msem_init",
+ "msem_remove",
+ "adjtime", /* 325 */
+ "kload",
+ "fattach",
+ "fdetach",
+ "serialize",
+ "statvfs", /* 330 */
+ "fstatvfs",
+ "lchown",
+ "getsid",
+ "sysfs",
+ NULL, /* 335 */
+ NULL,
+ "sched_setparam",
+ "sched_getparam",
+ "sched_setscheduler",
+ "sched_getscheduler", /* 340 */
+ "sched_yield",
+ "sched_get_priority_max",
+ "sched_get_priority_min",
+ "sched_rr_get_interval",
+ "clock_settime", /* 345 */
+ "clock_gettime",
+ "clock_getres",
+ "timer_create",
+ "timer_delete",
+ "timer_settime", /* 350 */
+ "timer_gettime",
+ "timer_getoverrun",
+ "nanosleep",
+ "toolbox",
+ NULL, /* 355 */
+ "getdents",
+ "getcontext",
+ "sysinfo",
+ "fcntl64",
+ "ftruncate64", /* 360 */
+ "fstat64",
+ "getdirentries64",
+ "getrlimit64",
+ "lockf64",
+ "lseek64", /* 365 */
+ "lstat64",
+ "mmap64",
+ "setrlimit64",
+ "stat64",
+ "truncate64", /* 370 */
+ "ulimit64",
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* 375 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "setcontext", /* 380 */
+ "sigaltstack",
+ "waitid",
+ "setpgrp",
+ "recvmsg2",
+ "sendmsg2", /* 385 */
+ "socket2",
+ "socketpair2",
+ "setregid",
+ "lwp_create",
+ "lwp_terminate", /* 390 */
+ "lwp_wait",
+ "lwp_suspend",
+ "lwp_resume",
+ "lwp_self",
+ "lwp_abort_syscall", /* 395 */
+ "lwp_info",
+ "lwp_kill",
+ "ksleep",
+ "kwakeup",
+ "ksleep_abort", /* 400 */
+ "lwp_proc_info",
+ "lwp_exit",
+ "lwp_continue",
+ "getacl",
+ "fgetacl", /* 405 */
+ "setacl",
+ "fsetacl",
+ "getaccess",
+ "lwp_mutex_init",
+ "lwp_mutex_lock_sys", /* 410 */
+ "lwp_mutex_unlock",
+ "lwp_cond_init",
+ "lwp_cond_signal",
+ "lwp_cond_broadcast",
+ "lwp_cond_wait_sys", /* 415 */
+ "lwp_getscheduler",
+ "lwp_setscheduler",
+ "lwp_getprivate",
+ "lwp_setprivate",
+ "lwp_detach", /* 420 */
+ "mlock",
+ "munlock",
+ "mlockall",
+ "munlockall",
+ "shm_open", /* 425 */
+ "shm_unlink",
+ "sigqueue",
+ "sigwaitinfo",
+ "sigtimedwait",
+ "sigwait", /* 430 */
+ "aio_read",
+ "aio_write",
+ "lio_listio",
+ "aio_error",
+ "aio_return", /* 435 */
+ "aio_cancel",
+ "aio_suspend",
+ "aio_fsync",
+ "mq_open",
+ "mq_unlink", /* 440 */
+ "mq_send",
+ "mq_receive",
+ "mq_notify",
+ "mq_setattr",
+ "mq_getattr", /* 445 */
+ "ksem_open",
+ "ksem_unlink",
+ "ksem_close",
+ "ksem_destroy",
+ "lw_sem_incr", /* 450 */
+ "lw_sem_decr",
+ "lw_sem_read",
+ "mq_close",
+};
+static const int syscall_names_max = 453;
+
+int
+hpux_unimplemented(unsigned long arg1,unsigned long arg2,unsigned long arg3,
+ unsigned long arg4,unsigned long arg5,unsigned long arg6,
+ unsigned long arg7,unsigned long sc_num)
+{
+ /* NOTE: sc_num trashes arg8 for the few syscalls that actually
+ * have a valid 8th argument.
+ */
+ const char *name = NULL;
+ if ( sc_num <= syscall_names_max && sc_num >= 0 ) {
+ name = syscall_names[sc_num];
+ }
+
+ if ( name ) {
+ printk(KERN_DEBUG "Unimplemented HP-UX syscall emulation. Syscall #%lu (%s)\n",
+ sc_num, name);
+ } else {
+ printk(KERN_DEBUG "Unimplemented unknown HP-UX syscall emulation. Syscall #%lu\n",
+ sc_num);
+ }
+
+ printk(KERN_DEBUG " Args: %lx %lx %lx %lx %lx %lx %lx\n",
+ arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+
+ return -ENOSYS;
+}
diff --git a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S
new file mode 100644
index 000000000000..1aa936dfe147
--- /dev/null
+++ b/arch/parisc/hpux/wrappers.S
@@ -0,0 +1,257 @@
+/*
+ * Linux/PARISC Project (http://www.parisc-linux.org/)
+ *
+ * HP-UX System Call Wrapper routines and System Call Return Path
+ *
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __LP64__
+#warning PA64 support needs more work...did first cut
+#endif
+
+#include <asm/offsets.h>
+#include <asm/assembly.h>
+#include <asm/signal.h>
+
+#ifdef __LP64__
+ .level 2.0w
+#else
+ .level 1.1
+#endif
+ .text
+
+ /* These should probably go in a header file somewhere.
+ * They are duplicated in kernel/wrappers.S
+ * Possibly we should consider consolidating these
+ * register save/restore macros.
+ */
+ .macro reg_save regs
+#ifdef __LP64__
+#warning NEEDS WORK for 64-bit
+#endif
+ STREG %r3, PT_GR3(\regs)
+ STREG %r4, PT_GR4(\regs)
+ STREG %r5, PT_GR5(\regs)
+ STREG %r6, PT_GR6(\regs)
+ STREG %r7, PT_GR7(\regs)
+ STREG %r8, PT_GR8(\regs)
+ STREG %r9, PT_GR9(\regs)
+ STREG %r10,PT_GR10(\regs)
+ STREG %r11,PT_GR11(\regs)
+ STREG %r12,PT_GR12(\regs)
+ STREG %r13,PT_GR13(\regs)
+ STREG %r14,PT_GR14(\regs)
+ STREG %r15,PT_GR15(\regs)
+ STREG %r16,PT_GR16(\regs)
+ STREG %r17,PT_GR17(\regs)
+ STREG %r18,PT_GR18(\regs)
+ .endm
+
+ .macro reg_restore regs
+ LDREG PT_GR3(\regs), %r3
+ LDREG PT_GR4(\regs), %r4
+ LDREG PT_GR5(\regs), %r5
+ LDREG PT_GR6(\regs), %r6
+ LDREG PT_GR7(\regs), %r7
+ LDREG PT_GR8(\regs), %r8
+ LDREG PT_GR9(\regs), %r9
+ LDREG PT_GR10(\regs),%r10
+ LDREG PT_GR11(\regs),%r11
+ LDREG PT_GR12(\regs),%r12
+ LDREG PT_GR13(\regs),%r13
+ LDREG PT_GR14(\regs),%r14
+ LDREG PT_GR15(\regs),%r15
+ LDREG PT_GR16(\regs),%r16
+ LDREG PT_GR17(\regs),%r17
+ LDREG PT_GR18(\regs),%r18
+ .endm
+
+
+ .export hpux_fork_wrapper
+ .export hpux_child_return
+ .import sys_fork
+
+hpux_fork_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+ ;! pointer in task
+ reg_save %r1
+
+ STREG %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ STREG %r2,PT_GR19(%r1) ;! save for child
+ STREG %r30,PT_GR21(%r1) ;! save for child
+
+ LDREG PT_GR30(%r1),%r25
+ mtctl %r25,%cr29
+ copy %r1,%r24
+ bl sys_clone,%r2
+ ldi SIGCHLD,%r26
+
+ LDREG -84(%r30),%r2
+fork_return:
+ ldo -64(%r30),%r30
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+
+ reg_restore %r1
+
+ /*
+ * HP-UX wants pid (child gets parent pid, parent gets child pid)
+ * in r28 and a flag in r29 (r29 == 1 for child, 0 for parent).
+ * Linux fork returns 0 for child, pid for parent. Since HP-UX
+ * libc stub throws away parent pid and returns 0 for child,
+ * we'll just return 0 for parent pid now. Only applications
+ * that jump directly to the gateway page (not supported) will
+ * know the difference. We can fix this later if necessary.
+ */
+
+ ldo -1024(%r0),%r1
+ comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */
+ or,= %r28,%r0,%r0
+ or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */
+ ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */
+
+fork_exit:
+ bv %r0(%r2)
+ nop
+
+ /* Set the return value for the child */
+
+hpux_child_return:
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+ bl schedule_tail, %r2
+ nop
+#endif
+
+ LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
+ b fork_return
+ copy %r0,%r28
+
+ .export hpux_execve_wrapper
+ .export hpux_execv_wrapper
+ .import hpux_execve
+
+hpux_execv_wrapper:
+ copy %r0,%r24 /* NULL environment */
+
+hpux_execve_wrapper:
+
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+
+ /*
+ * Do we need to save/restore r3-r18 here?
+ * I don't think so. why would new thread need old
+ * threads registers?
+ */
+
+ /* Store arg0, arg1 and arg2 so that hpux_execve will find them */
+
+ STREG %r26,PT_GR26(%r1)
+ STREG %r25,PT_GR25(%r1)
+ STREG %r24,PT_GR24(%r1)
+
+ STREG %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ bl hpux_execve,%r2
+ copy %r1,%arg0
+
+ ldo -64(%r30),%r30
+ LDREG -20(%r30),%r2
+
+ /* If exec succeeded we need to load the args */
+
+ ldo -1024(%r0),%r1
+ comb,>>= %r28,%r1,exec_error
+ copy %r2,%r19
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr
+ LDREG TASK_PT_GR26(%r1),%r26
+ LDREG TASK_PT_GR25(%r1),%r25
+ LDREG TASK_PT_GR24(%r1),%r24
+ LDREG TASK_PT_GR23(%r1),%r23
+ copy %r0,%r2 /* Flag to syscall_exit not to clear args */
+
+exec_error:
+ bv %r0(%r19)
+ nop
+
+ .export hpux_pipe_wrapper
+ .import hpux_pipe
+
+ /* HP-UX expects pipefd's returned in r28 & r29 */
+
+hpux_pipe_wrapper:
+ STREG %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ bl hpux_pipe,%r2
+ ldo -56(%r30),%r26 /* pass local array to hpux_pipe */
+
+
+ ldo -1024(%r0),%r1
+ comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */
+ LDREG -84(%r30),%r2
+
+ /* if success, load fd's from stack array */
+
+ LDREG -56(%r30),%r28
+ LDREG -52(%r30),%r29
+
+pipe_exit:
+ bv %r0(%r2)
+ ldo -64(%r30),%r30
+
+ .export hpux_syscall_exit
+ .import syscall_exit
+
+hpux_syscall_exit:
+
+ /*
+ *
+ * HP-UX call return conventions:
+ *
+ * if error:
+ * r22 = 1
+ * r28 = errno value
+ * r29 = secondary return value
+ * else
+ * r22 = 0
+ * r28 = return value
+ * r29 = secondary return value
+ *
+ * For now, we'll just check to see if r28 is < (unsigned long)-1024
+ * (to handle addresses > 2 Gb) and if so set r22 to zero. If not,
+ * we'll complement r28 and set r22 to 1. Wrappers will be
+ * needed for syscalls that care about the secondary return value.
+ * The wrapper may also need a way of avoiding the following code,
+ * but we'll deal with that when it becomes necessary.
+ */
+
+ ldo -1024(%r0),%r1
+ comb,<< %r28,%r1,no_error
+ copy %r0,%r22
+ subi 0,%r28,%r28
+ ldo 1(%r0),%r22
+
+no_error:
+ b syscall_exit
+ nop
+
+ .export hpux_unimplemented_wrapper
+ .import hpux_unimplemented
+
+hpux_unimplemented_wrapper:
+ b hpux_unimplemented
+ STREG %r22,-64(%r30) /* overwrite arg8 with syscall number */
diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh
new file mode 100644
index 000000000000..9632b3e164c7
--- /dev/null
+++ b/arch/parisc/install.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# arch/parisc/install.sh, derived from arch/i386/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+#
+# "make install" script for i386 architecture
+#
+# Arguments:
+# $1 - kernel version
+# $2 - kernel image file
+# $3 - kernel map file
+# $4 - default install path (blank if root directory)
+#
+
+# User may have a custom install script
+
+if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
+if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+
+# Default install
+
+if [ -f $4/vmlinux ]; then
+ mv $4/vmlinux $4/vmlinux.old
+fi
+
+if [ -f $4/System.map ]; then
+ mv $4/System.map $4/System.old
+fi
+
+cat $2 > $4/vmlinux
+cp $3 $4/System.map
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
new file mode 100644
index 000000000000..171f9c239f60
--- /dev/null
+++ b/arch/parisc/kernel/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for arch/parisc/kernel
+#
+
+extra-y := init_task.o head.o vmlinux.lds
+
+AFLAGS_entry.o := -traditional
+AFLAGS_pacache.o := -traditional
+CFLAGS_ioctl32.o := -Ifs/
+
+obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
+ pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
+ ptrace.o hardware.o inventory.o drivers.o semaphore.o \
+ signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
+ process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
+ topology.o
+
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_PA11) += pci-dma.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o
+# only supported for PCX-W/U in 64-bit mode at the moment
+obj-$(CONFIG_64BIT) += perf.o perf_asm.o
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
new file mode 100644
index 000000000000..1ad44f92d6e4
--- /dev/null
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -0,0 +1,299 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed to extract
+ * and format the required data.
+ *
+ * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org>
+ * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org>
+ * Copyright (C) 2000 Sam Creasey <sammy@sammy.net>
+ * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
+ * Copyright (C) 2001 Paul Bame <bame at parisc-linux.org>
+ * Copyright (C) 2001 Richard Hirst <rhirst at parisc-linux.org>
+ * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
+ * Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/thread_info.h>
+#include <linux/version.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/pdc.h>
+#include <asm/uaccess.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+#ifdef __LP64__
+#define FRAME_SIZE 128
+#else
+#define FRAME_SIZE 64
+#endif
+
+#define align(x,y) (((x)+FRAME_SIZE+(y)-1) - (((x)+(y)-1)%(y)))
+
+int main(void)
+{
+ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+ DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending));
+ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+ DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+ DEFINE(TASK_PERSONALITY, offsetof(struct task_struct, personality));
+ DEFINE(TASK_PID, offsetof(struct task_struct, pid));
+ BLANK();
+ DEFINE(TASK_REGS, offsetof(struct task_struct, thread.regs));
+ DEFINE(TASK_PT_PSW, offsetof(struct task_struct, thread.regs.gr[ 0]));
+ DEFINE(TASK_PT_GR1, offsetof(struct task_struct, thread.regs.gr[ 1]));
+ DEFINE(TASK_PT_GR2, offsetof(struct task_struct, thread.regs.gr[ 2]));
+ DEFINE(TASK_PT_GR3, offsetof(struct task_struct, thread.regs.gr[ 3]));
+ DEFINE(TASK_PT_GR4, offsetof(struct task_struct, thread.regs.gr[ 4]));
+ DEFINE(TASK_PT_GR5, offsetof(struct task_struct, thread.regs.gr[ 5]));
+ DEFINE(TASK_PT_GR6, offsetof(struct task_struct, thread.regs.gr[ 6]));
+ DEFINE(TASK_PT_GR7, offsetof(struct task_struct, thread.regs.gr[ 7]));
+ DEFINE(TASK_PT_GR8, offsetof(struct task_struct, thread.regs.gr[ 8]));
+ DEFINE(TASK_PT_GR9, offsetof(struct task_struct, thread.regs.gr[ 9]));
+ DEFINE(TASK_PT_GR10, offsetof(struct task_struct, thread.regs.gr[10]));
+ DEFINE(TASK_PT_GR11, offsetof(struct task_struct, thread.regs.gr[11]));
+ DEFINE(TASK_PT_GR12, offsetof(struct task_struct, thread.regs.gr[12]));
+ DEFINE(TASK_PT_GR13, offsetof(struct task_struct, thread.regs.gr[13]));
+ DEFINE(TASK_PT_GR14, offsetof(struct task_struct, thread.regs.gr[14]));
+ DEFINE(TASK_PT_GR15, offsetof(struct task_struct, thread.regs.gr[15]));
+ DEFINE(TASK_PT_GR16, offsetof(struct task_struct, thread.regs.gr[16]));
+ DEFINE(TASK_PT_GR17, offsetof(struct task_struct, thread.regs.gr[17]));
+ DEFINE(TASK_PT_GR18, offsetof(struct task_struct, thread.regs.gr[18]));
+ DEFINE(TASK_PT_GR19, offsetof(struct task_struct, thread.regs.gr[19]));
+ DEFINE(TASK_PT_GR20, offsetof(struct task_struct, thread.regs.gr[20]));
+ DEFINE(TASK_PT_GR21, offsetof(struct task_struct, thread.regs.gr[21]));
+ DEFINE(TASK_PT_GR22, offsetof(struct task_struct, thread.regs.gr[22]));
+ DEFINE(TASK_PT_GR23, offsetof(struct task_struct, thread.regs.gr[23]));
+ DEFINE(TASK_PT_GR24, offsetof(struct task_struct, thread.regs.gr[24]));
+ DEFINE(TASK_PT_GR25, offsetof(struct task_struct, thread.regs.gr[25]));
+ DEFINE(TASK_PT_GR26, offsetof(struct task_struct, thread.regs.gr[26]));
+ DEFINE(TASK_PT_GR27, offsetof(struct task_struct, thread.regs.gr[27]));
+ DEFINE(TASK_PT_GR28, offsetof(struct task_struct, thread.regs.gr[28]));
+ DEFINE(TASK_PT_GR29, offsetof(struct task_struct, thread.regs.gr[29]));
+ DEFINE(TASK_PT_GR30, offsetof(struct task_struct, thread.regs.gr[30]));
+ DEFINE(TASK_PT_GR31, offsetof(struct task_struct, thread.regs.gr[31]));
+ DEFINE(TASK_PT_FR0, offsetof(struct task_struct, thread.regs.fr[ 0]));
+ DEFINE(TASK_PT_FR1, offsetof(struct task_struct, thread.regs.fr[ 1]));
+ DEFINE(TASK_PT_FR2, offsetof(struct task_struct, thread.regs.fr[ 2]));
+ DEFINE(TASK_PT_FR3, offsetof(struct task_struct, thread.regs.fr[ 3]));
+ DEFINE(TASK_PT_FR4, offsetof(struct task_struct, thread.regs.fr[ 4]));
+ DEFINE(TASK_PT_FR5, offsetof(struct task_struct, thread.regs.fr[ 5]));
+ DEFINE(TASK_PT_FR6, offsetof(struct task_struct, thread.regs.fr[ 6]));
+ DEFINE(TASK_PT_FR7, offsetof(struct task_struct, thread.regs.fr[ 7]));
+ DEFINE(TASK_PT_FR8, offsetof(struct task_struct, thread.regs.fr[ 8]));
+ DEFINE(TASK_PT_FR9, offsetof(struct task_struct, thread.regs.fr[ 9]));
+ DEFINE(TASK_PT_FR10, offsetof(struct task_struct, thread.regs.fr[10]));
+ DEFINE(TASK_PT_FR11, offsetof(struct task_struct, thread.regs.fr[11]));
+ DEFINE(TASK_PT_FR12, offsetof(struct task_struct, thread.regs.fr[12]));
+ DEFINE(TASK_PT_FR13, offsetof(struct task_struct, thread.regs.fr[13]));
+ DEFINE(TASK_PT_FR14, offsetof(struct task_struct, thread.regs.fr[14]));
+ DEFINE(TASK_PT_FR15, offsetof(struct task_struct, thread.regs.fr[15]));
+ DEFINE(TASK_PT_FR16, offsetof(struct task_struct, thread.regs.fr[16]));
+ DEFINE(TASK_PT_FR17, offsetof(struct task_struct, thread.regs.fr[17]));
+ DEFINE(TASK_PT_FR18, offsetof(struct task_struct, thread.regs.fr[18]));
+ DEFINE(TASK_PT_FR19, offsetof(struct task_struct, thread.regs.fr[19]));
+ DEFINE(TASK_PT_FR20, offsetof(struct task_struct, thread.regs.fr[20]));
+ DEFINE(TASK_PT_FR21, offsetof(struct task_struct, thread.regs.fr[21]));
+ DEFINE(TASK_PT_FR22, offsetof(struct task_struct, thread.regs.fr[22]));
+ DEFINE(TASK_PT_FR23, offsetof(struct task_struct, thread.regs.fr[23]));
+ DEFINE(TASK_PT_FR24, offsetof(struct task_struct, thread.regs.fr[24]));
+ DEFINE(TASK_PT_FR25, offsetof(struct task_struct, thread.regs.fr[25]));
+ DEFINE(TASK_PT_FR26, offsetof(struct task_struct, thread.regs.fr[26]));
+ DEFINE(TASK_PT_FR27, offsetof(struct task_struct, thread.regs.fr[27]));
+ DEFINE(TASK_PT_FR28, offsetof(struct task_struct, thread.regs.fr[28]));
+ DEFINE(TASK_PT_FR29, offsetof(struct task_struct, thread.regs.fr[29]));
+ DEFINE(TASK_PT_FR30, offsetof(struct task_struct, thread.regs.fr[30]));
+ DEFINE(TASK_PT_FR31, offsetof(struct task_struct, thread.regs.fr[31]));
+ DEFINE(TASK_PT_SR0, offsetof(struct task_struct, thread.regs.sr[ 0]));
+ DEFINE(TASK_PT_SR1, offsetof(struct task_struct, thread.regs.sr[ 1]));
+ DEFINE(TASK_PT_SR2, offsetof(struct task_struct, thread.regs.sr[ 2]));
+ DEFINE(TASK_PT_SR3, offsetof(struct task_struct, thread.regs.sr[ 3]));
+ DEFINE(TASK_PT_SR4, offsetof(struct task_struct, thread.regs.sr[ 4]));
+ DEFINE(TASK_PT_SR5, offsetof(struct task_struct, thread.regs.sr[ 5]));
+ DEFINE(TASK_PT_SR6, offsetof(struct task_struct, thread.regs.sr[ 6]));
+ DEFINE(TASK_PT_SR7, offsetof(struct task_struct, thread.regs.sr[ 7]));
+ DEFINE(TASK_PT_IASQ0, offsetof(struct task_struct, thread.regs.iasq[0]));
+ DEFINE(TASK_PT_IASQ1, offsetof(struct task_struct, thread.regs.iasq[1]));
+ DEFINE(TASK_PT_IAOQ0, offsetof(struct task_struct, thread.regs.iaoq[0]));
+ DEFINE(TASK_PT_IAOQ1, offsetof(struct task_struct, thread.regs.iaoq[1]));
+ DEFINE(TASK_PT_CR27, offsetof(struct task_struct, thread.regs.cr27));
+ DEFINE(TASK_PT_ORIG_R28, offsetof(struct task_struct, thread.regs.orig_r28));
+ DEFINE(TASK_PT_KSP, offsetof(struct task_struct, thread.regs.ksp));
+ DEFINE(TASK_PT_KPC, offsetof(struct task_struct, thread.regs.kpc));
+ DEFINE(TASK_PT_SAR, offsetof(struct task_struct, thread.regs.sar));
+ DEFINE(TASK_PT_IIR, offsetof(struct task_struct, thread.regs.iir));
+ DEFINE(TASK_PT_ISR, offsetof(struct task_struct, thread.regs.isr));
+ DEFINE(TASK_PT_IOR, offsetof(struct task_struct, thread.regs.ior));
+ BLANK();
+ DEFINE(TASK_SZ, sizeof(struct task_struct));
+ DEFINE(TASK_SZ_ALGN, align(sizeof(struct task_struct), 64));
+ BLANK();
+ DEFINE(PT_PSW, offsetof(struct pt_regs, gr[ 0]));
+ DEFINE(PT_GR1, offsetof(struct pt_regs, gr[ 1]));
+ DEFINE(PT_GR2, offsetof(struct pt_regs, gr[ 2]));
+ DEFINE(PT_GR3, offsetof(struct pt_regs, gr[ 3]));
+ DEFINE(PT_GR4, offsetof(struct pt_regs, gr[ 4]));
+ DEFINE(PT_GR5, offsetof(struct pt_regs, gr[ 5]));
+ DEFINE(PT_GR6, offsetof(struct pt_regs, gr[ 6]));
+ DEFINE(PT_GR7, offsetof(struct pt_regs, gr[ 7]));
+ DEFINE(PT_GR8, offsetof(struct pt_regs, gr[ 8]));
+ DEFINE(PT_GR9, offsetof(struct pt_regs, gr[ 9]));
+ DEFINE(PT_GR10, offsetof(struct pt_regs, gr[10]));
+ DEFINE(PT_GR11, offsetof(struct pt_regs, gr[11]));
+ DEFINE(PT_GR12, offsetof(struct pt_regs, gr[12]));
+ DEFINE(PT_GR13, offsetof(struct pt_regs, gr[13]));
+ DEFINE(PT_GR14, offsetof(struct pt_regs, gr[14]));
+ DEFINE(PT_GR15, offsetof(struct pt_regs, gr[15]));
+ DEFINE(PT_GR16, offsetof(struct pt_regs, gr[16]));
+ DEFINE(PT_GR17, offsetof(struct pt_regs, gr[17]));
+ DEFINE(PT_GR18, offsetof(struct pt_regs, gr[18]));
+ DEFINE(PT_GR19, offsetof(struct pt_regs, gr[19]));
+ DEFINE(PT_GR20, offsetof(struct pt_regs, gr[20]));
+ DEFINE(PT_GR21, offsetof(struct pt_regs, gr[21]));
+ DEFINE(PT_GR22, offsetof(struct pt_regs, gr[22]));
+ DEFINE(PT_GR23, offsetof(struct pt_regs, gr[23]));
+ DEFINE(PT_GR24, offsetof(struct pt_regs, gr[24]));
+ DEFINE(PT_GR25, offsetof(struct pt_regs, gr[25]));
+ DEFINE(PT_GR26, offsetof(struct pt_regs, gr[26]));
+ DEFINE(PT_GR27, offsetof(struct pt_regs, gr[27]));
+ DEFINE(PT_GR28, offsetof(struct pt_regs, gr[28]));
+ DEFINE(PT_GR29, offsetof(struct pt_regs, gr[29]));
+ DEFINE(PT_GR30, offsetof(struct pt_regs, gr[30]));
+ DEFINE(PT_GR31, offsetof(struct pt_regs, gr[31]));
+ DEFINE(PT_FR0, offsetof(struct pt_regs, fr[ 0]));
+ DEFINE(PT_FR1, offsetof(struct pt_regs, fr[ 1]));
+ DEFINE(PT_FR2, offsetof(struct pt_regs, fr[ 2]));
+ DEFINE(PT_FR3, offsetof(struct pt_regs, fr[ 3]));
+ DEFINE(PT_FR4, offsetof(struct pt_regs, fr[ 4]));
+ DEFINE(PT_FR5, offsetof(struct pt_regs, fr[ 5]));
+ DEFINE(PT_FR6, offsetof(struct pt_regs, fr[ 6]));
+ DEFINE(PT_FR7, offsetof(struct pt_regs, fr[ 7]));
+ DEFINE(PT_FR8, offsetof(struct pt_regs, fr[ 8]));
+ DEFINE(PT_FR9, offsetof(struct pt_regs, fr[ 9]));
+ DEFINE(PT_FR10, offsetof(struct pt_regs, fr[10]));
+ DEFINE(PT_FR11, offsetof(struct pt_regs, fr[11]));
+ DEFINE(PT_FR12, offsetof(struct pt_regs, fr[12]));
+ DEFINE(PT_FR13, offsetof(struct pt_regs, fr[13]));
+ DEFINE(PT_FR14, offsetof(struct pt_regs, fr[14]));
+ DEFINE(PT_FR15, offsetof(struct pt_regs, fr[15]));
+ DEFINE(PT_FR16, offsetof(struct pt_regs, fr[16]));
+ DEFINE(PT_FR17, offsetof(struct pt_regs, fr[17]));
+ DEFINE(PT_FR18, offsetof(struct pt_regs, fr[18]));
+ DEFINE(PT_FR19, offsetof(struct pt_regs, fr[19]));
+ DEFINE(PT_FR20, offsetof(struct pt_regs, fr[20]));
+ DEFINE(PT_FR21, offsetof(struct pt_regs, fr[21]));
+ DEFINE(PT_FR22, offsetof(struct pt_regs, fr[22]));
+ DEFINE(PT_FR23, offsetof(struct pt_regs, fr[23]));
+ DEFINE(PT_FR24, offsetof(struct pt_regs, fr[24]));
+ DEFINE(PT_FR25, offsetof(struct pt_regs, fr[25]));
+ DEFINE(PT_FR26, offsetof(struct pt_regs, fr[26]));
+ DEFINE(PT_FR27, offsetof(struct pt_regs, fr[27]));
+ DEFINE(PT_FR28, offsetof(struct pt_regs, fr[28]));
+ DEFINE(PT_FR29, offsetof(struct pt_regs, fr[29]));
+ DEFINE(PT_FR30, offsetof(struct pt_regs, fr[30]));
+ DEFINE(PT_FR31, offsetof(struct pt_regs, fr[31]));
+ DEFINE(PT_SR0, offsetof(struct pt_regs, sr[ 0]));
+ DEFINE(PT_SR1, offsetof(struct pt_regs, sr[ 1]));
+ DEFINE(PT_SR2, offsetof(struct pt_regs, sr[ 2]));
+ DEFINE(PT_SR3, offsetof(struct pt_regs, sr[ 3]));
+ DEFINE(PT_SR4, offsetof(struct pt_regs, sr[ 4]));
+ DEFINE(PT_SR5, offsetof(struct pt_regs, sr[ 5]));
+ DEFINE(PT_SR6, offsetof(struct pt_regs, sr[ 6]));
+ DEFINE(PT_SR7, offsetof(struct pt_regs, sr[ 7]));
+ DEFINE(PT_IASQ0, offsetof(struct pt_regs, iasq[0]));
+ DEFINE(PT_IASQ1, offsetof(struct pt_regs, iasq[1]));
+ DEFINE(PT_IAOQ0, offsetof(struct pt_regs, iaoq[0]));
+ DEFINE(PT_IAOQ1, offsetof(struct pt_regs, iaoq[1]));
+ DEFINE(PT_CR27, offsetof(struct pt_regs, cr27));
+ DEFINE(PT_ORIG_R28, offsetof(struct pt_regs, orig_r28));
+ DEFINE(PT_KSP, offsetof(struct pt_regs, ksp));
+ DEFINE(PT_KPC, offsetof(struct pt_regs, kpc));
+ DEFINE(PT_SAR, offsetof(struct pt_regs, sar));
+ DEFINE(PT_IIR, offsetof(struct pt_regs, iir));
+ DEFINE(PT_ISR, offsetof(struct pt_regs, isr));
+ DEFINE(PT_IOR, offsetof(struct pt_regs, ior));
+ DEFINE(PT_SIZE, sizeof(struct pt_regs));
+ DEFINE(PT_SZ_ALGN, align(sizeof(struct pt_regs), 64));
+ BLANK();
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+ DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_SEGMENT, offsetof(struct thread_info, addr_limit));
+ DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
+ DEFINE(THREAD_SZ, sizeof(struct thread_info));
+ DEFINE(THREAD_SZ_ALGN, align(sizeof(struct thread_info), 64));
+ BLANK();
+ DEFINE(IRQSTAT_SIRQ_PEND, offsetof(irq_cpustat_t, __softirq_pending));
+ DEFINE(IRQSTAT_SZ, sizeof(irq_cpustat_t));
+ BLANK();
+ DEFINE(ICACHE_BASE, offsetof(struct pdc_cache_info, ic_base));
+ DEFINE(ICACHE_STRIDE, offsetof(struct pdc_cache_info, ic_stride));
+ DEFINE(ICACHE_COUNT, offsetof(struct pdc_cache_info, ic_count));
+ DEFINE(ICACHE_LOOP, offsetof(struct pdc_cache_info, ic_loop));
+ DEFINE(DCACHE_BASE, offsetof(struct pdc_cache_info, dc_base));
+ DEFINE(DCACHE_STRIDE, offsetof(struct pdc_cache_info, dc_stride));
+ DEFINE(DCACHE_COUNT, offsetof(struct pdc_cache_info, dc_count));
+ DEFINE(DCACHE_LOOP, offsetof(struct pdc_cache_info, dc_loop));
+ DEFINE(ITLB_SID_BASE, offsetof(struct pdc_cache_info, it_sp_base));
+ DEFINE(ITLB_SID_STRIDE, offsetof(struct pdc_cache_info, it_sp_stride));
+ DEFINE(ITLB_SID_COUNT, offsetof(struct pdc_cache_info, it_sp_count));
+ DEFINE(ITLB_OFF_BASE, offsetof(struct pdc_cache_info, it_off_base));
+ DEFINE(ITLB_OFF_STRIDE, offsetof(struct pdc_cache_info, it_off_stride));
+ DEFINE(ITLB_OFF_COUNT, offsetof(struct pdc_cache_info, it_off_count));
+ DEFINE(ITLB_LOOP, offsetof(struct pdc_cache_info, it_loop));
+ DEFINE(DTLB_SID_BASE, offsetof(struct pdc_cache_info, dt_sp_base));
+ DEFINE(DTLB_SID_STRIDE, offsetof(struct pdc_cache_info, dt_sp_stride));
+ DEFINE(DTLB_SID_COUNT, offsetof(struct pdc_cache_info, dt_sp_count));
+ DEFINE(DTLB_OFF_BASE, offsetof(struct pdc_cache_info, dt_off_base));
+ DEFINE(DTLB_OFF_STRIDE, offsetof(struct pdc_cache_info, dt_off_stride));
+ DEFINE(DTLB_OFF_COUNT, offsetof(struct pdc_cache_info, dt_off_count));
+ DEFINE(DTLB_LOOP, offsetof(struct pdc_cache_info, dt_loop));
+ BLANK();
+ DEFINE(PA_BLOCKSTEP_BIT, 31-PT_BLOCKSTEP_BIT);
+ DEFINE(PA_SINGLESTEP_BIT, 31-PT_SINGLESTEP_BIT);
+ BLANK();
+ DEFINE(ASM_PMD_SHIFT, PMD_SHIFT);
+ DEFINE(ASM_PGDIR_SHIFT, PGDIR_SHIFT);
+ DEFINE(ASM_BITS_PER_PGD, BITS_PER_PGD);
+ DEFINE(ASM_BITS_PER_PMD, BITS_PER_PMD);
+ DEFINE(ASM_BITS_PER_PTE, BITS_PER_PTE);
+ DEFINE(ASM_PGD_PMD_OFFSET, -(PAGE_SIZE << PGD_ORDER));
+ DEFINE(ASM_PMD_ENTRY, ((PAGE_OFFSET & PMD_MASK) >> PMD_SHIFT));
+ DEFINE(ASM_PGD_ENTRY, PAGE_OFFSET >> PGDIR_SHIFT);
+ DEFINE(ASM_PGD_ENTRY_SIZE, PGD_ENTRY_SIZE);
+ DEFINE(ASM_PMD_ENTRY_SIZE, PMD_ENTRY_SIZE);
+ DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE);
+ DEFINE(ASM_PT_INITIAL, PT_INITIAL);
+ DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
+ BLANK();
+ DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
+ DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
+ DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
+ return 0;
+}
diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c
new file mode 100644
index 000000000000..d1833f164bbe
--- /dev/null
+++ b/arch/parisc/kernel/binfmt_elf32.c
@@ -0,0 +1,126 @@
+/*
+ * Support for 32-bit Linux/Parisc ELF binaries on 64 bit kernels
+ *
+ * Copyright (C) 2000 John Marvin
+ * Copyright (C) 2000 Hewlett Packard Co.
+ *
+ * Heavily inspired from various other efforts to do the same thing
+ * (ia64,sparc64/mips64)
+ */
+
+/* Make sure include/asm-parisc/elf.h does the right thing */
+
+#define ELF_CLASS ELFCLASS32
+
+#define ELF_CORE_COPY_REGS(dst, pt) \
+ memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \
+ { int i; \
+ for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \
+ for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \
+ } \
+ dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \
+ dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \
+ dst[44] = (elf_greg_t) pt->sar; dst[45] = (elf_greg_t) pt->iir; \
+ dst[46] = (elf_greg_t) pt->isr; dst[47] = (elf_greg_t) pt->ior; \
+ dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \
+ dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \
+ dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \
+ dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \
+ dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \
+ dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \
+ dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \
+ dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15);
+
+
+typedef unsigned int elf_greg_t;
+
+#include <linux/spinlock.h>
+#include <asm/processor.h>
+#include <linux/module.h>
+#include <linux/elfcore.h>
+#include <linux/compat.h> /* struct compat_timeval */
+
+#define elf_prstatus elf_prstatus32
+struct elf_prstatus32
+{
+ struct elf_siginfo pr_info; /* Info associated with signal */
+ short pr_cursig; /* Current signal */
+ unsigned int pr_sigpend; /* Set of pending signals */
+ unsigned int pr_sighold; /* Set of held signals */
+ pid_t pr_pid;
+ pid_t pr_ppid;
+ pid_t pr_pgrp;
+ pid_t pr_sid;
+ struct compat_timeval pr_utime; /* User time */
+ struct compat_timeval pr_stime; /* System time */
+ struct compat_timeval pr_cutime; /* Cumulative user time */
+ struct compat_timeval pr_cstime; /* Cumulative system time */
+ elf_gregset_t pr_reg; /* GP registers */
+ int pr_fpvalid; /* True if math co-processor being used. */
+};
+
+#define elf_prpsinfo elf_prpsinfo32
+struct elf_prpsinfo32
+{
+ char pr_state; /* numeric process state */
+ char pr_sname; /* char for pr_state */
+ char pr_zomb; /* zombie */
+ char pr_nice; /* nice val */
+ unsigned int pr_flag; /* flags */
+ u16 pr_uid;
+ u16 pr_gid;
+ pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ /* Lots missing */
+ char pr_fname[16]; /* filename of executable */
+ char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
+};
+
+#define elf_addr_t unsigned int
+#define init_elf_binfmt init_elf32_binfmt
+
+#define ELF_PLATFORM ("PARISC32\0")
+
+/*
+ * We should probably use this macro to set a flag somewhere to indicate
+ * this is a 32 on 64 process. We could use PER_LINUX_32BIT, or we
+ * could set a processor dependent flag in the thread_struct.
+ */
+
+#define SET_PERSONALITY(ex, ibcs2) \
+ current->personality = PER_LINUX32; \
+ current->thread.map_base = DEFAULT_MAP_BASE32; \
+ current->thread.task_size = DEFAULT_TASK_SIZE32 \
+
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
+static __inline__ void
+cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
+{
+ unsigned long jiffies = cputime_to_jiffies(cputime);
+ value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
+ value->tv_sec = jiffies / HZ;
+}
+
+#include "../../../fs/binfmt_elf.c"
+
+/* Set up a separate execution domain for ELF32 binaries running
+ * on an ELF64 kernel */
+
+static struct exec_domain parisc32_exec_domain = {
+ .name = "Linux/ELF32",
+ .pers_low = PER_LINUX32,
+ .pers_high = PER_LINUX32,
+};
+
+static int __init parisc32_exec_init(void)
+{
+ /* steal the identity signal mappings from the default domain */
+ parisc32_exec_domain.signal_map = default_exec_domain.signal_map;
+ parisc32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
+
+ register_exec_domain(&parisc32_exec_domain);
+
+ return 0;
+}
+
+__initcall(parisc32_exec_init);
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
new file mode 100644
index 000000000000..f46a07a79218
--- /dev/null
+++ b/arch/parisc/kernel/cache.c
@@ -0,0 +1,366 @@
+/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 Helge Deller (07-13-1999)
+ * Copyright (C) 1999 SuSE GmbH Nuernberg
+ * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
+ *
+ * Cache and TLB management
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/pagemap.h>
+
+#include <asm/pdc.h>
+#include <asm/cache.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/processor.h>
+
+int split_tlb;
+int dcache_stride;
+int icache_stride;
+EXPORT_SYMBOL(dcache_stride);
+
+
+#if defined(CONFIG_SMP)
+/* On some machines (e.g. ones with the Merced bus), there can be
+ * only a single PxTLB broadcast at a time; this must be guaranteed
+ * by software. We put a spinlock around all TLB flushes to
+ * ensure this.
+ */
+DEFINE_SPINLOCK(pa_tlb_lock);
+EXPORT_SYMBOL(pa_tlb_lock);
+#endif
+
+struct pdc_cache_info cache_info;
+#ifndef CONFIG_PA20
+static struct pdc_btlb_info btlb_info;
+#endif
+
+#ifdef CONFIG_SMP
+void
+flush_data_cache(void)
+{
+ on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
+}
+void
+flush_instruction_cache(void)
+{
+ on_each_cpu((void (*)(void *))flush_instruction_cache_local, NULL, 1, 1);
+}
+#endif
+
+void
+flush_cache_all_local(void)
+{
+ flush_instruction_cache_local();
+ flush_data_cache_local();
+}
+EXPORT_SYMBOL(flush_cache_all_local);
+
+/* flushes EVERYTHING (tlb & cache) */
+
+void
+flush_all_caches(void)
+{
+ flush_cache_all();
+ flush_tlb_all();
+}
+EXPORT_SYMBOL(flush_all_caches);
+
+void
+update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+ struct page *page = pte_page(pte);
+
+ if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&
+ test_bit(PG_dcache_dirty, &page->flags)) {
+
+ flush_kernel_dcache_page(page_address(page));
+ clear_bit(PG_dcache_dirty, &page->flags);
+ }
+}
+
+void
+show_cache_info(struct seq_file *m)
+{
+ seq_printf(m, "I-cache\t\t: %ld KB\n",
+ cache_info.ic_size/1024 );
+ seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %d-way associative)\n",
+ cache_info.dc_size/1024,
+ (cache_info.dc_conf.cc_wt ? "WT":"WB"),
+ (cache_info.dc_conf.cc_sh ? ", shared I/D":""),
+ (cache_info.dc_conf.cc_assoc)
+ );
+
+ seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
+ cache_info.it_size,
+ cache_info.dt_size,
+ cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
+ );
+
+#ifndef CONFIG_PA20
+ /* BTLB - Block TLB */
+ if (btlb_info.max_size==0) {
+ seq_printf(m, "BTLB\t\t: not supported\n" );
+ } else {
+ seq_printf(m,
+ "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
+ "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
+ "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
+ btlb_info.max_size, (int)4096,
+ btlb_info.max_size>>8,
+ btlb_info.fixed_range_info.num_i,
+ btlb_info.fixed_range_info.num_d,
+ btlb_info.fixed_range_info.num_comb,
+ btlb_info.variable_range_info.num_i,
+ btlb_info.variable_range_info.num_d,
+ btlb_info.variable_range_info.num_comb
+ );
+ }
+#endif
+}
+
+void __init
+parisc_cache_init(void)
+{
+ if (pdc_cache_info(&cache_info) < 0)
+ panic("parisc_cache_init: pdc_cache_info failed");
+
+#if 0
+ printk("ic_size %lx dc_size %lx it_size %lx\n",
+ cache_info.ic_size,
+ cache_info.dc_size,
+ cache_info.it_size);
+
+ printk("DC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
+ cache_info.dc_base,
+ cache_info.dc_stride,
+ cache_info.dc_count,
+ cache_info.dc_loop);
+
+ printk("dc_conf = 0x%lx alias %d blk %d line %d shift %d\n",
+ *(unsigned long *) (&cache_info.dc_conf),
+ cache_info.dc_conf.cc_alias,
+ cache_info.dc_conf.cc_block,
+ cache_info.dc_conf.cc_line,
+ cache_info.dc_conf.cc_shift);
+ printk(" wt %d sh %d cst %d assoc %d\n",
+ cache_info.dc_conf.cc_wt,
+ cache_info.dc_conf.cc_sh,
+ cache_info.dc_conf.cc_cst,
+ cache_info.dc_conf.cc_assoc);
+
+ printk("IC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
+ cache_info.ic_base,
+ cache_info.ic_stride,
+ cache_info.ic_count,
+ cache_info.ic_loop);
+
+ printk("ic_conf = 0x%lx alias %d blk %d line %d shift %d\n",
+ *(unsigned long *) (&cache_info.ic_conf),
+ cache_info.ic_conf.cc_alias,
+ cache_info.ic_conf.cc_block,
+ cache_info.ic_conf.cc_line,
+ cache_info.ic_conf.cc_shift);
+ printk(" wt %d sh %d cst %d assoc %d\n",
+ cache_info.ic_conf.cc_wt,
+ cache_info.ic_conf.cc_sh,
+ cache_info.ic_conf.cc_cst,
+ cache_info.ic_conf.cc_assoc);
+
+ printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
+ cache_info.dt_conf.tc_sh,
+ cache_info.dt_conf.tc_page,
+ cache_info.dt_conf.tc_cst,
+ cache_info.dt_conf.tc_aid,
+ cache_info.dt_conf.tc_pad1);
+
+ printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
+ cache_info.it_conf.tc_sh,
+ cache_info.it_conf.tc_page,
+ cache_info.it_conf.tc_cst,
+ cache_info.it_conf.tc_aid,
+ cache_info.it_conf.tc_pad1);
+#endif
+
+ split_tlb = 0;
+ if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) {
+ if (cache_info.dt_conf.tc_sh == 2)
+ printk(KERN_WARNING "Unexpected TLB configuration. "
+ "Will flush I/D separately (could be optimized).\n");
+
+ split_tlb = 1;
+ }
+
+ /* "New and Improved" version from Jim Hull
+ * (1 << (cc_block-1)) * (cc_line << (4 + cnf.cc_shift))
+ */
+#define CAFL_STRIDE(cnf) (cnf.cc_line << (3 + cnf.cc_block + cnf.cc_shift))
+ dcache_stride = CAFL_STRIDE(cache_info.dc_conf);
+ icache_stride = CAFL_STRIDE(cache_info.ic_conf);
+#undef CAFL_STRIDE
+
+#ifndef CONFIG_PA20
+ if (pdc_btlb_info(&btlb_info) < 0) {
+ memset(&btlb_info, 0, sizeof btlb_info);
+ }
+#endif
+
+ if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) ==
+ PDC_MODEL_NVA_UNSUPPORTED) {
+ printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n");
+#if 0
+ panic("SMP kernel required to avoid non-equivalent aliasing");
+#endif
+ }
+}
+
+void disable_sr_hashing(void)
+{
+ int srhash_type;
+
+ switch (boot_cpu_data.cpu_type) {
+ case pcx: /* We shouldn't get this far. setup.c should prevent it. */
+ BUG();
+ return;
+
+ case pcxs:
+ case pcxt:
+ case pcxt_:
+ srhash_type = SRHASH_PCXST;
+ break;
+
+ case pcxl:
+ srhash_type = SRHASH_PCXL;
+ break;
+
+ case pcxl2: /* pcxl2 doesn't support space register hashing */
+ return;
+
+ default: /* Currently all PA2.0 machines use the same ins. sequence */
+ srhash_type = SRHASH_PA20;
+ break;
+ }
+
+ disable_sr_hashing_asm(srhash_type);
+}
+
+void flush_dcache_page(struct page *page)
+{
+ struct address_space *mapping = page_mapping(page);
+ struct vm_area_struct *mpnt;
+ struct prio_tree_iter iter;
+ unsigned long offset;
+ unsigned long addr;
+ pgoff_t pgoff;
+ pte_t *pte;
+ unsigned long pfn = page_to_pfn(page);
+
+
+ if (mapping && !mapping_mapped(mapping)) {
+ set_bit(PG_dcache_dirty, &page->flags);
+ return;
+ }
+
+ flush_kernel_dcache_page(page_address(page));
+
+ if (!mapping)
+ return;
+
+ pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+
+ /* We have carefully arranged in arch_get_unmapped_area() that
+ * *any* mappings of a file are always congruently mapped (whether
+ * declared as MAP_PRIVATE or MAP_SHARED), so we only need
+ * to flush one address here for them all to become coherent */
+
+ flush_dcache_mmap_lock(mapping);
+ vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
+ offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
+ addr = mpnt->vm_start + offset;
+
+ /* Flush instructions produce non access tlb misses.
+ * On PA, we nullify these instructions rather than
+ * taking a page fault if the pte doesn't exist.
+ * This is just for speed. If the page translation
+ * isn't there, there's no point exciting the
+ * nadtlb handler into a nullification frenzy */
+
+
+ if(!(pte = translation_exists(mpnt, addr)))
+ continue;
+
+ /* make sure we really have this page: the private
+ * mappings may cover this area but have COW'd this
+ * particular page */
+ if(pte_pfn(*pte) != pfn)
+ continue;
+
+ __flush_cache_page(mpnt, addr);
+
+ break;
+ }
+ flush_dcache_mmap_unlock(mapping);
+}
+EXPORT_SYMBOL(flush_dcache_page);
+
+/* Defined in arch/parisc/kernel/pacache.S */
+EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
+EXPORT_SYMBOL(flush_kernel_dcache_page);
+EXPORT_SYMBOL(flush_data_cache_local);
+EXPORT_SYMBOL(flush_kernel_icache_range_asm);
+
+void clear_user_page_asm(void *page, unsigned long vaddr)
+{
+ /* This function is implemented in assembly in pacache.S */
+ extern void __clear_user_page_asm(void *page, unsigned long vaddr);
+
+ purge_tlb_start();
+ __clear_user_page_asm(page, vaddr);
+ purge_tlb_end();
+}
+
+#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
+int parisc_cache_flush_threshold = FLUSH_THRESHOLD;
+
+void parisc_setup_cache_timing(void)
+{
+ unsigned long rangetime, alltime;
+ extern char _text; /* start of kernel code, defined by linker */
+ extern char _end; /* end of BSS, defined by linker */
+ unsigned long size;
+
+ alltime = mfctl(16);
+ flush_data_cache();
+ alltime = mfctl(16) - alltime;
+
+ size = (unsigned long)(&_end - _text);
+ rangetime = mfctl(16);
+ flush_kernel_dcache_range((unsigned long)&_text, size);
+ rangetime = mfctl(16) - rangetime;
+
+ printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
+ alltime, size, rangetime);
+
+ /* Racy, but if we see an intermediate value, it's ok too... */
+ parisc_cache_flush_threshold = size * alltime / rangetime;
+
+ parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1);
+ if (!parisc_cache_flush_threshold)
+ parisc_cache_flush_threshold = FLUSH_THRESHOLD;
+
+ printk("Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
+}
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
new file mode 100644
index 000000000000..ebf186656afb
--- /dev/null
+++ b/arch/parisc/kernel/drivers.c
@@ -0,0 +1,765 @@
+/*
+ * drivers.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Copyright (c) 1999 The Puffin Group
+ * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard
+ * Copyright (c) 2001 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2001,2002 Ryan Bradetich
+ * Copyright (c) 2004-2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * The file handles registering devices and drivers, then matching them.
+ * It's the closest we get to a dating agency.
+ *
+ * If you're thinking about modifying this file, here are some gotchas to
+ * bear in mind:
+ * - 715/Mirage device paths have a dummy device between Lasi and its children
+ * - The EISA adapter may show up as a sibling or child of Wax
+ * - Dino has an optionally functional serial port. If firmware enables it,
+ * it shows up as a child of Dino. If firmware disables it, the buswalk
+ * finds it and it shows up as a child of Cujo
+ * - Dino has both parisc and pci devices as children
+ * - parisc devices are discovered in a random order, including children
+ * before parents in some cases.
+ */
+
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/pdc.h>
+#include <asm/parisc-device.h>
+
+/* See comments in include/asm-parisc/pci.h */
+struct hppa_dma_ops *hppa_dma_ops;
+EXPORT_SYMBOL(hppa_dma_ops);
+
+static struct device root = {
+ .bus_id = "parisc",
+};
+
+#define for_each_padev(padev) \
+ for (padev = next_dev(&root); padev != NULL; \
+ padev = next_dev(&padev->dev))
+
+#define check_dev(padev) \
+ (padev->id.hw_type != HPHW_FAULTY) ? padev : next_dev(&padev->dev)
+
+/**
+ * next_dev - enumerates registered devices
+ * @dev: the previous device returned from next_dev
+ *
+ * next_dev does a depth-first search of the tree, returning parents
+ * before children. Returns NULL when there are no more devices.
+ */
+static struct parisc_device *next_dev(struct device *dev)
+{
+ if (!list_empty(&dev->children)) {
+ dev = list_to_dev(dev->children.next);
+ return check_dev(to_parisc_device(dev));
+ }
+
+ while (dev != &root) {
+ if (dev->node.next != &dev->parent->children) {
+ dev = list_to_dev(dev->node.next);
+ return to_parisc_device(dev);
+ }
+ dev = dev->parent;
+ }
+
+ return NULL;
+}
+
+/**
+ * match_device - Report whether this driver can handle this device
+ * @driver: the PA-RISC driver to try
+ * @dev: the PA-RISC device to try
+ */
+static int match_device(struct parisc_driver *driver, struct parisc_device *dev)
+{
+ const struct parisc_device_id *ids;
+
+ for (ids = driver->id_table; ids->sversion; ids++) {
+ if ((ids->sversion != SVERSION_ANY_ID) &&
+ (ids->sversion != dev->id.sversion))
+ continue;
+
+ if ((ids->hw_type != HWTYPE_ANY_ID) &&
+ (ids->hw_type != dev->id.hw_type))
+ continue;
+
+ if ((ids->hversion != HVERSION_ANY_ID) &&
+ (ids->hversion != dev->id.hversion))
+ continue;
+
+ return 1;
+ }
+ return 0;
+}
+
+static void claim_device(struct parisc_driver *driver, struct parisc_device *dev)
+{
+ dev->driver = driver;
+ request_mem_region(dev->hpa, 0x1000, driver->name);
+}
+
+static int parisc_driver_probe(struct device *dev)
+{
+ int rc;
+ struct parisc_device *pa_dev = to_parisc_device(dev);
+ struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
+
+ rc = pa_drv->probe(pa_dev);
+
+ if(!rc)
+ claim_device(pa_drv, pa_dev);
+
+ return rc;
+}
+
+static int parisc_driver_remove(struct device *dev)
+{
+ struct parisc_device *pa_dev = to_parisc_device(dev);
+ struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
+ if (pa_drv->remove)
+ pa_drv->remove(pa_dev);
+ release_mem_region(pa_dev->hpa, 0x1000);
+
+ return 0;
+}
+
+
+/**
+ * register_parisc_driver - Register this driver if it can handle a device
+ * @driver: the PA-RISC driver to try
+ */
+int register_parisc_driver(struct parisc_driver *driver)
+{
+ /* FIXME: we need this because apparently the sti
+ * driver can be registered twice */
+ if(driver->drv.name) {
+ printk(KERN_WARNING
+ "BUG: skipping previously registered driver %s\n",
+ driver->name);
+ return 1;
+ }
+
+ if (!driver->probe) {
+ printk(KERN_WARNING
+ "BUG: driver %s has no probe routine\n",
+ driver->name);
+ return 1;
+ }
+
+ driver->drv.bus = &parisc_bus_type;
+
+ /* We install our own probe and remove routines */
+ WARN_ON(driver->drv.probe != NULL);
+ WARN_ON(driver->drv.remove != NULL);
+
+ driver->drv.probe = parisc_driver_probe;
+ driver->drv.remove = parisc_driver_remove;
+ driver->drv.name = driver->name;
+
+ return driver_register(&driver->drv);
+}
+EXPORT_SYMBOL(register_parisc_driver);
+
+/**
+ * count_parisc_driver - count # of devices this driver would match
+ * @driver: the PA-RISC driver to try
+ *
+ * Use by IOMMU support to "guess" the right size IOPdir.
+ * Formula is something like memsize/(num_iommu * entry_size).
+ */
+int count_parisc_driver(struct parisc_driver *driver)
+{
+ struct parisc_device *device;
+ int cnt = 0;
+
+ for_each_padev(device) {
+ if (match_device(driver, device))
+ cnt++;
+ }
+
+ return cnt;
+}
+
+
+
+/**
+ * unregister_parisc_driver - Unregister this driver from the list of drivers
+ * @driver: the PA-RISC driver to unregister
+ */
+int unregister_parisc_driver(struct parisc_driver *driver)
+{
+ driver_unregister(&driver->drv);
+ return 0;
+}
+EXPORT_SYMBOL(unregister_parisc_driver);
+
+static struct parisc_device *find_device_by_addr(unsigned long hpa)
+{
+ struct parisc_device *dev;
+ for_each_padev(dev) {
+ if (dev->hpa == hpa)
+ return dev;
+ }
+ return NULL;
+}
+
+/**
+ * find_pa_parent_type - Find a parent of a specific type
+ * @dev: The device to start searching from
+ * @type: The device type to search for.
+ *
+ * Walks up the device tree looking for a device of the specified type.
+ * If it finds it, it returns it. If not, it returns NULL.
+ */
+const struct parisc_device *
+find_pa_parent_type(const struct parisc_device *padev, int type)
+{
+ const struct device *dev = &padev->dev;
+ while (dev != &root) {
+ struct parisc_device *candidate = to_parisc_device(dev);
+ if (candidate->id.hw_type == type)
+ return candidate;
+ dev = dev->parent;
+ }
+
+ return NULL;
+}
+
+#ifdef CONFIG_PCI
+static inline int is_pci_dev(struct device *dev)
+{
+ return dev->bus == &pci_bus_type;
+}
+#else
+static inline int is_pci_dev(struct device *dev)
+{
+ return 0;
+}
+#endif
+
+/*
+ * get_node_path fills in @path with the firmware path to the device.
+ * Note that if @node is a parisc device, we don't fill in the 'mod' field.
+ * This is because both callers pass the parent and fill in the mod
+ * themselves. If @node is a PCI device, we do fill it in, even though this
+ * is inconsistent.
+ */
+static void get_node_path(struct device *dev, struct hardware_path *path)
+{
+ int i = 5;
+ memset(&path->bc, -1, 6);
+
+ if (is_pci_dev(dev)) {
+ unsigned int devfn = to_pci_dev(dev)->devfn;
+ path->mod = PCI_FUNC(devfn);
+ path->bc[i--] = PCI_SLOT(devfn);
+ dev = dev->parent;
+ }
+
+ while (dev != &root) {
+ if (is_pci_dev(dev)) {
+ unsigned int devfn = to_pci_dev(dev)->devfn;
+ path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn)<< 5);
+ } else if (dev->bus == &parisc_bus_type) {
+ path->bc[i--] = to_parisc_device(dev)->hw_path;
+ }
+ dev = dev->parent;
+ }
+}
+
+static char *print_hwpath(struct hardware_path *path, char *output)
+{
+ int i;
+ for (i = 0; i < 6; i++) {
+ if (path->bc[i] == -1)
+ continue;
+ output += sprintf(output, "%u/", (unsigned char) path->bc[i]);
+ }
+ output += sprintf(output, "%u", (unsigned char) path->mod);
+ return output;
+}
+
+/**
+ * print_pa_hwpath - Returns hardware path for PA devices
+ * dev: The device to return the path for
+ * output: Pointer to a previously-allocated array to place the path in.
+ *
+ * This function fills in the output array with a human-readable path
+ * to a PA device. This string is compatible with that used by PDC, and
+ * may be printed on the outside of the box.
+ */
+char *print_pa_hwpath(struct parisc_device *dev, char *output)
+{
+ struct hardware_path path;
+
+ get_node_path(dev->dev.parent, &path);
+ path.mod = dev->hw_path;
+ return print_hwpath(&path, output);
+}
+EXPORT_SYMBOL(print_pa_hwpath);
+
+#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+/**
+ * get_pci_node_path - Determines the hardware path for a PCI device
+ * @pdev: The device to return the path for
+ * @path: Pointer to a previously-allocated array to place the path in.
+ *
+ * This function fills in the hardware_path structure with the route to
+ * the specified PCI device. This structure is suitable for passing to
+ * PDC calls.
+ */
+void get_pci_node_path(struct pci_dev *pdev, struct hardware_path *path)
+{
+ get_node_path(&pdev->dev, path);
+}
+EXPORT_SYMBOL(get_pci_node_path);
+
+/**
+ * print_pci_hwpath - Returns hardware path for PCI devices
+ * dev: The device to return the path for
+ * output: Pointer to a previously-allocated array to place the path in.
+ *
+ * This function fills in the output array with a human-readable path
+ * to a PCI device. This string is compatible with that used by PDC, and
+ * may be printed on the outside of the box.
+ */
+char *print_pci_hwpath(struct pci_dev *dev, char *output)
+{
+ struct hardware_path path;
+
+ get_pci_node_path(dev, &path);
+ return print_hwpath(&path, output);
+}
+EXPORT_SYMBOL(print_pci_hwpath);
+
+#endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */
+
+static void setup_bus_id(struct parisc_device *padev)
+{
+ struct hardware_path path;
+ char *output = padev->dev.bus_id;
+ int i;
+
+ get_node_path(padev->dev.parent, &path);
+
+ for (i = 0; i < 6; i++) {
+ if (path.bc[i] == -1)
+ continue;
+ output += sprintf(output, "%u:", (unsigned char) path.bc[i]);
+ }
+ sprintf(output, "%u", (unsigned char) padev->hw_path);
+}
+
+struct parisc_device * create_tree_node(char id, struct device *parent)
+{
+ struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ memset(dev, 0, sizeof(*dev));
+ dev->hw_path = id;
+ dev->id.hw_type = HPHW_FAULTY;
+
+ dev->dev.parent = parent;
+ setup_bus_id(dev);
+
+ dev->dev.bus = &parisc_bus_type;
+ dev->dma_mask = 0xffffffffUL; /* PARISC devices are 32-bit */
+
+ /* make the generic dma mask a pointer to the parisc one */
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.coherent_dma_mask = dev->dma_mask;
+ device_register(&dev->dev);
+
+ return dev;
+}
+
+/**
+ * alloc_tree_node - returns a device entry in the iotree
+ * @parent: the parent node in the tree
+ * @id: the element of the module path for this entry
+ *
+ * Checks all the children of @parent for a matching @id. If none
+ * found, it allocates a new device and returns it.
+ */
+static struct parisc_device * alloc_tree_node(struct device *parent, char id)
+{
+ struct device *dev;
+
+ list_for_each_entry(dev, &parent->children, node) {
+ struct parisc_device *padev = to_parisc_device(dev);
+ if (padev->hw_path == id)
+ return padev;
+ }
+
+ return create_tree_node(id, parent);
+}
+
+static struct parisc_device *create_parisc_device(struct hardware_path *modpath)
+{
+ int i;
+ struct device *parent = &root;
+ for (i = 0; i < 6; i++) {
+ if (modpath->bc[i] == -1)
+ continue;
+ parent = &alloc_tree_node(parent, modpath->bc[i])->dev;
+ }
+ return alloc_tree_node(parent, modpath->mod);
+}
+
+struct parisc_device *
+alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path)
+{
+ int status;
+ unsigned long bytecnt;
+ u8 iodc_data[32];
+ struct parisc_device *dev;
+ const char *name;
+
+ /* Check to make sure this device has not already been added - Ryan */
+ if (find_device_by_addr(hpa) != NULL)
+ return NULL;
+
+ status = pdc_iodc_read(&bytecnt, hpa, 0, &iodc_data, 32);
+ if (status != PDC_OK)
+ return NULL;
+
+ dev = create_parisc_device(mod_path);
+ if (dev->id.hw_type != HPHW_FAULTY) {
+ char p[64];
+ print_pa_hwpath(dev, p);
+ printk("Two devices have hardware path %s. Please file a bug with HP.\n"
+ "In the meantime, you could try rearranging your cards.\n", p);
+ return NULL;
+ }
+
+ dev->id.hw_type = iodc_data[3] & 0x1f;
+ dev->id.hversion = (iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4);
+ dev->id.hversion_rev = iodc_data[1] & 0x0f;
+ dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) |
+ (iodc_data[5] << 8) | iodc_data[6];
+ dev->hpa = hpa;
+ name = parisc_hardware_description(&dev->id);
+ if (name) {
+ strlcpy(dev->name, name, sizeof(dev->name));
+ }
+
+ return dev;
+}
+
+static int parisc_generic_match(struct device *dev, struct device_driver *drv)
+{
+ return match_device(to_parisc_driver(drv), to_parisc_device(dev));
+}
+
+#define pa_dev_attr(name, field, format_string) \
+static ssize_t name##_show(struct device *dev, char *buf) \
+{ \
+ struct parisc_device *padev = to_parisc_device(dev); \
+ return sprintf(buf, format_string, padev->field); \
+}
+
+#define pa_dev_attr_id(field, format) pa_dev_attr(field, id.field, format)
+
+pa_dev_attr(irq, irq, "%u\n");
+pa_dev_attr_id(hw_type, "0x%02x\n");
+pa_dev_attr(rev, id.hversion_rev, "0x%x\n");
+pa_dev_attr_id(hversion, "0x%03x\n");
+pa_dev_attr_id(sversion, "0x%05x\n");
+
+static struct device_attribute parisc_device_attrs[] = {
+ __ATTR_RO(irq),
+ __ATTR_RO(hw_type),
+ __ATTR_RO(rev),
+ __ATTR_RO(hversion),
+ __ATTR_RO(sversion),
+ __ATTR_NULL,
+};
+
+struct bus_type parisc_bus_type = {
+ .name = "parisc",
+ .match = parisc_generic_match,
+ .dev_attrs = parisc_device_attrs,
+};
+
+/**
+ * register_parisc_device - Locate a driver to manage this device.
+ * @dev: The parisc device.
+ *
+ * Search the driver list for a driver that is willing to manage
+ * this device.
+ */
+int register_parisc_device(struct parisc_device *dev)
+{
+ if (!dev)
+ return 0;
+
+ if (dev->driver)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * match_pci_device - Matches a pci device against a given hardware path
+ * entry.
+ * @dev: the generic device (known to be contained by a pci_dev).
+ * @index: the current BC index
+ * @modpath: the hardware path.
+ * @return: true if the device matches the hardware path.
+ */
+static int match_pci_device(struct device *dev, int index,
+ struct hardware_path *modpath)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ int id;
+
+ if (index == 5) {
+ /* we are at the end of the path, and on the actual device */
+ unsigned int devfn = pdev->devfn;
+ return ((modpath->bc[5] == PCI_SLOT(devfn)) &&
+ (modpath->mod == PCI_FUNC(devfn)));
+ }
+
+ id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5);
+ return (modpath->bc[index] == id);
+}
+
+/**
+ * match_parisc_device - Matches a parisc device against a given hardware
+ * path entry.
+ * @dev: the generic device (known to be contained by a parisc_device).
+ * @index: the current BC index
+ * @modpath: the hardware path.
+ * @return: true if the device matches the hardware path.
+ */
+static int match_parisc_device(struct device *dev, int index,
+ struct hardware_path *modpath)
+{
+ struct parisc_device *curr = to_parisc_device(dev);
+ char id = (index == 6) ? modpath->mod : modpath->bc[index];
+
+ return (curr->hw_path == id);
+}
+
+/**
+ * parse_tree_node - returns a device entry in the iotree
+ * @parent: the parent node in the tree
+ * @index: the current BC index
+ * @modpath: the hardware_path struct to match a device against
+ * @return: The corresponding device if found, NULL otherwise.
+ *
+ * Checks all the children of @parent for a matching @id. If none
+ * found, it returns NULL.
+ */
+static struct device *
+parse_tree_node(struct device *parent, int index, struct hardware_path *modpath)
+{
+ struct device *device;
+
+ list_for_each_entry(device, &parent->children, node) {
+ if (device->bus == &parisc_bus_type) {
+ if (match_parisc_device(device, index, modpath))
+ return device;
+ } else if (is_pci_dev(device)) {
+ if (match_pci_device(device, index, modpath))
+ return device;
+ } else if (device->bus == NULL) {
+ /* we are on a bus bridge */
+ struct device *new = parse_tree_node(device, index, modpath);
+ if (new)
+ return new;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * hwpath_to_device - Finds the generic device corresponding to a given hardware path.
+ * @modpath: the hardware path.
+ * @return: The target device, NULL if not found.
+ */
+struct device *hwpath_to_device(struct hardware_path *modpath)
+{
+ int i;
+ struct device *parent = &root;
+ for (i = 0; i < 6; i++) {
+ if (modpath->bc[i] == -1)
+ continue;
+ parent = parse_tree_node(parent, i, modpath);
+ if (!parent)
+ return NULL;
+ }
+ if (is_pci_dev(parent)) /* pci devices already parse MOD */
+ return parent;
+ else
+ return parse_tree_node(parent, 6, modpath);
+}
+EXPORT_SYMBOL(hwpath_to_device);
+
+/**
+ * device_to_hwpath - Populates the hwpath corresponding to the given device.
+ * @param dev the target device
+ * @param path pointer to a previously allocated hwpath struct to be filled in
+ */
+void device_to_hwpath(struct device *dev, struct hardware_path *path)
+{
+ struct parisc_device *padev;
+ if (dev->bus == &parisc_bus_type) {
+ padev = to_parisc_device(dev);
+ get_node_path(dev->parent, path);
+ path->mod = padev->hw_path;
+ } else if (is_pci_dev(dev)) {
+ get_node_path(dev, path);
+ }
+}
+EXPORT_SYMBOL(device_to_hwpath);
+
+#define BC_PORT_MASK 0x8
+#define BC_LOWER_PORT 0x8
+
+#define BUS_CONVERTER(dev) \
+ ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT))
+
+#define IS_LOWER_PORT(dev) \
+ ((gsc_readl(dev->hpa + offsetof(struct bc_module, io_status)) \
+ & BC_PORT_MASK) == BC_LOWER_PORT)
+
+#define MAX_NATIVE_DEVICES 64
+#define NATIVE_DEVICE_OFFSET 0x1000
+
+#define FLEX_MASK F_EXTEND(0xfffc0000)
+#define IO_IO_LOW offsetof(struct bc_module, io_io_low)
+#define IO_IO_HIGH offsetof(struct bc_module, io_io_high)
+#define READ_IO_IO_LOW(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_LOW)
+#define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_HIGH)
+
+static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
+ struct device *parent);
+
+void walk_lower_bus(struct parisc_device *dev)
+{
+ unsigned long io_io_low, io_io_high;
+
+ if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev))
+ return;
+
+ if(dev->id.hw_type == HPHW_IOA) {
+ io_io_low = (unsigned long)(signed int)(READ_IO_IO_LOW(dev) << 16);
+ io_io_high = io_io_low + MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET;
+ } else {
+ io_io_low = (READ_IO_IO_LOW(dev) + ~FLEX_MASK) & FLEX_MASK;
+ io_io_high = (READ_IO_IO_HIGH(dev)+ ~FLEX_MASK) & FLEX_MASK;
+ }
+
+ walk_native_bus(io_io_low, io_io_high, &dev->dev);
+}
+
+/**
+ * walk_native_bus -- Probe a bus for devices
+ * @io_io_low: Base address of this bus.
+ * @io_io_high: Last address of this bus.
+ * @parent: The parent bus device.
+ *
+ * A native bus (eg Runway or GSC) may have up to 64 devices on it,
+ * spaced at intervals of 0x1000 bytes. PDC may not inform us of these
+ * devices, so we have to probe for them. Unfortunately, we may find
+ * devices which are not physically connected (such as extra serial &
+ * keyboard ports). This problem is not yet solved.
+ */
+static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
+ struct device *parent)
+{
+ int i, devices_found = 0;
+ unsigned long hpa = io_io_low;
+ struct hardware_path path;
+
+ get_node_path(parent, &path);
+ do {
+ for(i = 0; i < MAX_NATIVE_DEVICES; i++, hpa += NATIVE_DEVICE_OFFSET) {
+ struct parisc_device *dev;
+
+ /* Was the device already added by Firmware? */
+ dev = find_device_by_addr(hpa);
+ if (!dev) {
+ path.mod = i;
+ dev = alloc_pa_dev(hpa, &path);
+ if (!dev)
+ continue;
+
+ register_parisc_device(dev);
+ devices_found++;
+ }
+ walk_lower_bus(dev);
+ }
+ } while(!devices_found && hpa < io_io_high);
+}
+
+#define CENTRAL_BUS_ADDR F_EXTEND(0xfff80000)
+
+/**
+ * walk_central_bus - Find devices attached to the central bus
+ *
+ * PDC doesn't tell us about all devices in the system. This routine
+ * finds devices connected to the central bus.
+ */
+void walk_central_bus(void)
+{
+ walk_native_bus(CENTRAL_BUS_ADDR,
+ CENTRAL_BUS_ADDR + (MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET),
+ &root);
+}
+
+static void print_parisc_device(struct parisc_device *dev)
+{
+ char hw_path[64];
+ static int count;
+
+ print_pa_hwpath(dev, hw_path);
+ printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
+ ++count, dev->name, dev->hpa, hw_path, dev->id.hw_type,
+ dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
+
+ if (dev->num_addrs) {
+ int k;
+ printk(", additional addresses: ");
+ for (k = 0; k < dev->num_addrs; k++)
+ printk("0x%lx ", dev->addr[k]);
+ }
+ printk("\n");
+}
+
+/**
+ * init_parisc_bus - Some preparation to be done before inventory
+ */
+void init_parisc_bus(void)
+{
+ bus_register(&parisc_bus_type);
+ device_register(&root);
+ get_device(&root);
+}
+
+/**
+ * print_parisc_devices - Print out a list of devices found in this system
+ */
+void print_parisc_devices(void)
+{
+ struct parisc_device *dev;
+ for_each_padev(dev) {
+ print_parisc_device(dev);
+ }
+}
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
new file mode 100644
index 000000000000..ee58d37dbb27
--- /dev/null
+++ b/arch/parisc/kernel/entry.S
@@ -0,0 +1,2426 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * kernel entry points (interruptions, system call wrappers)
+ * Copyright (C) 1999,2000 Philipp Rumpf
+ * Copyright (C) 1999 SuSE GmbH Nuernberg
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <asm/offsets.h>
+
+/* we have the following possibilities to act on an interruption:
+ * - handle in assembly and use shadowed registers only
+ * - save registers to kernel stack and handle in assembly or C */
+
+
+#include <asm/assembly.h> /* for LDREG/STREG defines */
+#include <asm/pgtable.h>
+#include <asm/psw.h>
+#include <asm/signal.h>
+#include <asm/unistd.h>
+#include <asm/thread_info.h>
+
+#ifdef __LP64__
+#define CMPIB cmpib,*
+#define CMPB cmpb,*
+#define COND(x) *x
+
+ .level 2.0w
+#else
+#define CMPIB cmpib,
+#define CMPB cmpb,
+#define COND(x) x
+
+ .level 2.0
+#endif
+
+ .import pa_dbit_lock,data
+
+ /* space_to_prot macro creates a prot id from a space id */
+
+#if (SPACEID_SHIFT) == 0
+ .macro space_to_prot spc prot
+ depd,z \spc,62,31,\prot
+ .endm
+#else
+ .macro space_to_prot spc prot
+ extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot
+ .endm
+#endif
+
+ /* Switch to virtual mapping, trashing only %r1 */
+ .macro virt_map
+ rsm PSW_SM_Q,%r0
+ tovirt_r1 %r29
+ mfsp %sr7, %r1
+ or,= %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */
+ mtsp %r1, %sr3
+ mtsp %r0, %sr4
+ mtsp %r0, %sr5
+ mtsp %r0, %sr6
+ mtsp %r0, %sr7
+ load32 KERNEL_PSW, %r1
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ load32 4f, %r1
+ mtctl %r1, %cr18 /* Set IIAOQ tail */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* Set IIAOQ head */
+ rfir
+ nop
+4:
+ .endm
+
+ /*
+ * The "get_stack" macros are responsible for determining the
+ * kernel stack value.
+ *
+ * For Faults:
+ * If sr7 == 0
+ * Already using a kernel stack, so call the
+ * get_stack_use_r30 macro to push a pt_regs structure
+ * on the stack, and store registers there.
+ * else
+ * Need to set up a kernel stack, so call the
+ * get_stack_use_cr30 macro to set up a pointer
+ * to the pt_regs structure contained within the
+ * task pointer pointed to by cr30. Set the stack
+ * pointer to point to the end of the task structure.
+ *
+ * For Interrupts:
+ * If sr7 == 0
+ * Already using a kernel stack, check to see if r30
+ * is already pointing to the per processor interrupt
+ * stack. If it is, call the get_stack_use_r30 macro
+ * to push a pt_regs structure on the stack, and store
+ * registers there. Otherwise, call get_stack_use_cr31
+ * to get a pointer to the base of the interrupt stack
+ * and push a pt_regs structure on that stack.
+ * else
+ * Need to set up a kernel stack, so call the
+ * get_stack_use_cr30 macro to set up a pointer
+ * to the pt_regs structure contained within the
+ * task pointer pointed to by cr30. Set the stack
+ * pointer to point to the end of the task structure.
+ * N.B: We don't use the interrupt stack for the
+ * first interrupt from userland, because signals/
+ * resched's are processed when returning to userland,
+ * and we can sleep in those cases.
+ *
+ * Note that we use shadowed registers for temps until
+ * we can save %r26 and %r29. %r26 is used to preserve
+ * %r8 (a shadowed register) which temporarily contained
+ * either the fault type ("code") or the eirr. We need
+ * to use a non-shadowed register to carry the value over
+ * the rfir in virt_map. We use %r26 since this value winds
+ * up being passed as the argument to either do_cpu_irq_mask
+ * or handle_interruption. %r29 is used to hold a pointer
+ * the register save area, and once again, it needs to
+ * be a non-shadowed register so that it survives the rfir.
+ *
+ * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame.
+ */
+
+ .macro get_stack_use_cr30
+
+ /* we save the registers in the task struct */
+
+ mfctl %cr30, %r1
+ tophys %r1,%r9
+ LDREG TI_TASK(%r9), %r1 /* thread_info -> task_struct */
+ tophys %r1,%r9
+ ldo TASK_REGS(%r9),%r9
+ STREG %r30, PT_GR30(%r9)
+ STREG %r29,PT_GR29(%r9)
+ STREG %r26,PT_GR26(%r9)
+ copy %r9,%r29
+ mfctl %cr30, %r1
+ ldo THREAD_SZ_ALGN(%r1), %r30
+ .endm
+
+ .macro get_stack_use_r30
+
+ /* we put a struct pt_regs on the stack and save the registers there */
+
+ tophys %r30,%r9
+ STREG %r30,PT_GR30(%r9)
+ ldo PT_SZ_ALGN(%r30),%r30
+ STREG %r29,PT_GR29(%r9)
+ STREG %r26,PT_GR26(%r9)
+ copy %r9,%r29
+ .endm
+
+ .macro rest_stack
+ LDREG PT_GR1(%r29), %r1
+ LDREG PT_GR30(%r29),%r30
+ LDREG PT_GR29(%r29),%r29
+ .endm
+
+ /* default interruption handler
+ * (calls traps.c:handle_interruption) */
+ .macro def code
+ b intr_save
+ ldi \code, %r8
+ .align 32
+ .endm
+
+ /* Interrupt interruption handler
+ * (calls irq.c:do_cpu_irq_mask) */
+ .macro extint code
+ b intr_extint
+ mfsp %sr7,%r16
+ .align 32
+ .endm
+
+ .import os_hpmc, code
+
+ /* HPMC handler */
+ .macro hpmc code
+ nop /* must be a NOP, will be patched later */
+ load32 PA(os_hpmc), %r3
+ bv,n 0(%r3)
+ nop
+ .word 0 /* checksum (will be patched) */
+ .word PA(os_hpmc) /* address of handler */
+ .word 0 /* length of handler */
+ .endm
+
+ /*
+ * Performance Note: Instructions will be moved up into
+ * this part of the code later on, once we are sure
+ * that the tlb miss handlers are close to final form.
+ */
+
+ /* Register definitions for tlb miss handler macros */
+
+ va = r8 /* virtual address for which the trap occured */
+ spc = r24 /* space for which the trap occured */
+
+#ifndef __LP64__
+
+ /*
+ * itlb miss interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro itlb_11 code
+
+ mfctl %pcsq, spc
+ b itlb_miss_11
+ mfctl %pcoq, va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * itlb miss interruption handler (parisc 2.0)
+ */
+
+ .macro itlb_20 code
+ mfctl %pcsq, spc
+#ifdef __LP64__
+ b itlb_miss_20w
+#else
+ b itlb_miss_20
+#endif
+ mfctl %pcoq, va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * naitlb miss interruption handler (parisc 1.1 - 32 bit)
+ *
+ * Note: naitlb misses will be treated
+ * as an ordinary itlb miss for now.
+ * However, note that naitlb misses
+ * have the faulting address in the
+ * IOR/ISR.
+ */
+
+ .macro naitlb_11 code
+
+ mfctl %isr,spc
+ b itlb_miss_11
+ mfctl %ior,va
+ /* FIXME: If user causes a naitlb miss, the priv level may not be in
+ * lower bits of va, where the itlb miss handler is expecting them
+ */
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * naitlb miss interruption handler (parisc 2.0)
+ *
+ * Note: naitlb misses will be treated
+ * as an ordinary itlb miss for now.
+ * However, note that naitlb misses
+ * have the faulting address in the
+ * IOR/ISR.
+ */
+
+ .macro naitlb_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b itlb_miss_20w
+#else
+ b itlb_miss_20
+#endif
+ mfctl %ior,va
+ /* FIXME: If user causes a naitlb miss, the priv level may not be in
+ * lower bits of va, where the itlb miss handler is expecting them
+ */
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * dtlb miss interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro dtlb_11 code
+
+ mfctl %isr, spc
+ b dtlb_miss_11
+ mfctl %ior, va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * dtlb miss interruption handler (parisc 2.0)
+ */
+
+ .macro dtlb_20 code
+
+ mfctl %isr, spc
+#ifdef __LP64__
+ b dtlb_miss_20w
+#else
+ b dtlb_miss_20
+#endif
+ mfctl %ior, va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */
+
+ .macro nadtlb_11 code
+
+ mfctl %isr,spc
+ b nadtlb_miss_11
+ mfctl %ior,va
+
+ .align 32
+ .endm
+#endif
+
+ /* nadtlb miss interruption handler (parisc 2.0) */
+
+ .macro nadtlb_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b nadtlb_miss_20w
+#else
+ b nadtlb_miss_20
+#endif
+ mfctl %ior,va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * dirty bit trap interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro dbit_11 code
+
+ mfctl %isr,spc
+ b dbit_trap_11
+ mfctl %ior,va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * dirty bit trap interruption handler (parisc 2.0)
+ */
+
+ .macro dbit_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b dbit_trap_20w
+#else
+ b dbit_trap_20
+#endif
+ mfctl %ior,va
+
+ .align 32
+ .endm
+
+ /* The following are simple 32 vs 64 bit instruction
+ * abstractions for the macros */
+ .macro EXTR reg1,start,length,reg2
+#ifdef __LP64__
+ extrd,u \reg1,32+\start,\length,\reg2
+#else
+ extrw,u \reg1,\start,\length,\reg2
+#endif
+ .endm
+
+ .macro DEP reg1,start,length,reg2
+#ifdef __LP64__
+ depd \reg1,32+\start,\length,\reg2
+#else
+ depw \reg1,\start,\length,\reg2
+#endif
+ .endm
+
+ .macro DEPI val,start,length,reg
+#ifdef __LP64__
+ depdi \val,32+\start,\length,\reg
+#else
+ depwi \val,\start,\length,\reg
+#endif
+ .endm
+
+ /* In LP64, the space contains part of the upper 32 bits of the
+ * fault. We have to extract this and place it in the va,
+ * zeroing the corresponding bits in the space register */
+ .macro space_adjust spc,va,tmp
+#ifdef __LP64__
+ extrd,u \spc,63,SPACEID_SHIFT,\tmp
+ depd %r0,63,SPACEID_SHIFT,\spc
+ depd \tmp,31,SPACEID_SHIFT,\va
+#endif
+ .endm
+
+ .import swapper_pg_dir,code
+
+ /* Get the pgd. For faults on space zero (kernel space), this
+ * is simply swapper_pg_dir. For user space faults, the
+ * pgd is stored in %cr25 */
+ .macro get_pgd spc,reg
+ ldil L%PA(swapper_pg_dir),\reg
+ ldo R%PA(swapper_pg_dir)(\reg),\reg
+ or,COND(=) %r0,\spc,%r0
+ mfctl %cr25,\reg
+ .endm
+
+ /*
+ space_check(spc,tmp,fault)
+
+ spc - The space we saw the fault with.
+ tmp - The place to store the current space.
+ fault - Function to call on failure.
+
+ Only allow faults on different spaces from the
+ currently active one if we're the kernel
+
+ */
+ .macro space_check spc,tmp,fault
+ mfsp %sr7,\tmp
+ or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page
+ * as kernel, so defeat the space
+ * check if it is */
+ copy \spc,\tmp
+ or,COND(=) %r0,\tmp,%r0 /* nullify if executing as kernel */
+ cmpb,COND(<>),n \tmp,\spc,\fault
+ .endm
+
+ /* Look up a PTE in a 2-Level scheme (faulting at each
+ * level if the entry isn't present
+ *
+ * NOTE: we use ldw even for LP64, since the short pointers
+ * can address up to 1TB
+ */
+ .macro L2_ptep pmd,pte,index,va,fault
+#if PT_NLEVELS == 3
+ EXTR \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
+#else
+ EXTR \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
+#endif
+ DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */
+ copy %r0,\pte
+ ldw,s \index(\pmd),\pmd
+ bb,>=,n \pmd,_PxD_PRESENT_BIT,\fault
+ DEP %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
+ copy \pmd,%r9
+#ifdef __LP64__
+ shld %r9,PxD_VALUE_SHIFT,\pmd
+#else
+ shlw %r9,PxD_VALUE_SHIFT,\pmd
+#endif
+ EXTR \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
+ DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */
+ shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd
+ LDREG %r0(\pmd),\pte /* pmd is now pte */
+ bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault
+ .endm
+
+ /* Look up PTE in a 3-Level scheme.
+ *
+ * Here we implement a Hybrid L2/L3 scheme: we allocate the
+ * first pmd adjacent to the pgd. This means that we can
+ * subtract a constant offset to get to it. The pmd and pgd
+ * sizes are arranged so that a single pmd covers 4GB (giving
+ * a full LP64 process access to 8TB) so our lookups are
+ * effectively L2 for the first 4GB of the kernel (i.e. for
+ * all ILP32 processes and all the kernel for machines with
+ * under 4GB of memory) */
+ .macro L3_ptep pgd,pte,index,va,fault
+ extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
+ copy %r0,\pte
+ extrd,u,*= \va,31,32,%r0
+ ldw,s \index(\pgd),\pgd
+ extrd,u,*= \va,31,32,%r0
+ bb,>=,n \pgd,_PxD_PRESENT_BIT,\fault
+ extrd,u,*= \va,31,32,%r0
+ shld \pgd,PxD_VALUE_SHIFT,\index
+ extrd,u,*= \va,31,32,%r0
+ copy \index,\pgd
+ extrd,u,*<> \va,31,32,%r0
+ ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd
+ L2_ptep \pgd,\pte,\index,\va,\fault
+ .endm
+
+ /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and
+ * don't needlessly dirty the cache line if it was already set */
+ .macro update_ptep ptep,pte,tmp,tmp1
+ ldi _PAGE_ACCESSED,\tmp1
+ or \tmp1,\pte,\tmp
+ and,COND(<>) \tmp1,\pte,%r0
+ STREG \tmp,0(\ptep)
+ .endm
+
+ /* Set the dirty bit (and accessed bit). No need to be
+ * clever, this is only used from the dirty fault */
+ .macro update_dirty ptep,pte,tmp
+ ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp
+ or \tmp,\pte,\pte
+ STREG \pte,0(\ptep)
+ .endm
+
+ /* Convert the pte and prot to tlb insertion values. How
+ * this happens is quite subtle, read below */
+ .macro make_insert_tlb spc,pte,prot
+ space_to_prot \spc \prot /* create prot id from space */
+ /* The following is the real subtlety. This is depositing
+ * T <-> _PAGE_REFTRAP
+ * D <-> _PAGE_DIRTY
+ * B <-> _PAGE_DMB (memory break)
+ *
+ * Then incredible subtlety: The access rights are
+ * _PAGE_GATEWAY _PAGE_EXEC _PAGE_READ
+ * See 3-14 of the parisc 2.0 manual
+ *
+ * Finally, _PAGE_READ goes in the top bit of PL1 (so we
+ * trigger an access rights trap in user space if the user
+ * tries to read an unreadable page */
+ depd \pte,8,7,\prot
+
+ /* PAGE_USER indicates the page can be read with user privileges,
+ * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1
+ * contains _PAGE_READ */
+ extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0
+ depdi 7,11,3,\prot
+ /* If we're a gateway page, drop PL2 back to zero for promotion
+ * to kernel privilege (so we can execute the page as kernel).
+ * Any privilege promotion page always denys read and write */
+ extrd,u,*= \pte,_PAGE_GATEWAY_BIT+32,1,%r0
+ depd %r0,11,2,\prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for iitlbt */
+
+ depd %r0,63,PAGE_SHIFT,\pte
+ extrd,u \pte,56,32,\pte
+ .endm
+
+ /* Identical macro to make_insert_tlb above, except it
+ * makes the tlb entry for the differently formatted pa11
+ * insertion instructions */
+ .macro make_insert_tlb_11 spc,pte,prot
+ zdep \spc,30,15,\prot
+ dep \pte,8,7,\prot
+ extru,= \pte,_PAGE_NO_CACHE_BIT,1,%r0
+ depi 1,12,1,\prot
+ extru,= \pte,_PAGE_USER_BIT,1,%r0
+ depi 7,11,3,\prot /* Set for user space (1 rsvd for read) */
+ extru,= \pte,_PAGE_GATEWAY_BIT,1,%r0
+ depi 0,11,2,\prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for iitlba */
+
+ depi 0,31,12,\pte
+ extru \pte,24,25,\pte
+
+ .endm
+
+ /* This is for ILP32 PA2.0 only. The TLB insertion needs
+ * to extend into I/O space if the address is 0xfXXXXXXX
+ * so we extend the f's into the top word of the pte in
+ * this case */
+ .macro f_extend pte,tmp
+ extrd,s \pte,42,4,\tmp
+ addi,<> 1,\tmp,%r0
+ extrd,s \pte,63,25,\pte
+ .endm
+
+ /* The alias region is an 8MB aligned 16MB to do clear and
+ * copy user pages at addresses congruent with the user
+ * virtual address.
+ *
+ * To use the alias page, you set %r26 up with the to TLB
+ * entry (identifying the physical page) and %r23 up with
+ * the from tlb entry (or nothing if only a to entry---for
+ * clear_user_page_asm) */
+ .macro do_alias spc,tmp,tmp1,va,pte,prot,fault
+ cmpib,COND(<>),n 0,\spc,\fault
+ ldil L%(TMPALIAS_MAP_START),\tmp
+#if defined(__LP64__) && (TMPALIAS_MAP_START >= 0x80000000)
+ /* on LP64, ldi will sign extend into the upper 32 bits,
+ * which is behaviour we don't want */
+ depdi 0,31,32,\tmp
+#endif
+ copy \va,\tmp1
+ DEPI 0,31,23,\tmp1
+ cmpb,COND(<>),n \tmp,\tmp1,\fault
+ ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
+ depd,z \prot,8,7,\prot
+ /*
+ * OK, it is in the temp alias region, check whether "from" or "to".
+ * Check "subtle" note in pacache.S re: r23/r26.
+ */
+#ifdef __LP64__
+ extrd,u,*= \va,41,1,%r0
+#else
+ extrw,u,= \va,9,1,%r0
+#endif
+ or,COND(tr) %r23,%r0,\pte
+ or %r26,%r0,\pte
+ .endm
+
+
+ /*
+ * Align fault_vector_20 on 4K boundary so that both
+ * fault_vector_11 and fault_vector_20 are on the
+ * same page. This is only necessary as long as we
+ * write protect the kernel text, which we may stop
+ * doing once we use large page translations to cover
+ * the static part of the kernel address space.
+ */
+
+ .export fault_vector_20
+
+ .text
+
+ .align 4096
+
+fault_vector_20:
+ /* First vector is invalid (0) */
+ .ascii "cows can fly"
+ .byte 0
+ .align 32
+
+ hpmc 1
+ def 2
+ def 3
+ extint 4
+ def 5
+ itlb_20 6
+ def 7
+ def 8
+ def 9
+ def 10
+ def 11
+ def 12
+ def 13
+ def 14
+ dtlb_20 15
+#if 0
+ naitlb_20 16
+#else
+ def 16
+#endif
+ nadtlb_20 17
+ def 18
+ def 19
+ dbit_20 20
+ def 21
+ def 22
+ def 23
+ def 24
+ def 25
+ def 26
+ def 27
+ def 28
+ def 29
+ def 30
+ def 31
+
+#ifndef __LP64__
+
+ .export fault_vector_11
+
+ .align 2048
+
+fault_vector_11:
+ /* First vector is invalid (0) */
+ .ascii "cows can fly"
+ .byte 0
+ .align 32
+
+ hpmc 1
+ def 2
+ def 3
+ extint 4
+ def 5
+ itlb_11 6
+ def 7
+ def 8
+ def 9
+ def 10
+ def 11
+ def 12
+ def 13
+ def 14
+ dtlb_11 15
+#if 0
+ naitlb_11 16
+#else
+ def 16
+#endif
+ nadtlb_11 17
+ def 18
+ def 19
+ dbit_11 20
+ def 21
+ def 22
+ def 23
+ def 24
+ def 25
+ def 26
+ def 27
+ def 28
+ def 29
+ def 30
+ def 31
+
+#endif
+
+ .import handle_interruption,code
+ .import do_cpu_irq_mask,code
+
+ /*
+ * r26 = function to be called
+ * r25 = argument to pass in
+ * r24 = flags for do_fork()
+ *
+ * Kernel threads don't ever return, so they don't need
+ * a true register context. We just save away the arguments
+ * for copy_thread/ret_ to properly set up the child.
+ */
+
+#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
+#define CLONE_UNTRACED 0x00800000
+
+ .export __kernel_thread, code
+ .import do_fork
+__kernel_thread:
+ STREG %r2, -RP_OFFSET(%r30)
+
+ copy %r30, %r1
+ ldo PT_SZ_ALGN(%r30),%r30
+#ifdef __LP64__
+ /* Yo, function pointers in wide mode are little structs... -PB */
+ ldd 24(%r26), %r2
+ STREG %r2, PT_GR27(%r1) /* Store childs %dp */
+ ldd 16(%r26), %r26
+
+ STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */
+ copy %r0, %r22 /* user_tid */
+#endif
+ STREG %r26, PT_GR26(%r1) /* Store function & argument for child */
+ STREG %r25, PT_GR25(%r1)
+ ldil L%CLONE_UNTRACED, %r26
+ ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */
+ or %r26, %r24, %r26 /* will have kernel mappings. */
+ ldi 1, %r25 /* stack_start, signals kernel thread */
+ stw %r0, -52(%r30) /* user_tid */
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+ BL do_fork, %r2
+ copy %r1, %r24 /* pt_regs */
+
+ /* Parent Returns here */
+
+ LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2
+ ldo -PT_SZ_ALGN(%r30), %r30
+ bv %r0(%r2)
+ nop
+
+ /*
+ * Child Returns here
+ *
+ * copy_thread moved args from temp save area set up above
+ * into task save area.
+ */
+
+ .export ret_from_kernel_thread
+ret_from_kernel_thread:
+
+ /* Call schedule_tail first though */
+ BL schedule_tail, %r2
+ nop
+
+ LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1
+ LDREG TASK_PT_GR25(%r1), %r26
+#ifdef __LP64__
+ LDREG TASK_PT_GR27(%r1), %r27
+ LDREG TASK_PT_GR22(%r1), %r22
+#endif
+ LDREG TASK_PT_GR26(%r1), %r1
+ ble 0(%sr7, %r1)
+ copy %r31, %r2
+
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+ loadgp /* Thread could have been in a module */
+#endif
+ b sys_exit
+ ldi 0, %r26
+
+ .import sys_execve, code
+ .export __execve, code
+__execve:
+ copy %r2, %r15
+ copy %r30, %r16
+ ldo PT_SZ_ALGN(%r30), %r30
+ STREG %r26, PT_GR26(%r16)
+ STREG %r25, PT_GR25(%r16)
+ STREG %r24, PT_GR24(%r16)
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+ BL sys_execve, %r2
+ copy %r16, %r26
+
+ cmpib,=,n 0,%r28,intr_return /* forward */
+
+ /* yes, this will trap and die. */
+ copy %r15, %r2
+ copy %r16, %r30
+ bv %r0(%r2)
+ nop
+
+ .align 4
+
+ /*
+ * struct task_struct *_switch_to(struct task_struct *prev,
+ * struct task_struct *next)
+ *
+ * switch kernel stacks and return prev */
+ .export _switch_to, code
+_switch_to:
+ STREG %r2, -RP_OFFSET(%r30)
+
+ callee_save
+
+ load32 _switch_to_ret, %r2
+
+ STREG %r2, TASK_PT_KPC(%r26)
+ LDREG TASK_PT_KPC(%r25), %r2
+
+ STREG %r30, TASK_PT_KSP(%r26)
+ LDREG TASK_PT_KSP(%r25), %r30
+ LDREG TASK_THREAD_INFO(%r25), %r25
+ bv %r0(%r2)
+ mtctl %r25,%cr30
+
+_switch_to_ret:
+ mtctl %r0, %cr0 /* Needed for single stepping */
+ callee_rest
+
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ copy %r26, %r28
+
+ /*
+ * Common rfi return path for interruptions, kernel execve, and
+ * sys_rt_sigreturn (sometimes). The sys_rt_sigreturn syscall will
+ * return via this path if the signal was received when the process
+ * was running; if the process was blocked on a syscall then the
+ * normal syscall_exit path is used. All syscalls for traced
+ * proceses exit via intr_restore.
+ *
+ * XXX If any syscalls that change a processes space id ever exit
+ * this way, then we will need to copy %sr3 in to PT_SR[3..7], and
+ * adjust IASQ[0..1].
+ *
+ * Note that the following code uses a "relied upon translation".
+ * See the parisc ACD for details. The ssm is necessary due to a
+ * PCXT bug.
+ */
+
+ .align 4096
+
+ .export syscall_exit_rfi
+syscall_exit_rfi:
+ mfctl %cr30,%r16
+ LDREG TI_TASK(%r16), %r16 /* thread_info -> task_struct */
+ ldo TASK_REGS(%r16),%r16
+ /* Force iaoq to userspace, as the user has had access to our current
+ * context via sigcontext. Also Filter the PSW for the same reason.
+ */
+ LDREG PT_IAOQ0(%r16),%r19
+ depi 3,31,2,%r19
+ STREG %r19,PT_IAOQ0(%r16)
+ LDREG PT_IAOQ1(%r16),%r19
+ depi 3,31,2,%r19
+ STREG %r19,PT_IAOQ1(%r16)
+ LDREG PT_PSW(%r16),%r19
+ load32 USER_PSW_MASK,%r1
+#ifdef __LP64__
+ load32 USER_PSW_HI_MASK,%r20
+ depd %r20,31,32,%r1
+#endif
+ and %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
+ load32 USER_PSW,%r1
+ or %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
+ STREG %r19,PT_PSW(%r16)
+
+ /*
+ * If we aren't being traced, we never saved space registers
+ * (we don't store them in the sigcontext), so set them
+ * to "proper" values now (otherwise we'll wind up restoring
+ * whatever was last stored in the task structure, which might
+ * be inconsistent if an interrupt occured while on the gateway
+ * page) Note that we may be "trashing" values the user put in
+ * them, but we don't support the the user changing them.
+ */
+
+ STREG %r0,PT_SR2(%r16)
+ mfsp %sr3,%r19
+ STREG %r19,PT_SR0(%r16)
+ STREG %r19,PT_SR1(%r16)
+ STREG %r19,PT_SR3(%r16)
+ STREG %r19,PT_SR4(%r16)
+ STREG %r19,PT_SR5(%r16)
+ STREG %r19,PT_SR6(%r16)
+ STREG %r19,PT_SR7(%r16)
+
+intr_return:
+ /* NOTE: Need to enable interrupts incase we schedule. */
+ ssm PSW_SM_I, %r0
+
+ /* Check for software interrupts */
+
+ .import irq_stat,data
+
+ load32 irq_stat,%r19
+#ifdef CONFIG_SMP
+ mfctl %cr30,%r1
+ ldw TI_CPU(%r1),%r1 /* get cpu # - int */
+ /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
+ ** irq_stat[] is defined using ____cacheline_aligned.
+ */
+#ifdef __LP64__
+ shld %r1, 6, %r20
+#else
+ shlw %r1, 5, %r20
+#endif
+ add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */
+#endif /* CONFIG_SMP */
+
+ LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */
+ cmpib,<>,n 0,%r20,intr_do_softirq /* forward */
+
+intr_check_resched:
+
+ /* check for reschedule */
+ mfctl %cr30,%r1
+ LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
+ bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
+
+intr_check_sig:
+ /* As above */
+ mfctl %cr30,%r1
+ LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_SIGPENDING */
+ bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
+
+intr_restore:
+ copy %r16,%r29
+ ldo PT_FR31(%r29),%r1
+ rest_fp %r1
+ rest_general %r29
+
+ /* Create a "relied upon translation" PA 2.0 Arch. F-5 */
+ ssm 0,%r0
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ tophys_r1 %r29
+ rsm (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
+
+ /* Restore space id's and special cr's from PT_REGS
+ * structure pointed to by r29 */
+ rest_specials %r29
+
+ /* Important: Note that rest_stack restores r29
+ * last (we are using it)! It also restores r1 and r30. */
+ rest_stack
+
+ rfi
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ .import do_softirq,code
+intr_do_softirq:
+ bl do_softirq,%r2
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#else
+ nop
+#endif
+ b intr_check_resched
+ nop
+
+ .import schedule,code
+intr_do_resched:
+ /* Only do reschedule if we are returning to user space */
+ LDREG PT_IASQ0(%r16), %r20
+ CMPIB= 0,%r20,intr_restore /* backward */
+ nop
+ LDREG PT_IASQ1(%r16), %r20
+ CMPIB= 0,%r20,intr_restore /* backward */
+ nop
+
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+
+ ldil L%intr_check_sig, %r2
+ b schedule
+ ldo R%intr_check_sig(%r2), %r2
+
+
+ .import do_signal,code
+intr_do_signal:
+ /*
+ This check is critical to having LWS
+ working. The IASQ is zero on the gateway
+ page and we cannot deliver any signals until
+ we get off the gateway page.
+
+ Only do signals if we are returning to user space
+ */
+ LDREG PT_IASQ0(%r16), %r20
+ CMPIB= 0,%r20,intr_restore /* backward */
+ nop
+ LDREG PT_IASQ1(%r16), %r20
+ CMPIB= 0,%r20,intr_restore /* backward */
+ nop
+
+ copy %r0, %r24 /* unsigned long in_syscall */
+ copy %r16, %r25 /* struct pt_regs *regs */
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+
+ BL do_signal,%r2
+ copy %r0, %r26 /* sigset_t *oldset = NULL */
+
+ b intr_check_sig
+ nop
+
+ /*
+ * External interrupts.
+ */
+
+intr_extint:
+ CMPIB=,n 0,%r16,1f
+ get_stack_use_cr30
+ b,n 3f
+
+1:
+#if 0 /* Interrupt Stack support not working yet! */
+ mfctl %cr31,%r1
+ copy %r30,%r17
+ /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
+#ifdef __LP64__
+ depdi 0,63,15,%r17
+#else
+ depi 0,31,15,%r17
+#endif
+ CMPB=,n %r1,%r17,2f
+ get_stack_use_cr31
+ b,n 3f
+#endif
+2:
+ get_stack_use_r30
+
+3:
+ save_specials %r29
+ virt_map
+ save_general %r29
+
+ ldo PT_FR0(%r29), %r24
+ save_fp %r24
+
+ loadgp
+
+ copy %r29, %r26 /* arg0 is pt_regs */
+ copy %r29, %r16 /* save pt_regs */
+
+ ldil L%intr_return, %r2
+
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+
+ b do_cpu_irq_mask
+ ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */
+
+
+ /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
+
+ .export intr_save, code /* for os_hpmc */
+
+intr_save:
+ mfsp %sr7,%r16
+ CMPIB=,n 0,%r16,1f
+ get_stack_use_cr30
+ b 2f
+ copy %r8,%r26
+
+1:
+ get_stack_use_r30
+ copy %r8,%r26
+
+2:
+ save_specials %r29
+
+ /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
+
+ /*
+ * FIXME: 1) Use a #define for the hardwired "6" below (and in
+ * traps.c.
+ * 2) Once we start executing code above 4 Gb, we need
+ * to adjust iasq/iaoq here in the same way we
+ * adjust isr/ior below.
+ */
+
+ CMPIB=,n 6,%r26,skip_save_ior
+
+ /* save_specials left ipsw value in r8 for us to test */
+
+ mfctl %cr20, %r16 /* isr */
+ mfctl %cr21, %r17 /* ior */
+
+#ifdef __LP64__
+ /*
+ * If the interrupted code was running with W bit off (32 bit),
+ * clear the b bits (bits 0 & 1) in the ior.
+ */
+ extrd,u,*<> %r8,PSW_W_BIT,1,%r0
+ depdi 0,1,2,%r17
+
+ /*
+ * FIXME: This code has hardwired assumptions about the split
+ * between space bits and offset bits. This will change
+ * when we allow alternate page sizes.
+ */
+
+ /* adjust isr/ior. */
+
+ extrd,u %r16,63,7,%r1 /* get high bits from isr for ior */
+ depd %r1,31,7,%r17 /* deposit them into ior */
+ depdi 0,63,7,%r16 /* clear them from isr */
+#endif
+ STREG %r16, PT_ISR(%r29)
+ STREG %r17, PT_IOR(%r29)
+
+
+skip_save_ior:
+ virt_map
+ save_general %r29
+
+ ldo PT_FR0(%r29), %r25
+ save_fp %r25
+
+ loadgp
+
+ copy %r29, %r25 /* arg1 is pt_regs */
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+
+ ldil L%intr_check_sig, %r2
+ copy %r25, %r16 /* save pt_regs */
+
+ b handle_interruption
+ ldo R%intr_check_sig(%r2), %r2
+
+
+ /*
+ * Note for all tlb miss handlers:
+ *
+ * cr24 contains a pointer to the kernel address space
+ * page directory.
+ *
+ * cr25 contains a pointer to the current user address
+ * space page directory.
+ *
+ * sr3 will contain the space id of the user address space
+ * of the current running thread while that thread is
+ * running in the kernel.
+ */
+
+ /*
+ * register number allocations. Note that these are all
+ * in the shadowed registers
+ */
+
+ t0 = r1 /* temporary register 0 */
+ va = r8 /* virtual address for which the trap occured */
+ t1 = r9 /* temporary register 1 */
+ pte = r16 /* pte/phys page # */
+ prot = r17 /* prot bits */
+ spc = r24 /* space for which the trap occured */
+ ptp = r25 /* page directory/page table pointer */
+
+#ifdef __LP64__
+
+dtlb_miss_20w:
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,dtlb_fault
+
+ L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ idtlbt pte,prot
+
+ rfir
+ nop
+
+dtlb_check_alias_20w:
+ do_alias spc,t0,t1,va,pte,prot,dtlb_fault
+
+ idtlbt pte,prot
+
+ rfir
+ nop
+
+nadtlb_miss_20w:
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,nadtlb_fault
+
+ L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ idtlbt pte,prot
+
+ rfir
+ nop
+
+nadtlb_check_flush_20w:
+ bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
+
+ /* Insert a "flush only" translation */
+
+ depdi,z 7,7,3,prot
+ depdi 1,10,1,prot
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,52,pte
+ idtlbt pte,prot
+
+ rfir
+ nop
+
+#else
+
+dtlb_miss_11:
+ get_pgd spc,ptp
+
+ space_check spc,t0,dtlb_fault
+
+ L2_ptep ptp,pte,t0,va,dtlb_check_alias_11
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb_11 spc,pte,prot
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ idtlba pte,(%sr1,va)
+ idtlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+dtlb_check_alias_11:
+
+ /* Check to see if fault is in the temporary alias region */
+
+ cmpib,<>,n 0,spc,dtlb_fault /* forward */
+ ldil L%(TMPALIAS_MAP_START),t0
+ copy va,t1
+ depwi 0,31,23,t1
+ cmpb,<>,n t0,t1,dtlb_fault /* forward */
+ ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
+ depw,z prot,8,7,prot
+
+ /*
+ * OK, it is in the temp alias region, check whether "from" or "to".
+ * Check "subtle" note in pacache.S re: r23/r26.
+ */
+
+ extrw,u,= va,9,1,r0
+ or,tr %r23,%r0,pte /* If "from" use "from" page */
+ or %r26,%r0,pte /* else "to", use "to" page */
+
+ idtlba pte,(va)
+ idtlbp prot,(va)
+
+ rfir
+ nop
+
+nadtlb_miss_11:
+ get_pgd spc,ptp
+
+ space_check spc,t0,nadtlb_fault
+
+ L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb_11 spc,pte,prot
+
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ idtlba pte,(%sr1,va)
+ idtlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+nadtlb_check_flush_11:
+ bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
+
+ /* Insert a "flush only" translation */
+
+ zdepi 7,7,3,prot
+ depi 1,10,1,prot
+
+ /* Get rid of prot bits and convert to page addr for idtlba */
+
+ depi 0,31,12,pte
+ extru pte,24,25,pte
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ idtlba pte,(%sr1,va)
+ idtlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+dtlb_miss_20:
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,dtlb_fault
+
+ L2_ptep ptp,pte,t0,va,dtlb_check_alias_20
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ f_extend pte,t0
+
+ idtlbt pte,prot
+
+ rfir
+ nop
+
+dtlb_check_alias_20:
+ do_alias spc,t0,t1,va,pte,prot,dtlb_fault
+
+ idtlbt pte,prot
+
+ rfir
+ nop
+
+nadtlb_miss_20:
+ get_pgd spc,ptp
+
+ space_check spc,t0,nadtlb_fault
+
+ L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ f_extend pte,t0
+
+ idtlbt pte,prot
+
+ rfir
+ nop
+
+nadtlb_check_flush_20:
+ bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
+
+ /* Insert a "flush only" translation */
+
+ depdi,z 7,7,3,prot
+ depdi 1,10,1,prot
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,32,pte
+ idtlbt pte,prot
+
+ rfir
+ nop
+#endif
+
+nadtlb_emulate:
+
+ /*
+ * Non access misses can be caused by fdc,fic,pdc,lpa,probe and
+ * probei instructions. We don't want to fault for these
+ * instructions (not only does it not make sense, it can cause
+ * deadlocks, since some flushes are done with the mmap
+ * semaphore held). If the translation doesn't exist, we can't
+ * insert a translation, so have to emulate the side effects
+ * of the instruction. Since we don't insert a translation
+ * we can get a lot of faults during a flush loop, so it makes
+ * sense to try to do it here with minimum overhead. We only
+ * emulate fdc,fic,pdc,probew,prober instructions whose base
+ * and index registers are not shadowed. We defer everything
+ * else to the "slow" path.
+ */
+
+ mfctl %cr19,%r9 /* Get iir */
+
+ /* PA 2.0 Arch Ref. Book pg 382 has a good description of the insn bits.
+ Checks for fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw */
+
+ /* Checks for fdc,fdce,pdc,"fic,4f" only */
+ ldi 0x280,%r16
+ and %r9,%r16,%r17
+ cmpb,<>,n %r16,%r17,nadtlb_probe_check
+ bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */
+ BL get_register,%r25
+ extrw,u %r9,15,5,%r8 /* Get index register # */
+ CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */
+ copy %r1,%r24
+ BL get_register,%r25
+ extrw,u %r9,10,5,%r8 /* Get base register # */
+ CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */
+ BL set_register,%r25
+ add,l %r1,%r24,%r1 /* doesn't affect c/b bits */
+
+nadtlb_nullify:
+ mfctl %cr22,%r8 /* Get ipsw */
+ ldil L%PSW_N,%r9
+ or %r8,%r9,%r8 /* Set PSW_N */
+ mtctl %r8,%cr22
+
+ rfir
+ nop
+
+ /*
+ When there is no translation for the probe address then we
+ must nullify the insn and return zero in the target regsiter.
+ This will indicate to the calling code that it does not have
+ write/read privileges to this address.
+
+ This should technically work for prober and probew in PA 1.1,
+ and also probe,r and probe,w in PA 2.0
+
+ WARNING: USE ONLY NON-SHADOW REGISTERS WITH PROBE INSN!
+ THE SLOW-PATH EMULATION HAS NOT BEEN WRITTEN YET.
+
+ */
+nadtlb_probe_check:
+ ldi 0x80,%r16
+ and %r9,%r16,%r17
+ cmpb,<>,n %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/
+ BL get_register,%r25 /* Find the target register */
+ extrw,u %r9,31,5,%r8 /* Get target register */
+ CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */
+ BL set_register,%r25
+ copy %r0,%r1 /* Write zero to target register */
+ b nadtlb_nullify /* Nullify return insn */
+ nop
+
+
+#ifdef __LP64__
+itlb_miss_20w:
+
+ /*
+ * I miss is a little different, since we allow users to fault
+ * on the gateway page which is in the kernel address space.
+ */
+
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,itlb_fault
+
+ L3_ptep ptp,pte,t0,va,itlb_fault
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ iitlbt pte,prot
+
+ rfir
+ nop
+
+#else
+
+itlb_miss_11:
+ get_pgd spc,ptp
+
+ space_check spc,t0,itlb_fault
+
+ L2_ptep ptp,pte,t0,va,itlb_fault
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb_11 spc,pte,prot
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ iitlba pte,(%sr1,va)
+ iitlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+itlb_miss_20:
+ get_pgd spc,ptp
+
+ space_check spc,t0,itlb_fault
+
+ L2_ptep ptp,pte,t0,va,itlb_fault
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ f_extend pte,t0
+
+ iitlbt pte,prot
+
+ rfir
+ nop
+
+#endif
+
+#ifdef __LP64__
+
+dbit_trap_20w:
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,dbit_fault
+
+ L3_ptep ptp,pte,t0,va,dbit_fault
+
+#ifdef CONFIG_SMP
+ CMPIB=,n 0,spc,dbit_nolock_20w
+ load32 PA(pa_dbit_lock),t0
+
+dbit_spin_20w:
+ ldcw 0(t0),t1
+ cmpib,= 0,t1,dbit_spin_20w
+ nop
+
+dbit_nolock_20w:
+#endif
+ update_dirty ptp,pte,t1
+
+ make_insert_tlb spc,pte,prot
+
+ idtlbt pte,prot
+#ifdef CONFIG_SMP
+ CMPIB=,n 0,spc,dbit_nounlock_20w
+ ldi 1,t1
+ stw t1,0(t0)
+
+dbit_nounlock_20w:
+#endif
+
+ rfir
+ nop
+#else
+
+dbit_trap_11:
+
+ get_pgd spc,ptp
+
+ space_check spc,t0,dbit_fault
+
+ L2_ptep ptp,pte,t0,va,dbit_fault
+
+#ifdef CONFIG_SMP
+ CMPIB=,n 0,spc,dbit_nolock_11
+ load32 PA(pa_dbit_lock),t0
+
+dbit_spin_11:
+ ldcw 0(t0),t1
+ cmpib,= 0,t1,dbit_spin_11
+ nop
+
+dbit_nolock_11:
+#endif
+ update_dirty ptp,pte,t1
+
+ make_insert_tlb_11 spc,pte,prot
+
+ mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ idtlba pte,(%sr1,va)
+ idtlbp prot,(%sr1,va)
+
+ mtsp t1, %sr1 /* Restore sr1 */
+#ifdef CONFIG_SMP
+ CMPIB=,n 0,spc,dbit_nounlock_11
+ ldi 1,t1
+ stw t1,0(t0)
+
+dbit_nounlock_11:
+#endif
+
+ rfir
+ nop
+
+dbit_trap_20:
+ get_pgd spc,ptp
+
+ space_check spc,t0,dbit_fault
+
+ L2_ptep ptp,pte,t0,va,dbit_fault
+
+#ifdef CONFIG_SMP
+ CMPIB=,n 0,spc,dbit_nolock_20
+ load32 PA(pa_dbit_lock),t0
+
+dbit_spin_20:
+ ldcw 0(t0),t1
+ cmpib,= 0,t1,dbit_spin_20
+ nop
+
+dbit_nolock_20:
+#endif
+ update_dirty ptp,pte,t1
+
+ make_insert_tlb spc,pte,prot
+
+ f_extend pte,t1
+
+ idtlbt pte,prot
+
+#ifdef CONFIG_SMP
+ CMPIB=,n 0,spc,dbit_nounlock_20
+ ldi 1,t1
+ stw t1,0(t0)
+
+dbit_nounlock_20:
+#endif
+
+ rfir
+ nop
+#endif
+
+ .import handle_interruption,code
+
+kernel_bad_space:
+ b intr_save
+ ldi 31,%r8 /* Use an unused code */
+
+dbit_fault:
+ b intr_save
+ ldi 20,%r8
+
+itlb_fault:
+ b intr_save
+ ldi 6,%r8
+
+nadtlb_fault:
+ b intr_save
+ ldi 17,%r8
+
+dtlb_fault:
+ b intr_save
+ ldi 15,%r8
+
+ /* Register saving semantics for system calls:
+
+ %r1 clobbered by system call macro in userspace
+ %r2 saved in PT_REGS by gateway page
+ %r3 - %r18 preserved by C code (saved by signal code)
+ %r19 - %r20 saved in PT_REGS by gateway page
+ %r21 - %r22 non-standard syscall args
+ stored in kernel stack by gateway page
+ %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page
+ %r27 - %r30 saved in PT_REGS by gateway page
+ %r31 syscall return pointer
+ */
+
+ /* Floating point registers (FIXME: what do we do with these?)
+
+ %fr0 - %fr3 status/exception, not preserved
+ %fr4 - %fr7 arguments
+ %fr8 - %fr11 not preserved by C code
+ %fr12 - %fr21 preserved by C code
+ %fr22 - %fr31 not preserved by C code
+ */
+
+ .macro reg_save regs
+ STREG %r3, PT_GR3(\regs)
+ STREG %r4, PT_GR4(\regs)
+ STREG %r5, PT_GR5(\regs)
+ STREG %r6, PT_GR6(\regs)
+ STREG %r7, PT_GR7(\regs)
+ STREG %r8, PT_GR8(\regs)
+ STREG %r9, PT_GR9(\regs)
+ STREG %r10,PT_GR10(\regs)
+ STREG %r11,PT_GR11(\regs)
+ STREG %r12,PT_GR12(\regs)
+ STREG %r13,PT_GR13(\regs)
+ STREG %r14,PT_GR14(\regs)
+ STREG %r15,PT_GR15(\regs)
+ STREG %r16,PT_GR16(\regs)
+ STREG %r17,PT_GR17(\regs)
+ STREG %r18,PT_GR18(\regs)
+ .endm
+
+ .macro reg_restore regs
+ LDREG PT_GR3(\regs), %r3
+ LDREG PT_GR4(\regs), %r4
+ LDREG PT_GR5(\regs), %r5
+ LDREG PT_GR6(\regs), %r6
+ LDREG PT_GR7(\regs), %r7
+ LDREG PT_GR8(\regs), %r8
+ LDREG PT_GR9(\regs), %r9
+ LDREG PT_GR10(\regs),%r10
+ LDREG PT_GR11(\regs),%r11
+ LDREG PT_GR12(\regs),%r12
+ LDREG PT_GR13(\regs),%r13
+ LDREG PT_GR14(\regs),%r14
+ LDREG PT_GR15(\regs),%r15
+ LDREG PT_GR16(\regs),%r16
+ LDREG PT_GR17(\regs),%r17
+ LDREG PT_GR18(\regs),%r18
+ .endm
+
+ .export sys_fork_wrapper
+ .export child_return
+sys_fork_wrapper:
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
+ ldo TASK_REGS(%r1),%r1
+ reg_save %r1
+ mfctl %cr27, %r3
+ STREG %r3, PT_CR27(%r1)
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+
+ /* These are call-clobbered registers and therefore
+ also syscall-clobbered (we hope). */
+ STREG %r2,PT_GR19(%r1) /* save for child */
+ STREG %r30,PT_GR21(%r1)
+
+ LDREG PT_GR30(%r1),%r25
+ copy %r1,%r24
+ BL sys_clone,%r2
+ ldi SIGCHLD,%r26
+
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+wrapper_exit:
+ ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ ldo TASK_REGS(%r1),%r1 /* get pt regs */
+
+ LDREG PT_CR27(%r1), %r3
+ mtctl %r3, %cr27
+ reg_restore %r1
+
+ /* strace expects syscall # to be preserved in r20 */
+ ldi __NR_fork,%r20
+ bv %r0(%r2)
+ STREG %r20,PT_GR20(%r1)
+
+ /* Set the return value for the child */
+child_return:
+ BL schedule_tail, %r2
+ nop
+
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
+ LDREG TASK_PT_GR19(%r1),%r2
+ b wrapper_exit
+ copy %r0,%r28
+
+
+ .export sys_clone_wrapper
+sys_clone_wrapper:
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ ldo TASK_REGS(%r1),%r1 /* get pt regs */
+ reg_save %r1
+ mfctl %cr27, %r3
+ STREG %r3, PT_CR27(%r1)
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+
+ STREG %r2,PT_GR19(%r1) /* save for child */
+ STREG %r30,PT_GR21(%r1)
+ BL sys_clone,%r2
+ copy %r1,%r24
+
+ b wrapper_exit
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+
+ .export sys_vfork_wrapper
+sys_vfork_wrapper:
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ ldo TASK_REGS(%r1),%r1 /* get pt regs */
+ reg_save %r1
+ mfctl %cr27, %r3
+ STREG %r3, PT_CR27(%r1)
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+
+ STREG %r2,PT_GR19(%r1) /* save for child */
+ STREG %r30,PT_GR21(%r1)
+
+ BL sys_vfork,%r2
+ copy %r1,%r26
+
+ b wrapper_exit
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+
+
+ .macro execve_wrapper execve
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ ldo TASK_REGS(%r1),%r1 /* get pt regs */
+
+ /*
+ * Do we need to save/restore r3-r18 here?
+ * I don't think so. why would new thread need old
+ * threads registers?
+ */
+
+ /* %arg0 - %arg3 are already saved for us. */
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+ bl \execve,%r2
+ copy %r1,%arg0
+
+ ldo -FRAME_SIZE(%r30),%r30
+ LDREG -RP_OFFSET(%r30),%r2
+
+ /* If exec succeeded we need to load the args */
+
+ ldo -1024(%r0),%r1
+ cmpb,>>= %r28,%r1,error_\execve
+ copy %r2,%r19
+
+error_\execve:
+ bv %r0(%r19)
+ nop
+ .endm
+
+ .export sys_execve_wrapper
+ .import sys_execve
+
+sys_execve_wrapper:
+ execve_wrapper sys_execve
+
+#ifdef __LP64__
+ .export sys32_execve_wrapper
+ .import sys32_execve
+
+sys32_execve_wrapper:
+ execve_wrapper sys32_execve
+#endif
+
+ .export sys_rt_sigreturn_wrapper
+sys_rt_sigreturn_wrapper:
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
+ ldo TASK_REGS(%r26),%r26 /* get pt regs */
+ /* Don't save regs, we are going to restore them from sigcontext. */
+ STREG %r2, -RP_OFFSET(%r30)
+#ifdef __LP64__
+ ldo FRAME_SIZE(%r30), %r30
+ BL sys_rt_sigreturn,%r2
+ ldo -16(%r30),%r29 /* Reference param save area */
+#else
+ BL sys_rt_sigreturn,%r2
+ ldo FRAME_SIZE(%r30), %r30
+#endif
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+
+ /* FIXME: I think we need to restore a few more things here. */
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ ldo TASK_REGS(%r1),%r1 /* get pt regs */
+ reg_restore %r1
+
+ /* If the signal was received while the process was blocked on a
+ * syscall, then r2 will take us to syscall_exit; otherwise r2 will
+ * take us to syscall_exit_rfi and on to intr_return.
+ */
+ bv %r0(%r2)
+ LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
+
+ .export sys_sigaltstack_wrapper
+sys_sigaltstack_wrapper:
+ /* Get the user stack pointer */
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ ldo TASK_REGS(%r1),%r24 /* get pt regs */
+ LDREG TASK_PT_GR30(%r24),%r24
+ STREG %r2, -RP_OFFSET(%r30)
+#ifdef __LP64__
+ ldo FRAME_SIZE(%r30), %r30
+ b,l do_sigaltstack,%r2
+ ldo -16(%r30),%r29 /* Reference param save area */
+#else
+ bl do_sigaltstack,%r2
+ ldo FRAME_SIZE(%r30), %r30
+#endif
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ nop
+
+#ifdef __LP64__
+ .export sys32_sigaltstack_wrapper
+sys32_sigaltstack_wrapper:
+ /* Get the user stack pointer */
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24
+ LDREG TASK_PT_GR30(%r24),%r24
+ STREG %r2, -RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30), %r30
+ b,l do_sigaltstack32,%r2
+ ldo -16(%r30),%r29 /* Reference param save area */
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ nop
+#endif
+
+ .export sys_rt_sigsuspend_wrapper
+sys_rt_sigsuspend_wrapper:
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
+ ldo TASK_REGS(%r1),%r24
+ reg_save %r24
+
+ STREG %r2, -RP_OFFSET(%r30)
+#ifdef __LP64__
+ ldo FRAME_SIZE(%r30), %r30
+ b,l sys_rt_sigsuspend,%r2
+ ldo -16(%r30),%r29 /* Reference param save area */
+#else
+ bl sys_rt_sigsuspend,%r2
+ ldo FRAME_SIZE(%r30), %r30
+#endif
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
+ ldo TASK_REGS(%r1),%r1
+ reg_restore %r1
+
+ bv %r0(%r2)
+ nop
+
+ .export syscall_exit
+syscall_exit:
+
+ /* NOTE: HP-UX syscalls also come through here
+ * after hpux_syscall_exit fixes up return
+ * values. */
+
+ /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
+ * via syscall_exit_rfi if the signal was received while the process
+ * was running.
+ */
+
+ /* save return value now */
+
+ mfctl %cr30, %r1
+ LDREG TI_TASK(%r1),%r1
+ STREG %r28,TASK_PT_GR28(%r1)
+
+#ifdef CONFIG_HPUX
+
+/* <linux/personality.h> cannot be easily included */
+#define PER_HPUX 0x10
+ LDREG TASK_PERSONALITY(%r1),%r19
+
+ /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
+ ldo -PER_HPUX(%r19), %r19
+ CMPIB<>,n 0,%r19,1f
+
+ /* Save other hpux returns if personality is PER_HPUX */
+ STREG %r22,TASK_PT_GR22(%r1)
+ STREG %r29,TASK_PT_GR29(%r1)
+1:
+
+#endif /* CONFIG_HPUX */
+
+ /* Seems to me that dp could be wrong here, if the syscall involved
+ * calling a module, and nothing got round to restoring dp on return.
+ */
+ loadgp
+
+syscall_check_bh:
+
+ /* Check for software interrupts */
+
+ .import irq_stat,data
+
+ load32 irq_stat,%r19
+
+#ifdef CONFIG_SMP
+ /* sched.h: int processor */
+ /* %r26 is used as scratch register to index into irq_stat[] */
+ ldw TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
+
+ /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
+#ifdef __LP64__
+ shld %r26, 6, %r20
+#else
+ shlw %r26, 5, %r20
+#endif
+ add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */
+#endif /* CONFIG_SMP */
+
+ LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */
+ cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */
+
+syscall_check_resched:
+
+ /* check for reschedule */
+
+ LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */
+ bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
+
+syscall_check_sig:
+ LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* get ti flags */
+ bb,<,n %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
+
+syscall_restore:
+ /* Are we being ptraced? */
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+
+ LDREG TASK_PTRACE(%r1), %r19
+ bb,< %r19,31,syscall_restore_rfi
+ nop
+
+ ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */
+ rest_fp %r19
+
+ LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */
+ mtsar %r19
+
+ LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */
+ LDREG TASK_PT_GR19(%r1),%r19
+ LDREG TASK_PT_GR20(%r1),%r20
+ LDREG TASK_PT_GR21(%r1),%r21
+ LDREG TASK_PT_GR22(%r1),%r22
+ LDREG TASK_PT_GR23(%r1),%r23
+ LDREG TASK_PT_GR24(%r1),%r24
+ LDREG TASK_PT_GR25(%r1),%r25
+ LDREG TASK_PT_GR26(%r1),%r26
+ LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */
+ LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */
+ LDREG TASK_PT_GR29(%r1),%r29
+ LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */
+
+ /* NOTE: We use rsm/ssm pair to make this operation atomic */
+ rsm PSW_SM_I, %r0
+ LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */
+ mfsp %sr3,%r1 /* Get users space id */
+ mtsp %r1,%sr7 /* Restore sr7 */
+ ssm PSW_SM_I, %r0
+
+ /* Set sr2 to zero for userspace syscalls to work. */
+ mtsp %r0,%sr2
+ mtsp %r1,%sr4 /* Restore sr4 */
+ mtsp %r1,%sr5 /* Restore sr5 */
+ mtsp %r1,%sr6 /* Restore sr6 */
+
+ depi 3,31,2,%r31 /* ensure return to user mode. */
+
+#ifdef __LP64__
+ /* decide whether to reset the wide mode bit
+ *
+ * For a syscall, the W bit is stored in the lowest bit
+ * of sp. Extract it and reset W if it is zero */
+ extrd,u,*<> %r30,63,1,%r1
+ rsm PSW_SM_W, %r0
+ /* now reset the lowest bit of sp if it was set */
+ xor %r30,%r1,%r30
+#endif
+ be,n 0(%sr3,%r31) /* return to user space */
+
+ /* We have to return via an RFI, so that PSW T and R bits can be set
+ * appropriately.
+ * This sets up pt_regs so we can return via intr_restore, which is not
+ * the most efficient way of doing things, but it works.
+ */
+syscall_restore_rfi:
+ ldo -1(%r0),%r2 /* Set recovery cntr to -1 */
+ mtctl %r2,%cr0 /* for immediate trap */
+ LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */
+ ldi 0x0b,%r20 /* Create new PSW */
+ depi -1,13,1,%r20 /* C, Q, D, and I bits */
+
+ /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are
+ * set in include/linux/ptrace.h and converted to PA bitmap
+ * numbers in asm-offsets.c */
+
+ /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */
+ extru,= %r19,PA_SINGLESTEP_BIT,1,%r0
+ depi -1,27,1,%r20 /* R bit */
+
+ /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */
+ extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0
+ depi -1,7,1,%r20 /* T bit */
+
+ STREG %r20,TASK_PT_PSW(%r1)
+
+ /* Always store space registers, since sr3 can be changed (e.g. fork) */
+
+ mfsp %sr3,%r25
+ STREG %r25,TASK_PT_SR3(%r1)
+ STREG %r25,TASK_PT_SR4(%r1)
+ STREG %r25,TASK_PT_SR5(%r1)
+ STREG %r25,TASK_PT_SR6(%r1)
+ STREG %r25,TASK_PT_SR7(%r1)
+ STREG %r25,TASK_PT_IASQ0(%r1)
+ STREG %r25,TASK_PT_IASQ1(%r1)
+
+ /* XXX W bit??? */
+ /* Now if old D bit is clear, it means we didn't save all registers
+ * on syscall entry, so do that now. This only happens on TRACEME
+ * calls, or if someone attached to us while we were on a syscall.
+ * We could make this more efficient by not saving r3-r18, but
+ * then we wouldn't be able to use the common intr_restore path.
+ * It is only for traced processes anyway, so performance is not
+ * an issue.
+ */
+ bb,< %r2,30,pt_regs_ok /* Branch if D set */
+ ldo TASK_REGS(%r1),%r25
+ reg_save %r25 /* Save r3 to r18 */
+
+ /* Save the current sr */
+ mfsp %sr0,%r2
+ STREG %r2,TASK_PT_SR0(%r1)
+
+ /* Save the scratch sr */
+ mfsp %sr1,%r2
+ STREG %r2,TASK_PT_SR1(%r1)
+
+ /* sr2 should be set to zero for userspace syscalls */
+ STREG %r0,TASK_PT_SR2(%r1)
+
+pt_regs_ok:
+ LDREG TASK_PT_GR31(%r1),%r2
+ depi 3,31,2,%r2 /* ensure return to user mode. */
+ STREG %r2,TASK_PT_IAOQ0(%r1)
+ ldo 4(%r2),%r2
+ STREG %r2,TASK_PT_IAOQ1(%r1)
+ copy %r25,%r16
+ b intr_restore
+ nop
+
+ .import do_softirq,code
+syscall_do_softirq:
+ bl do_softirq,%r2
+ nop
+ /* NOTE: We enable I-bit incase we schedule later,
+ * and we might be going back to userspace if we were
+ * traced. */
+ b syscall_check_resched
+ ssm PSW_SM_I, %r0 /* do_softirq returns with I bit off */
+
+ .import schedule,code
+syscall_do_resched:
+ BL schedule,%r2
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#else
+ nop
+#endif
+ b syscall_check_bh /* if resched, we start over again */
+ nop
+
+ .import do_signal,code
+syscall_do_signal:
+ /* Save callee-save registers (for sigcontext).
+ FIXME: After this point the process structure should be
+ consistent with all the relevant state of the process
+ before the syscall. We need to verify this. */
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */
+ reg_save %r25
+
+ ldi 1, %r24 /* unsigned long in_syscall */
+
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+ BL do_signal,%r2
+ copy %r0, %r26 /* sigset_t *oldset = NULL */
+
+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
+ reg_restore %r20
+
+ b,n syscall_check_sig
+
+ /*
+ * get_register is used by the non access tlb miss handlers to
+ * copy the value of the general register specified in r8 into
+ * r1. This routine can't be used for shadowed registers, since
+ * the rfir will restore the original value. So, for the shadowed
+ * registers we put a -1 into r1 to indicate that the register
+ * should not be used (the register being copied could also have
+ * a -1 in it, but that is OK, it just means that we will have
+ * to use the slow path instead).
+ */
+
+get_register:
+ blr %r8,%r0
+ nop
+ bv %r0(%r25) /* r0 */
+ copy %r0,%r1
+ bv %r0(%r25) /* r1 - shadowed */
+ ldi -1,%r1
+ bv %r0(%r25) /* r2 */
+ copy %r2,%r1
+ bv %r0(%r25) /* r3 */
+ copy %r3,%r1
+ bv %r0(%r25) /* r4 */
+ copy %r4,%r1
+ bv %r0(%r25) /* r5 */
+ copy %r5,%r1
+ bv %r0(%r25) /* r6 */
+ copy %r6,%r1
+ bv %r0(%r25) /* r7 */
+ copy %r7,%r1
+ bv %r0(%r25) /* r8 - shadowed */
+ ldi -1,%r1
+ bv %r0(%r25) /* r9 - shadowed */
+ ldi -1,%r1
+ bv %r0(%r25) /* r10 */
+ copy %r10,%r1
+ bv %r0(%r25) /* r11 */
+ copy %r11,%r1
+ bv %r0(%r25) /* r12 */
+ copy %r12,%r1
+ bv %r0(%r25) /* r13 */
+ copy %r13,%r1
+ bv %r0(%r25) /* r14 */
+ copy %r14,%r1
+ bv %r0(%r25) /* r15 */
+ copy %r15,%r1
+ bv %r0(%r25) /* r16 - shadowed */
+ ldi -1,%r1
+ bv %r0(%r25) /* r17 - shadowed */
+ ldi -1,%r1
+ bv %r0(%r25) /* r18 */
+ copy %r18,%r1
+ bv %r0(%r25) /* r19 */
+ copy %r19,%r1
+ bv %r0(%r25) /* r20 */
+ copy %r20,%r1
+ bv %r0(%r25) /* r21 */
+ copy %r21,%r1
+ bv %r0(%r25) /* r22 */
+ copy %r22,%r1
+ bv %r0(%r25) /* r23 */
+ copy %r23,%r1
+ bv %r0(%r25) /* r24 - shadowed */
+ ldi -1,%r1
+ bv %r0(%r25) /* r25 - shadowed */
+ ldi -1,%r1
+ bv %r0(%r25) /* r26 */
+ copy %r26,%r1
+ bv %r0(%r25) /* r27 */
+ copy %r27,%r1
+ bv %r0(%r25) /* r28 */
+ copy %r28,%r1
+ bv %r0(%r25) /* r29 */
+ copy %r29,%r1
+ bv %r0(%r25) /* r30 */
+ copy %r30,%r1
+ bv %r0(%r25) /* r31 */
+ copy %r31,%r1
+
+ /*
+ * set_register is used by the non access tlb miss handlers to
+ * copy the value of r1 into the general register specified in
+ * r8.
+ */
+
+set_register:
+ blr %r8,%r0
+ nop
+ bv %r0(%r25) /* r0 (silly, but it is a place holder) */
+ copy %r1,%r0
+ bv %r0(%r25) /* r1 */
+ copy %r1,%r1
+ bv %r0(%r25) /* r2 */
+ copy %r1,%r2
+ bv %r0(%r25) /* r3 */
+ copy %r1,%r3
+ bv %r0(%r25) /* r4 */
+ copy %r1,%r4
+ bv %r0(%r25) /* r5 */
+ copy %r1,%r5
+ bv %r0(%r25) /* r6 */
+ copy %r1,%r6
+ bv %r0(%r25) /* r7 */
+ copy %r1,%r7
+ bv %r0(%r25) /* r8 */
+ copy %r1,%r8
+ bv %r0(%r25) /* r9 */
+ copy %r1,%r9
+ bv %r0(%r25) /* r10 */
+ copy %r1,%r10
+ bv %r0(%r25) /* r11 */
+ copy %r1,%r11
+ bv %r0(%r25) /* r12 */
+ copy %r1,%r12
+ bv %r0(%r25) /* r13 */
+ copy %r1,%r13
+ bv %r0(%r25) /* r14 */
+ copy %r1,%r14
+ bv %r0(%r25) /* r15 */
+ copy %r1,%r15
+ bv %r0(%r25) /* r16 */
+ copy %r1,%r16
+ bv %r0(%r25) /* r17 */
+ copy %r1,%r17
+ bv %r0(%r25) /* r18 */
+ copy %r1,%r18
+ bv %r0(%r25) /* r19 */
+ copy %r1,%r19
+ bv %r0(%r25) /* r20 */
+ copy %r1,%r20
+ bv %r0(%r25) /* r21 */
+ copy %r1,%r21
+ bv %r0(%r25) /* r22 */
+ copy %r1,%r22
+ bv %r0(%r25) /* r23 */
+ copy %r1,%r23
+ bv %r0(%r25) /* r24 */
+ copy %r1,%r24
+ bv %r0(%r25) /* r25 */
+ copy %r1,%r25
+ bv %r0(%r25) /* r26 */
+ copy %r1,%r26
+ bv %r0(%r25) /* r27 */
+ copy %r1,%r27
+ bv %r0(%r25) /* r28 */
+ copy %r1,%r28
+ bv %r0(%r25) /* r29 */
+ copy %r1,%r29
+ bv %r0(%r25) /* r30 */
+ copy %r1,%r30
+ bv %r0(%r25) /* r31 */
+ copy %r1,%r31
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
new file mode 100644
index 000000000000..f244fb200db1
--- /dev/null
+++ b/arch/parisc/kernel/firmware.c
@@ -0,0 +1,1405 @@
+/*
+ * arch/parisc/kernel/firmware.c - safe PDC access routines
+ *
+ * PDC == Processor Dependent Code
+ *
+ * See http://www.parisc-linux.org/documentation/index.html
+ * for documentation describing the entry points and calling
+ * conventions defined below.
+ *
+ * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org)
+ * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
+ * Copyright 2003 Grant Grundler <grundler parisc-linux org>
+ * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org>
+ * Copyright 2004 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/* I think it would be in everyone's best interest to follow this
+ * guidelines when writing PDC wrappers:
+ *
+ * - the name of the pdc wrapper should match one of the macros
+ * used for the first two arguments
+ * - don't use caps for random parts of the name
+ * - use the static PDC result buffers and "copyout" to structs
+ * supplied by the caller to encapsulate alignment restrictions
+ * - hold pdc_lock while in PDC or using static result buffers
+ * - use __pa() to convert virtual (kernel) pointers to physical
+ * ones.
+ * - the name of the struct used for pdc return values should equal
+ * one of the macros used for the first two arguments to the
+ * corresponding PDC call
+ * - keep the order of arguments
+ * - don't be smart (setting trailing NUL bytes for strings, return
+ * something useful even if the call failed) unless you are sure
+ * it's not going to affect functionality or performance
+ *
+ * Example:
+ * int pdc_cache_info(struct pdc_cache_info *cache_info )
+ * {
+ * int retval;
+ *
+ * spin_lock_irq(&pdc_lock);
+ * retval = mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
+ * convert_to_wide(pdc_result);
+ * memcpy(cache_info, pdc_result, sizeof(*cache_info));
+ * spin_unlock_irq(&pdc_lock);
+ *
+ * return retval;
+ * }
+ * prumpf 991016
+ */
+
+#include <stdarg.h>
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/pdcpat.h>
+#include <asm/system.h>
+#include <asm/processor.h> /* for boot_cpu_data */
+
+static DEFINE_SPINLOCK(pdc_lock);
+static unsigned long pdc_result[32] __attribute__ ((aligned (8)));
+static unsigned long pdc_result2[32] __attribute__ ((aligned (8)));
+
+#ifdef __LP64__
+#define WIDE_FIRMWARE 0x1
+#define NARROW_FIRMWARE 0x2
+
+/* Firmware needs to be initially set to narrow to determine the
+ * actual firmware width. */
+int parisc_narrow_firmware = 1;
+#endif
+
+/* on all currently-supported platforms, IODC I/O calls are always
+ * 32-bit calls, and MEM_PDC calls are always the same width as the OS.
+ * This means Cxxx boxes can't run wide kernels right now. -PB
+ *
+ * CONFIG_PDC_NARROW has been added to allow 64-bit kernels to run on
+ * systems with 32-bit MEM_PDC calls. This will allow wide kernels to
+ * run on Cxxx boxes now. -RB
+ *
+ * Note that some PAT boxes may have 64-bit IODC I/O...
+ */
+
+#ifdef __LP64__
+long real64_call(unsigned long function, ...);
+#endif
+long real32_call(unsigned long function, ...);
+
+#ifdef __LP64__
+# define MEM_PDC (unsigned long)(PAGE0->mem_pdc_hi) << 32 | PAGE0->mem_pdc
+# define mem_pdc_call(args...) unlikely(parisc_narrow_firmware) ? real32_call(MEM_PDC, args) : real64_call(MEM_PDC, args)
+#else
+# define MEM_PDC (unsigned long)PAGE0->mem_pdc
+# define mem_pdc_call(args...) real32_call(MEM_PDC, args)
+#endif
+
+
+/**
+ * f_extend - Convert PDC addresses to kernel addresses.
+ * @address: Address returned from PDC.
+ *
+ * This function is used to convert PDC addresses into kernel addresses
+ * when the PDC address size and kernel address size are different.
+ */
+static unsigned long f_extend(unsigned long address)
+{
+#ifdef __LP64__
+ if(unlikely(parisc_narrow_firmware)) {
+ if((address & 0xff000000) == 0xf0000000)
+ return 0xf0f0f0f000000000UL | (u32)address;
+
+ if((address & 0xf0000000) == 0xf0000000)
+ return 0xffffffff00000000UL | (u32)address;
+ }
+#endif
+ return address;
+}
+
+/**
+ * convert_to_wide - Convert the return buffer addresses into kernel addresses.
+ * @address: The return buffer from PDC.
+ *
+ * This function is used to convert the return buffer addresses retrieved from PDC
+ * into kernel addresses when the PDC address size and kernel address size are
+ * different.
+ */
+static void convert_to_wide(unsigned long *addr)
+{
+#ifdef __LP64__
+ int i;
+ unsigned int *p = (unsigned int *)addr;
+
+ if(unlikely(parisc_narrow_firmware)) {
+ for(i = 31; i >= 0; --i)
+ addr[i] = p[i];
+ }
+#endif
+}
+
+/**
+ * set_firmware_width - Determine if the firmware is wide or narrow.
+ *
+ * This function must be called before any pdc_* function that uses the convert_to_wide
+ * function.
+ */
+void __init set_firmware_width(void)
+{
+#ifdef __LP64__
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0);
+ convert_to_wide(pdc_result);
+ if(pdc_result[0] != NARROW_FIRMWARE)
+ parisc_narrow_firmware = 0;
+ spin_unlock_irq(&pdc_lock);
+#endif
+}
+
+/**
+ * pdc_emergency_unlock - Unlock the linux pdc lock
+ *
+ * This call unlocks the linux pdc lock in case we need some PDC functions
+ * (like pdc_add_valid) during kernel stack dump.
+ */
+void pdc_emergency_unlock(void)
+{
+ /* Spinlock DEBUG code freaks out if we unconditionally unlock */
+ if (spin_is_locked(&pdc_lock))
+ spin_unlock(&pdc_lock);
+}
+
+
+/**
+ * pdc_add_valid - Verify address can be accessed without causing a HPMC.
+ * @address: Address to be verified.
+ *
+ * This PDC call attempts to read from the specified address and verifies
+ * if the address is valid.
+ *
+ * The return value is PDC_OK (0) in case accessing this address is valid.
+ */
+int pdc_add_valid(unsigned long address)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, address);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_add_valid);
+
+/**
+ * pdc_chassis_info - Return chassis information.
+ * @result: The return buffer.
+ * @chassis_info: The memory buffer address.
+ * @len: The size of the memory buffer address.
+ *
+ * An HVERSION dependent call for returning the chassis information.
+ */
+int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ memcpy(&pdc_result, chassis_info, sizeof(*chassis_info));
+ memcpy(&pdc_result2, led_info, len);
+ retval = mem_pdc_call(PDC_CHASSIS, PDC_RETURN_CHASSIS_INFO,
+ __pa(pdc_result), __pa(pdc_result2), len);
+ memcpy(chassis_info, pdc_result, sizeof(*chassis_info));
+ memcpy(led_info, pdc_result2, len);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pat_chassis_send_log - Sends a PDC PAT CHASSIS log message.
+ * @retval: -1 on error, 0 on success. Other value are PDC errors
+ *
+ * Must be correctly formatted or expect system crash
+ */
+#ifdef __LP64__
+int pdc_pat_chassis_send_log(unsigned long state, unsigned long data)
+{
+ int retval = 0;
+
+ if (!is_pdc_pat())
+ return -1;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_CHASSIS_LOG, PDC_PAT_CHASSIS_WRITE_LOG, __pa(&state), __pa(&data));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+#endif
+
+/**
+ * pdc_chassis_disp - Updates display
+ * @retval: -1 on error, 0 on success
+ *
+ * Works on old PDC only (E class, others?)
+ */
+int pdc_chassis_disp(unsigned long disp)
+{
+ int retval = 0;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_coproc_cfg - To identify coprocessors attached to the processor.
+ * @pdc_coproc_info: Return buffer address.
+ *
+ * This PDC call returns the presence and status of all the coprocessors
+ * attached to the processor.
+ */
+int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result));
+ convert_to_wide(pdc_result);
+ pdc_coproc_info->ccr_functional = pdc_result[0];
+ pdc_coproc_info->ccr_present = pdc_result[1];
+ pdc_coproc_info->revision = pdc_result[17];
+ pdc_coproc_info->model = pdc_result[18];
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_iodc_read - Read data from the modules IODC.
+ * @actcnt: The actual number of bytes.
+ * @hpa: The HPA of the module for the iodc read.
+ * @index: The iodc entry point.
+ * @iodc_data: A buffer memory for the iodc options.
+ * @iodc_data_size: Size of the memory buffer.
+ *
+ * This PDC call reads from the IODC of the module specified by the hpa
+ * argument.
+ */
+int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index,
+ void *iodc_data, unsigned int iodc_data_size)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_IODC, PDC_IODC_READ, __pa(pdc_result), hpa,
+ index, __pa(pdc_result2), iodc_data_size);
+ convert_to_wide(pdc_result);
+ *actcnt = pdc_result[0];
+ memcpy(iodc_data, pdc_result2, iodc_data_size);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_iodc_read);
+
+/**
+ * pdc_system_map_find_mods - Locate unarchitected modules.
+ * @pdc_mod_info: Return buffer address.
+ * @mod_path: pointer to dev path structure.
+ * @mod_index: fixed address module index.
+ *
+ * To locate and identify modules which reside at fixed I/O addresses, which
+ * do not self-identify via architected bus walks.
+ */
+int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
+ struct pdc_module_path *mod_path, long mod_index)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
+ __pa(pdc_result2), mod_index);
+ convert_to_wide(pdc_result);
+ memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info));
+ memcpy(mod_path, pdc_result2, sizeof(*mod_path));
+ spin_unlock_irq(&pdc_lock);
+
+ pdc_mod_info->mod_addr = f_extend(pdc_mod_info->mod_addr);
+ return retval;
+}
+
+/**
+ * pdc_system_map_find_addrs - Retrieve additional address ranges.
+ * @pdc_addr_info: Return buffer address.
+ * @mod_index: Fixed address module index.
+ * @addr_index: Address range index.
+ *
+ * Retrieve additional information about subsequent address ranges for modules
+ * with multiple address ranges.
+ */
+int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info,
+ long mod_index, long addr_index)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_ADDRESS, __pa(pdc_result),
+ mod_index, addr_index);
+ convert_to_wide(pdc_result);
+ memcpy(pdc_addr_info, pdc_result, sizeof(*pdc_addr_info));
+ spin_unlock_irq(&pdc_lock);
+
+ pdc_addr_info->mod_addr = f_extend(pdc_addr_info->mod_addr);
+ return retval;
+}
+
+/**
+ * pdc_model_info - Return model information about the processor.
+ * @model: The return buffer.
+ *
+ * Returns the version numbers, identifiers, and capabilities from the processor module.
+ */
+int pdc_model_info(struct pdc_model *model)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_INFO, __pa(pdc_result), 0);
+ convert_to_wide(pdc_result);
+ memcpy(model, pdc_result, sizeof(*model));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_model_sysmodel - Get the system model name.
+ * @name: A char array of at least 81 characters.
+ *
+ * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L)
+ */
+int pdc_model_sysmodel(char *name)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_SYSMODEL, __pa(pdc_result),
+ OS_ID_HPUX, __pa(name));
+ convert_to_wide(pdc_result);
+
+ if (retval == PDC_OK) {
+ name[pdc_result[0]] = '\0'; /* add trailing '\0' */
+ } else {
+ name[0] = 0;
+ }
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_model_versions - Identify the version number of each processor.
+ * @cpu_id: The return buffer.
+ * @id: The id of the processor to check.
+ *
+ * Returns the version number for each processor component.
+ *
+ * This comment was here before, but I do not know what it means :( -RB
+ * id: 0 = cpu revision, 1 = boot-rom-version
+ */
+int pdc_model_versions(unsigned long *versions, int id)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_VERSIONS, __pa(pdc_result), id);
+ convert_to_wide(pdc_result);
+ *versions = pdc_result[0];
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_model_cpuid - Returns the CPU_ID.
+ * @cpu_id: The return buffer.
+ *
+ * Returns the CPU_ID value which uniquely identifies the cpu portion of
+ * the processor module.
+ */
+int pdc_model_cpuid(unsigned long *cpu_id)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ pdc_result[0] = 0; /* preset zero (call may not be implemented!) */
+ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CPU_ID, __pa(pdc_result), 0);
+ convert_to_wide(pdc_result);
+ *cpu_id = pdc_result[0];
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_model_capabilities - Returns the platform capabilities.
+ * @capabilities: The return buffer.
+ *
+ * Returns information about platform support for 32- and/or 64-bit
+ * OSes, IO-PDIR coherency, and virtual aliasing.
+ */
+int pdc_model_capabilities(unsigned long *capabilities)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ pdc_result[0] = 0; /* preset zero (call may not be implemented!) */
+ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0);
+ convert_to_wide(pdc_result);
+ *capabilities = pdc_result[0];
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_cache_info - Return cache and TLB information.
+ * @cache_info: The return buffer.
+ *
+ * Returns information about the processor's cache and TLB.
+ */
+int pdc_cache_info(struct pdc_cache_info *cache_info)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_INFO, __pa(pdc_result), 0);
+ convert_to_wide(pdc_result);
+ memcpy(cache_info, pdc_result, sizeof(*cache_info));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+#ifndef CONFIG_PA20
+/**
+ * pdc_btlb_info - Return block TLB information.
+ * @btlb: The return buffer.
+ *
+ * Returns information about the hardware Block TLB.
+ */
+int pdc_btlb_info(struct pdc_btlb_info *btlb)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0);
+ memcpy(btlb, pdc_result, sizeof(*btlb));
+ spin_unlock_irq(&pdc_lock);
+
+ if(retval < 0) {
+ btlb->max_size = 0;
+ }
+ return retval;
+}
+
+/**
+ * pdc_mem_map_hpa - Find fixed module information.
+ * @address: The return buffer
+ * @mod_path: pointer to dev path structure.
+ *
+ * This call was developed for S700 workstations to allow the kernel to find
+ * the I/O devices (Core I/O). In the future (Kittyhawk and beyond) this
+ * call will be replaced (on workstations) by the architected PDC_SYSTEM_MAP
+ * call.
+ *
+ * This call is supported by all existing S700 workstations (up to Gecko).
+ */
+int pdc_mem_map_hpa(struct pdc_memory_map *address,
+ struct pdc_module_path *mod_path)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ memcpy(pdc_result2, mod_path, sizeof(*mod_path));
+ retval = mem_pdc_call(PDC_MEM_MAP, PDC_MEM_MAP_HPA, __pa(pdc_result),
+ __pa(pdc_result2));
+ memcpy(address, pdc_result, sizeof(*address));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+#endif /* !CONFIG_PA20 */
+
+/**
+ * pdc_lan_station_id - Get the LAN address.
+ * @lan_addr: The return buffer.
+ * @hpa: The network device HPA.
+ *
+ * Get the LAN station address when it is not directly available from the LAN hardware.
+ */
+int pdc_lan_station_id(char *lan_addr, unsigned long hpa)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
+ __pa(pdc_result), hpa);
+ if (retval < 0) {
+ /* FIXME: else read MAC from NVRAM */
+ memset(lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
+ } else {
+ memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE);
+ }
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_lan_station_id);
+
+/**
+ * pdc_stable_read - Read data from Stable Storage.
+ * @staddr: Stable Storage address to access.
+ * @memaddr: The memory address where Stable Storage data shall be copied.
+ * @count: number of bytes to transfert. count is multiple of 4.
+ *
+ * This PDC call reads from the Stable Storage address supplied in staddr
+ * and copies count bytes to the memory address memaddr.
+ * The call will fail if staddr+count > PDC_STABLE size.
+ */
+int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_READ, staddr,
+ __pa(pdc_result), count);
+ convert_to_wide(pdc_result);
+ memcpy(memaddr, pdc_result, count);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_stable_read);
+
+/**
+ * pdc_stable_write - Write data to Stable Storage.
+ * @staddr: Stable Storage address to access.
+ * @memaddr: The memory address where Stable Storage data shall be read from.
+ * @count: number of bytes to transfert. count is multiple of 4.
+ *
+ * This PDC call reads count bytes from the supplied memaddr address,
+ * and copies count bytes to the Stable Storage address staddr.
+ * The call will fail if staddr+count > PDC_STABLE size.
+ */
+int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ memcpy(pdc_result, memaddr, count);
+ convert_to_wide(pdc_result);
+ retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_WRITE, staddr,
+ __pa(pdc_result), count);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_stable_write);
+
+/**
+ * pdc_stable_get_size - Get Stable Storage size in bytes.
+ * @size: pointer where the size will be stored.
+ *
+ * This PDC call returns the number of bytes in the processor's Stable
+ * Storage, which is the number of contiguous bytes implemented in Stable
+ * Storage starting from staddr=0. size in an unsigned 64-bit integer
+ * which is a multiple of four.
+ */
+int pdc_stable_get_size(unsigned long *size)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_RETURN_SIZE, __pa(pdc_result));
+ *size = pdc_result[0];
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_stable_get_size);
+
+/**
+ * pdc_stable_verify_contents - Checks that Stable Storage contents are valid.
+ *
+ * This PDC call is meant to be used to check the integrity of the current
+ * contents of Stable Storage.
+ */
+int pdc_stable_verify_contents(void)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_VERIFY_CONTENTS);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_stable_verify_contents);
+
+/**
+ * pdc_stable_initialize - Sets Stable Storage contents to zero and initialize
+ * the validity indicator.
+ *
+ * This PDC call will erase all contents of Stable Storage. Use with care!
+ */
+int pdc_stable_initialize(void)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_INITIALIZE);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_stable_initialize);
+
+/**
+ * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD)
+ * @hwpath: fully bc.mod style path to the device.
+ * @initiator: the array to return the result into
+ *
+ * Get the SCSI operational parameters from PDC.
+ * Needed since HPUX never used BIOS or symbios card NVRAM.
+ * Most ncr/sym cards won't have an entry and just use whatever
+ * capabilities of the card are (eg Ultra, LVD). But there are
+ * several cases where it's useful:
+ * o set SCSI id for Multi-initiator clusters,
+ * o cable too long (ie SE scsi 10Mhz won't support 6m length),
+ * o bus width exported is less than what the interface chip supports.
+ */
+int pdc_get_initiator(struct hardware_path *hwpath, struct pdc_initiator *initiator)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+
+/* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */
+#define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \
+ strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 8) == 0)
+
+ retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR,
+ __pa(pdc_result), __pa(hwpath));
+ if (retval < PDC_OK)
+ goto out;
+
+ if (pdc_result[0] < 16) {
+ initiator->host_id = pdc_result[0];
+ } else {
+ initiator->host_id = -1;
+ }
+
+ /*
+ * Sprockets and Piranha return 20 or 40 (MT/s). Prelude returns
+ * 1, 2, 5 or 10 for 5, 10, 20 or 40 MT/s, respectively
+ */
+ switch (pdc_result[1]) {
+ case 1: initiator->factor = 50; break;
+ case 2: initiator->factor = 25; break;
+ case 5: initiator->factor = 12; break;
+ case 25: initiator->factor = 10; break;
+ case 20: initiator->factor = 12; break;
+ case 40: initiator->factor = 10; break;
+ default: initiator->factor = -1; break;
+ }
+
+ if (IS_SPROCKETS()) {
+ initiator->width = pdc_result[4];
+ initiator->mode = pdc_result[5];
+ } else {
+ initiator->width = -1;
+ initiator->mode = -1;
+ }
+
+ out:
+ spin_unlock_irq(&pdc_lock);
+ return (retval >= PDC_OK);
+}
+EXPORT_SYMBOL(pdc_get_initiator);
+
+
+/**
+ * pdc_pci_irt_size - Get the number of entries in the interrupt routing table.
+ * @num_entries: The return value.
+ * @hpa: The HPA for the device.
+ *
+ * This PDC function returns the number of entries in the specified cell's
+ * interrupt table.
+ * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes
+ */
+int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE,
+ __pa(pdc_result), hpa);
+ convert_to_wide(pdc_result);
+ *num_entries = pdc_result[0];
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pci_irt - Get the PCI interrupt routing table.
+ * @num_entries: The number of entries in the table.
+ * @hpa: The Hard Physical Address of the device.
+ * @tbl:
+ *
+ * Get the PCI interrupt routing table for the device at the given HPA.
+ * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes
+ */
+int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl)
+{
+ int retval;
+
+ BUG_ON((unsigned long)tbl & 0x7);
+
+ spin_lock_irq(&pdc_lock);
+ pdc_result[0] = num_entries;
+ retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
+ __pa(pdc_result), hpa, __pa(tbl));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+
+#if 0 /* UNTEST CODE - left here in case someone needs it */
+
+/**
+ * pdc_pci_config_read - read PCI config space.
+ * @hpa token from PDC to indicate which PCI device
+ * @pci_addr configuration space address to read from
+ *
+ * Read PCI Configuration space *before* linux PCI subsystem is running.
+ */
+unsigned int pdc_pci_config_read(void *hpa, unsigned long cfg_addr)
+{
+ int retval;
+ spin_lock_irq(&pdc_lock);
+ pdc_result[0] = 0;
+ pdc_result[1] = 0;
+ retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_READ_CONFIG,
+ __pa(pdc_result), hpa, cfg_addr&~3UL, 4UL);
+ spin_unlock_irq(&pdc_lock);
+ return retval ? ~0 : (unsigned int) pdc_result[0];
+}
+
+
+/**
+ * pdc_pci_config_write - read PCI config space.
+ * @hpa token from PDC to indicate which PCI device
+ * @pci_addr configuration space address to write
+ * @val value we want in the 32-bit register
+ *
+ * Write PCI Configuration space *before* linux PCI subsystem is running.
+ */
+void pdc_pci_config_write(void *hpa, unsigned long cfg_addr, unsigned int val)
+{
+ int retval;
+ spin_lock_irq(&pdc_lock);
+ pdc_result[0] = 0;
+ retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_WRITE_CONFIG,
+ __pa(pdc_result), hpa,
+ cfg_addr&~3UL, 4UL, (unsigned long) val);
+ spin_unlock_irq(&pdc_lock);
+ return retval;
+}
+#endif /* UNTESTED CODE */
+
+/**
+ * pdc_tod_read - Read the Time-Of-Day clock.
+ * @tod: The return buffer:
+ *
+ * Read the Time-Of-Day clock
+ */
+int pdc_tod_read(struct pdc_tod *tod)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(pdc_result), 0);
+ convert_to_wide(pdc_result);
+ memcpy(tod, pdc_result, sizeof(*tod));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_tod_read);
+
+/**
+ * pdc_tod_set - Set the Time-Of-Day clock.
+ * @sec: The number of seconds since epoch.
+ * @usec: The number of micro seconds.
+ *
+ * Set the Time-Of-Day clock.
+ */
+int pdc_tod_set(unsigned long sec, unsigned long usec)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_tod_set);
+
+#ifdef __LP64__
+int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
+ struct pdc_memory_table *tbl, unsigned long entries)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_MEM, PDC_MEM_TABLE, __pa(pdc_result), __pa(pdc_result2), entries);
+ convert_to_wide(pdc_result);
+ memcpy(r_addr, pdc_result, sizeof(*r_addr));
+ memcpy(tbl, pdc_result2, entries * sizeof(*tbl));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+#endif /* __LP64__ */
+
+/* FIXME: Is this pdc used? I could not find type reference to ftc_bitmap
+ * so I guessed at unsigned long. Someone who knows what this does, can fix
+ * it later. :)
+ */
+int pdc_do_firm_test_reset(unsigned long ftc_bitmap)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_FIRM_TEST_RESET,
+ PDC_FIRM_TEST_MAGIC, ftc_bitmap);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/*
+ * pdc_do_reset - Reset the system.
+ *
+ * Reset the system.
+ */
+int pdc_do_reset(void)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/*
+ * pdc_soft_power_info - Enable soft power switch.
+ * @power_reg: address of soft power register
+ *
+ * Return the absolute address of the soft power switch register
+ */
+int __init pdc_soft_power_info(unsigned long *power_reg)
+{
+ int retval;
+
+ *power_reg = (unsigned long) (-1);
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0);
+ if (retval == PDC_OK) {
+ convert_to_wide(pdc_result);
+ *power_reg = f_extend(pdc_result[0]);
+ }
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/*
+ * pdc_soft_power_button - Control the soft power button behaviour
+ * @sw_control: 0 for hardware control, 1 for software control
+ *
+ *
+ * This PDC function places the soft power button under software or
+ * hardware control.
+ * Under software control the OS may control to when to allow to shut
+ * down the system. Under hardware control pressing the power button
+ * powers off the system immediately.
+ */
+int pdc_soft_power_button(int sw_control)
+{
+ int retval;
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control);
+ spin_unlock_irq(&pdc_lock);
+ return retval;
+}
+
+/*
+ * pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices.
+ * Primarily a problem on T600 (which parisc-linux doesn't support) but
+ * who knows what other platform firmware might do with this OS "hook".
+ */
+void pdc_io_reset(void)
+{
+ spin_lock_irq(&pdc_lock);
+ mem_pdc_call(PDC_IO, PDC_IO_RESET, 0);
+ spin_unlock_irq(&pdc_lock);
+}
+
+/*
+ * pdc_io_reset_devices - Hack to Stop USB controller
+ *
+ * If PDC used the usb controller, the usb controller
+ * is still running and will crash the machines during iommu
+ * setup, because of still running DMA. This PDC call
+ * stops the USB controller.
+ * Normally called after calling pdc_io_reset().
+ */
+void pdc_io_reset_devices(void)
+{
+ spin_lock_irq(&pdc_lock);
+ mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0);
+ spin_unlock_irq(&pdc_lock);
+}
+
+
+/**
+ * pdc_iodc_putc - Console character print using IODC.
+ * @c: the character to output.
+ *
+ * Note that only these special chars are architected for console IODC io:
+ * BEL, BS, CR, and LF. Others are passed through.
+ * Since the HP console requires CR+LF to perform a 'newline', we translate
+ * "\n" to "\r\n".
+ */
+void pdc_iodc_putc(unsigned char c)
+{
+ /* XXX Should we spinlock posx usage */
+ static int posx; /* for simple TAB-Simulation... */
+ static int __attribute__((aligned(8))) iodc_retbuf[32];
+ static char __attribute__((aligned(64))) iodc_dbuf[4096];
+ unsigned int n;
+ unsigned int flags;
+
+ switch (c) {
+ case '\n':
+ iodc_dbuf[0] = '\r';
+ iodc_dbuf[1] = '\n';
+ n = 2;
+ posx = 0;
+ break;
+ case '\t':
+ pdc_iodc_putc(' ');
+ while (posx & 7) /* expand TAB */
+ pdc_iodc_putc(' ');
+ return; /* return since IODC can't handle this */
+ case '\b':
+ posx-=2; /* BS */
+ default:
+ iodc_dbuf[0] = c;
+ n = 1;
+ posx++;
+ break;
+ }
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ real32_call(PAGE0->mem_cons.iodc_io,
+ (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
+ PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
+ spin_unlock_irqrestore(&pdc_lock, flags);
+}
+
+/**
+ * pdc_iodc_outc - Console character print using IODC (without conversions).
+ * @c: the character to output.
+ *
+ * Write the character directly to the IODC console.
+ */
+void pdc_iodc_outc(unsigned char c)
+{
+ unsigned int n, flags;
+
+ /* fill buffer with one caracter and print it */
+ static int __attribute__((aligned(8))) iodc_retbuf[32];
+ static char __attribute__((aligned(64))) iodc_dbuf[4096];
+
+ n = 1;
+ iodc_dbuf[0] = c;
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ real32_call(PAGE0->mem_cons.iodc_io,
+ (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
+ PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
+ spin_unlock_irqrestore(&pdc_lock, flags);
+}
+
+/**
+ * pdc_iodc_getc - Read a character (non-blocking) from the PDC console.
+ *
+ * Read a character (non-blocking) from the PDC console, returns -1 if
+ * key is not present.
+ */
+int pdc_iodc_getc(void)
+{
+ unsigned int flags;
+ static int __attribute__((aligned(8))) iodc_retbuf[32];
+ static char __attribute__((aligned(64))) iodc_dbuf[4096];
+ int ch;
+ int status;
+
+ /* Bail if no console input device. */
+ if (!PAGE0->mem_kbd.iodc_io)
+ return 0;
+
+ /* wait for a keyboard (rs232)-input */
+ spin_lock_irqsave(&pdc_lock, flags);
+ real32_call(PAGE0->mem_kbd.iodc_io,
+ (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
+ PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
+
+ ch = *iodc_dbuf;
+ status = *iodc_retbuf;
+ spin_unlock_irqrestore(&pdc_lock, flags);
+
+ if (status == 0)
+ return -1;
+
+ return ch;
+}
+
+int pdc_sti_call(unsigned long func, unsigned long flags,
+ unsigned long inptr, unsigned long outputr,
+ unsigned long glob_cfg)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = real32_call(func, flags, inptr, outputr, glob_cfg);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(pdc_sti_call);
+
+#ifdef __LP64__
+/**
+ * pdc_pat_cell_get_number - Returns the cell number.
+ * @cell_info: The return buffer.
+ *
+ * This PDC call returns the cell number of the cell from which the call
+ * is made.
+ */
+int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_NUMBER, __pa(pdc_result));
+ memcpy(cell_info, pdc_result, sizeof(*cell_info));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pat_cell_module - Retrieve the cell's module information.
+ * @actcnt: The number of bytes written to mem_addr.
+ * @ploc: The physical location.
+ * @mod: The module index.
+ * @view_type: The view of the address type.
+ * @mem_addr: The return buffer.
+ *
+ * This PDC call returns information about each module attached to the cell
+ * at the specified location.
+ */
+int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod,
+ unsigned long view_type, void *mem_addr)
+{
+ int retval;
+ static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8)));
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result),
+ ploc, mod, view_type, __pa(&result));
+ if(!retval) {
+ *actcnt = pdc_result[0];
+ memcpy(mem_addr, &result, *actcnt);
+ }
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pat_cpu_get_number - Retrieve the cpu number.
+ * @cpu_info: The return buffer.
+ * @hpa: The Hard Physical Address of the CPU.
+ *
+ * Retrieve the cpu number for the cpu at the specified HPA.
+ */
+int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER,
+ __pa(&pdc_result), hpa);
+ memcpy(cpu_info, pdc_result, sizeof(*cpu_info));
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pat_get_irt_size - Retrieve the number of entries in the cell's interrupt table.
+ * @num_entries: The return value.
+ * @cell_num: The target cell.
+ *
+ * This PDC function returns the number of entries in the specified cell's
+ * interrupt table.
+ */
+int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE,
+ __pa(pdc_result), cell_num);
+ *num_entries = pdc_result[0];
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pat_get_irt - Retrieve the cell's interrupt table.
+ * @r_addr: The return buffer.
+ * @cell_num: The target cell.
+ *
+ * This PDC function returns the actual interrupt table for the specified cell.
+ */
+int pdc_pat_get_irt(void *r_addr, unsigned long cell_num)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE,
+ __pa(r_addr), cell_num);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pat_pd_get_addr_map - Retrieve information about memory address ranges.
+ * @actlen: The return buffer.
+ * @mem_addr: Pointer to the memory buffer.
+ * @count: The number of bytes to read from the buffer.
+ * @offset: The offset with respect to the beginning of the buffer.
+ *
+ */
+int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr,
+ unsigned long count, unsigned long offset)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_ADDR_MAP, __pa(pdc_result),
+ __pa(pdc_result2), count, offset);
+ *actual_len = pdc_result[0];
+ memcpy(mem_addr, pdc_result2, *actual_len);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pat_io_pci_cfg_read - Read PCI configuration space.
+ * @pci_addr: PCI configuration space address for which the read request is being made.
+ * @pci_size: Size of read in bytes. Valid values are 1, 2, and 4.
+ * @mem_addr: Pointer to return memory buffer.
+ *
+ */
+int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr)
+{
+ int retval;
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ,
+ __pa(pdc_result), pci_addr, pci_size);
+ switch(pci_size) {
+ case 1: *(u8 *) mem_addr = (u8) pdc_result[0];
+ case 2: *(u16 *)mem_addr = (u16) pdc_result[0];
+ case 4: *(u32 *)mem_addr = (u32) pdc_result[0];
+ }
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+
+/**
+ * pdc_pat_io_pci_cfg_write - Retrieve information about memory address ranges.
+ * @pci_addr: PCI configuration space address for which the write request is being made.
+ * @pci_size: Size of write in bytes. Valid values are 1, 2, and 4.
+ * @value: Pointer to 1, 2, or 4 byte value in low order end of argument to be
+ * written to PCI Config space.
+ *
+ */
+int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+ retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_WRITE,
+ pci_addr, pci_size, val);
+ spin_unlock_irq(&pdc_lock);
+
+ return retval;
+}
+#endif /* __LP64__ */
+
+
+/***************** 32-bit real-mode calls ***********/
+/* The struct below is used
+ * to overlay real_stack (real2.S), preparing a 32-bit call frame.
+ * real32_call_asm() then uses this stack in narrow real mode
+ */
+
+struct narrow_stack {
+ /* use int, not long which is 64 bits */
+ unsigned int arg13;
+ unsigned int arg12;
+ unsigned int arg11;
+ unsigned int arg10;
+ unsigned int arg9;
+ unsigned int arg8;
+ unsigned int arg7;
+ unsigned int arg6;
+ unsigned int arg5;
+ unsigned int arg4;
+ unsigned int arg3;
+ unsigned int arg2;
+ unsigned int arg1;
+ unsigned int arg0;
+ unsigned int frame_marker[8];
+ unsigned int sp;
+ /* in reality, there's nearly 8k of stack after this */
+};
+
+long real32_call(unsigned long fn, ...)
+{
+ va_list args;
+ extern struct narrow_stack real_stack;
+ extern unsigned long real32_call_asm(unsigned int *,
+ unsigned int *,
+ unsigned int);
+
+ va_start(args, fn);
+ real_stack.arg0 = va_arg(args, unsigned int);
+ real_stack.arg1 = va_arg(args, unsigned int);
+ real_stack.arg2 = va_arg(args, unsigned int);
+ real_stack.arg3 = va_arg(args, unsigned int);
+ real_stack.arg4 = va_arg(args, unsigned int);
+ real_stack.arg5 = va_arg(args, unsigned int);
+ real_stack.arg6 = va_arg(args, unsigned int);
+ real_stack.arg7 = va_arg(args, unsigned int);
+ real_stack.arg8 = va_arg(args, unsigned int);
+ real_stack.arg9 = va_arg(args, unsigned int);
+ real_stack.arg10 = va_arg(args, unsigned int);
+ real_stack.arg11 = va_arg(args, unsigned int);
+ real_stack.arg12 = va_arg(args, unsigned int);
+ real_stack.arg13 = va_arg(args, unsigned int);
+ va_end(args);
+
+ return real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
+}
+
+#ifdef __LP64__
+/***************** 64-bit real-mode calls ***********/
+
+struct wide_stack {
+ unsigned long arg0;
+ unsigned long arg1;
+ unsigned long arg2;
+ unsigned long arg3;
+ unsigned long arg4;
+ unsigned long arg5;
+ unsigned long arg6;
+ unsigned long arg7;
+ unsigned long arg8;
+ unsigned long arg9;
+ unsigned long arg10;
+ unsigned long arg11;
+ unsigned long arg12;
+ unsigned long arg13;
+ unsigned long frame_marker[2]; /* rp, previous sp */
+ unsigned long sp;
+ /* in reality, there's nearly 8k of stack after this */
+};
+
+long real64_call(unsigned long fn, ...)
+{
+ va_list args;
+ extern struct wide_stack real64_stack;
+ extern unsigned long real64_call_asm(unsigned long *,
+ unsigned long *,
+ unsigned long);
+
+ va_start(args, fn);
+ real64_stack.arg0 = va_arg(args, unsigned long);
+ real64_stack.arg1 = va_arg(args, unsigned long);
+ real64_stack.arg2 = va_arg(args, unsigned long);
+ real64_stack.arg3 = va_arg(args, unsigned long);
+ real64_stack.arg4 = va_arg(args, unsigned long);
+ real64_stack.arg5 = va_arg(args, unsigned long);
+ real64_stack.arg6 = va_arg(args, unsigned long);
+ real64_stack.arg7 = va_arg(args, unsigned long);
+ real64_stack.arg8 = va_arg(args, unsigned long);
+ real64_stack.arg9 = va_arg(args, unsigned long);
+ real64_stack.arg10 = va_arg(args, unsigned long);
+ real64_stack.arg11 = va_arg(args, unsigned long);
+ real64_stack.arg12 = va_arg(args, unsigned long);
+ real64_stack.arg13 = va_arg(args, unsigned long);
+ va_end(args);
+
+ return real64_call_asm(&real64_stack.sp, &real64_stack.arg0, fn);
+}
+
+#endif /* __LP64__ */
+
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
new file mode 100644
index 000000000000..2071b5bba15c
--- /dev/null
+++ b/arch/parisc/kernel/hardware.c
@@ -0,0 +1,1366 @@
+/*
+ * Hardware descriptions for HP 9000 based hardware, including
+ * system types, SCSI controllers, DMA controllers, HPPB controllers
+ * and lots more.
+ *
+ * Based on the document "PA-RISC 1.1 I/O Firmware Architecture
+ * Reference Specification", March 7, 1999, version 0.96. This
+ * is available at http://parisc-linux.org/documentation/
+ *
+ * Copyright 1999 by Alex deVries <alex@onefishtwo.ca>
+ * and copyright 1999 The Puffin Group Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <asm/hardware.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+/*
+ * HP PARISC Hardware Database
+ * Access to this database is only possible during bootup
+ * so don't reference this table after starting the init process
+ */
+
+static struct hp_hardware hp_hardware_list[] __initdata = {
+ {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
+ {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
+ {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
+ {HPHW_NPROC,0xB,0x4,0x01,"Technical Shogun (845, 645)"},
+ {HPHW_NPROC,0xF,0x4,0x01,"Commercial Shogun (949)"},
+ {HPHW_NPROC,0xC,0x4,0x01,"Cheetah (850, 950)"},
+ {HPHW_NPROC,0x80,0x4,0x01,"Cheetah (950S)"},
+ {HPHW_NPROC,0x81,0x4,0x01,"Jaguar (855, 955)"},
+ {HPHW_NPROC,0x82,0x4,0x01,"Cougar (860, 960)"},
+ {HPHW_NPROC,0x83,0x4,0x13,"Panther (865, 870, 980)"},
+ {HPHW_NPROC,0x100,0x4,0x01,"Burgundy (810)"},
+ {HPHW_NPROC,0x101,0x4,0x01,"SilverFox Low (822, 922)"},
+ {HPHW_NPROC,0x102,0x4,0x01,"SilverFox High (832, 932)"},
+ {HPHW_NPROC,0x103,0x4,0x01,"Lego, SilverLite (815, 808, 920)"},
+ {HPHW_NPROC,0x104,0x4,0x03,"SilverBullet Low (842, 948)"},
+ {HPHW_NPROC,0x105,0x4,0x03,"SilverBullet High (852, 958)"},
+ {HPHW_NPROC,0x106,0x4,0x81,"Oboe"},
+ {HPHW_NPROC,0x180,0x4,0x12,"Dragon"},
+ {HPHW_NPROC,0x181,0x4,0x13,"Chimera (890, 990, 992)"},
+ {HPHW_NPROC,0x182,0x4,0x91,"TNT 100 (891,T500)"},
+ {HPHW_NPROC,0x183,0x4,0x91,"TNT 120 (892,T520)"},
+ {HPHW_NPROC,0x184,0x4,0x91,"Jade 180 U (893,T540)"},
+ {HPHW_NPROC,0x1FF,0x4,0x91,"Hitachi X Processor"},
+ {HPHW_NPROC,0x200,0x4,0x81,"Cobra (720)"},
+ {HPHW_NPROC,0x201,0x4,0x81,"Coral (750)"},
+ {HPHW_NPROC,0x202,0x4,0x81,"King Cobra (730)"},
+ {HPHW_NPROC,0x203,0x4,0x81,"Hardball (735/99)"},
+ {HPHW_NPROC,0x204,0x4,0x81,"Coral II (755/99)"},
+ {HPHW_NPROC,0x205,0x4,0x81,"Coral II (755/125)"},
+ {HPHW_NPROC,0x205,0x4,0x91,"Snake Eagle "},
+ {HPHW_NPROC,0x206,0x4,0x81,"Snake Cheetah (735/130)"},
+ {HPHW_NPROC,0x280,0x4,0x81,"Nova Low (817, 827, 957, 957LX)"},
+ {HPHW_NPROC,0x281,0x4,0x81,"Nova High (837, 847, 857, 967, 967LX)"},
+ {HPHW_NPROC,0x282,0x4,0x81,"Nova8 (807, 917, 917LX, 927,927LX, 937, 937LX, 947,947LX)"},
+ {HPHW_NPROC,0x283,0x4,0x81,"Nova64 (867, 877, 977)"},
+ {HPHW_NPROC,0x284,0x4,0x81,"TNova (887, 897, 987)"},
+ {HPHW_NPROC,0x285,0x4,0x81,"TNova64"},
+ {HPHW_NPROC,0x286,0x4,0x91,"Hydra64 (Nova)"},
+ {HPHW_NPROC,0x287,0x4,0x91,"Hydra96 (Nova)"},
+ {HPHW_NPROC,0x288,0x4,0x81,"TNova96"},
+ {HPHW_NPROC,0x300,0x4,0x81,"Bushmaster (710)"},
+ {HPHW_NPROC,0x302,0x4,0x81,"Flounder (705)"},
+ {HPHW_NPROC,0x310,0x4,0x81,"Scorpio (715/50)"},
+ {HPHW_NPROC,0x311,0x4,0x81,"Scorpio Jr.(715/33)"},
+ {HPHW_NPROC,0x312,0x4,0x81,"Strider-50 (715S/50)"},
+ {HPHW_NPROC,0x313,0x4,0x81,"Strider-33 (715S/33)"},
+ {HPHW_NPROC,0x314,0x4,0x81,"Trailways-50 (715T/50)"},
+ {HPHW_NPROC,0x315,0x4,0x81,"Trailways-33 (715T/33)"},
+ {HPHW_NPROC,0x316,0x4,0x81,"Scorpio Sr.(715/75)"},
+ {HPHW_NPROC,0x317,0x4,0x81,"Scorpio 100 (715/100)"},
+ {HPHW_NPROC,0x318,0x4,0x81,"Spectra (725/50)"},
+ {HPHW_NPROC,0x319,0x4,0x81,"Spectra (725/75)"},
+ {HPHW_NPROC,0x320,0x4,0x81,"Spectra (725/100)"},
+ {HPHW_NPROC,0x401,0x4,0x81,"Pace (745i, 747i)"},
+ {HPHW_NPROC,0x402,0x4,0x81,"Sidewinder (742i)"},
+ {HPHW_NPROC,0x403,0x4,0x81,"Fast Pace"},
+ {HPHW_NPROC,0x480,0x4,0x81,"Orville (E23)"},
+ {HPHW_NPROC,0x481,0x4,0x81,"Wilbur (E25)"},
+ {HPHW_NPROC,0x482,0x4,0x81,"WB-80 (E35)"},
+ {HPHW_NPROC,0x483,0x4,0x81,"WB-96 (E45)"},
+ {HPHW_NPROC,0x484,0x4,0x81,"UL Proc L-100 (811/D210,D310)"},
+ {HPHW_NPROC,0x485,0x4,0x81,"UL Proc L-75 (801/D200)"},
+ {HPHW_NPROC,0x501,0x4,0x81,"Merlin L2 132 (9000/778/B132L)"},
+ {HPHW_NPROC,0x502,0x4,0x81,"Merlin L2 160 (9000/778/B160L)"},
+ {HPHW_NPROC,0x503,0x4,0x81,"Merlin L2+ 132 (9000/778/B132L)"},
+ {HPHW_NPROC,0x504,0x4,0x81,"Merlin L2+ 180 (9000/778/B180L)"},
+ {HPHW_NPROC,0x505,0x4,0x81,"Raven L2 132 (9000/778/C132L)"},
+ {HPHW_NPROC,0x506,0x4,0x81,"Raven L2 160 (9000/779/C160L)"},
+ {HPHW_NPROC,0x507,0x4,0x81,"Raven L2 180 (9000/779/C180L)"},
+ {HPHW_NPROC,0x508,0x4,0x81,"Raven L2 160 (9000/779/C160L)"},
+ {HPHW_NPROC,0x509,0x4,0x81,"712/132 L2 Upgrade"},
+ {HPHW_NPROC,0x50A,0x4,0x81,"712/160 L2 Upgrade"},
+ {HPHW_NPROC,0x50B,0x4,0x81,"715/132 L2 Upgrade"},
+ {HPHW_NPROC,0x50C,0x4,0x81,"715/160 L2 Upgrade"},
+ {HPHW_NPROC,0x50D,0x4,0x81,"Rocky2 L2 120"},
+ {HPHW_NPROC,0x50E,0x4,0x81,"Rocky2 L2 150"},
+ {HPHW_NPROC,0x50F,0x4,0x81,"Anole L2 132 (744)"},
+ {HPHW_NPROC,0x510,0x4,0x81,"Anole L2 165 (744)"},
+ {HPHW_NPROC,0x511,0x4,0x81,"Kiji L2 132"},
+ {HPHW_NPROC,0x512,0x4,0x81,"UL L2 132 (803/D220,D320)"},
+ {HPHW_NPROC,0x513,0x4,0x81,"UL L2 160 (813/D220,D320)"},
+ {HPHW_NPROC,0x514,0x4,0x81,"Merlin Jr L2 132"},
+ {HPHW_NPROC,0x515,0x4,0x81,"Staccato L2 132"},
+ {HPHW_NPROC,0x516,0x4,0x81,"Staccato L2 180 (A Class 180)"},
+ {HPHW_NPROC,0x580,0x4,0x81,"KittyHawk DC2-100 (K100)"},
+ {HPHW_NPROC,0x581,0x4,0x91,"KittyHawk DC3-120 (K210)"},
+ {HPHW_NPROC,0x582,0x4,0x91,"KittyHawk DC3 100 (K400)"},
+ {HPHW_NPROC,0x583,0x4,0x91,"KittyHawk DC3 120 (K410)"},
+ {HPHW_NPROC,0x584,0x4,0x91,"LighteningHawk T120"},
+ {HPHW_NPROC,0x585,0x4,0x91,"SkyHawk 100"},
+ {HPHW_NPROC,0x586,0x4,0x91,"SkyHawk 120"},
+ {HPHW_NPROC,0x587,0x4,0x81,"UL Proc 1-way T'120"},
+ {HPHW_NPROC,0x588,0x4,0x91,"UL Proc 2-way T'120"},
+ {HPHW_NPROC,0x589,0x4,0x81,"UL Proc 1-way T'100 (821/D250,D350)"},
+ {HPHW_NPROC,0x58A,0x4,0x91,"UL Proc 2-way T'100 (831/D250,D350)"},
+ {HPHW_NPROC,0x58B,0x4,0x91,"KittyHawk DC2 100 (K200)"},
+ {HPHW_NPROC,0x58C,0x4,0x91,"ThunderHawk DC3- 120 1M (K220)"},
+ {HPHW_NPROC,0x58D,0x4,0x91,"ThunderHawk DC3 120 1M (K420)"},
+ {HPHW_NPROC,0x58E,0x4,0x81,"Raven 120 T'"},
+ {HPHW_NPROC,0x58F,0x4,0x91,"Mohawk 160 U 1M DC3 (K450)"},
+ {HPHW_NPROC,0x590,0x4,0x91,"Mohawk 180 U 1M DC3 (K460)"},
+ {HPHW_NPROC,0x591,0x4,0x91,"Mohawk 200 U 1M DC3"},
+ {HPHW_NPROC,0x592,0x4,0x81,"Raven 100 T'"},
+ {HPHW_NPROC,0x593,0x4,0x91,"FireHawk 160 U"},
+ {HPHW_NPROC,0x594,0x4,0x91,"FireHawk 180 U"},
+ {HPHW_NPROC,0x595,0x4,0x91,"FireHawk 220 U"},
+ {HPHW_NPROC,0x596,0x4,0x91,"FireHawk 240 U"},
+ {HPHW_NPROC,0x597,0x4,0x91,"SPP2000 processor"},
+ {HPHW_NPROC,0x598,0x4,0x81,"Raven U 230 (9000/780/C230)"},
+ {HPHW_NPROC,0x599,0x4,0x81,"Raven U 240 (9000/780/C240)"},
+ {HPHW_NPROC,0x59A,0x4,0x91,"Unlisted but reserved"},
+ {HPHW_NPROC,0x59A,0x4,0x81,"Unlisted but reserved"},
+ {HPHW_NPROC,0x59B,0x4,0x81,"Raven U 160 (9000/780/C160)"},
+ {HPHW_NPROC,0x59C,0x4,0x81,"Raven U 180 (9000/780/C180)"},
+ {HPHW_NPROC,0x59D,0x4,0x81,"Raven U 200 (9000/780/C200)"},
+ {HPHW_NPROC,0x59E,0x4,0x91,"ThunderHawk T' 120"},
+ {HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780)"},
+ {HPHW_NPROC,0x5A0,0x4,0x81,"UL 1w T120 1MB/1MB (841/D260,D360)"},
+ {HPHW_NPROC,0x5A1,0x4,0x91,"UL 2w T120 1MB/1MB (851/D260,D360)"},
+ {HPHW_NPROC,0x5A2,0x4,0x81,"UL 1w U160 512K/512K (861/D270,D370)"},
+ {HPHW_NPROC,0x5A3,0x4,0x91,"UL 2w U160 512K/512K (871/D270,D370)"},
+ {HPHW_NPROC,0x5A4,0x4,0x91,"Mohawk 160 U 1M DC3- (K250)"},
+ {HPHW_NPROC,0x5A5,0x4,0x91,"Mohawk 180 U 1M DC3- (K260)"},
+ {HPHW_NPROC,0x5A6,0x4,0x91,"Mohawk 200 U 1M DC3-"},
+ {HPHW_NPROC,0x5A7,0x4,0x81,"UL proc 1-way U160 1M/1M"},
+ {HPHW_NPROC,0x5A8,0x4,0x91,"UL proc 2-way U160 1M/1M"},
+ {HPHW_NPROC,0x5A9,0x4,0x81,"UL proc 1-way U180 1M/1M"},
+ {HPHW_NPROC,0x5AA,0x4,0x91,"UL proc 2-way U180 1M/1M"},
+ {HPHW_NPROC,0x5AB,0x4,0x91,"Obsolete"},
+ {HPHW_NPROC,0x5AB,0x4,0x81,"Obsolete"},
+ {HPHW_NPROC,0x5AC,0x4,0x91,"Obsolete"},
+ {HPHW_NPROC,0x5AC,0x4,0x81,"Obsolete"},
+ {HPHW_NPROC,0x5AD,0x4,0x91,"BraveHawk 180MHz DC3-"},
+ {HPHW_NPROC,0x5AE,0x4,0x91,"BraveHawk 200MHz DC3- (898/K370)"},
+ {HPHW_NPROC,0x5AF,0x4,0x91,"BraveHawk 220MHz DC3-"},
+ {HPHW_NPROC,0x5B0,0x4,0x91,"BraveHawk 180MHz DC3"},
+ {HPHW_NPROC,0x5B1,0x4,0x91,"BraveHawk 200MHz DC3 (899/K570)"},
+ {HPHW_NPROC,0x5B2,0x4,0x91,"BraveHawk 220MHz DC3"},
+ {HPHW_NPROC,0x5B3,0x4,0x91,"FireHawk 200"},
+ {HPHW_NPROC,0x5B4,0x4,0x91,"SPP2500"},
+ {HPHW_NPROC,0x5B5,0x4,0x91,"SummitHawk U+"},
+ {HPHW_NPROC,0x5B6,0x4,0x91,"DragonHawk U+ 240 DC3"},
+ {HPHW_NPROC,0x5B7,0x4,0x91,"DragonHawk U+ 240 DC3-"},
+ {HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"},
+ {HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"},
+ {HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"},
+ {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W"},
+ {HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"},
+ {HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"},
+ {HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"},
+ {HPHW_NPROC,0x5BF,0x4,0x91,"Forte W 4-way"},
+ {HPHW_NPROC,0x5C0,0x4,0x91,"M2250"},
+ {HPHW_NPROC,0x5C1,0x4,0x91,"M2500"},
+ {HPHW_NPROC,0x5C2,0x4,0x91,"Sonata 440"},
+ {HPHW_NPROC,0x5C3,0x4,0x91,"Sonata 360"},
+ {HPHW_NPROC,0x5C4,0x4,0x91,"Rhapsody 440"},
+ {HPHW_NPROC,0x5C5,0x4,0x91,"Rhapsody 360"},
+ {HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780)"},
+ {HPHW_NPROC,0x5C7,0x4,0x91,"Halfdome W 440"},
+ {HPHW_NPROC,0x5C8,0x4,0x81,"Lego 360 processor"},
+ {HPHW_NPROC,0x5C9,0x4,0x91,"Rhapsody DC- 440"},
+ {HPHW_NPROC,0x5CA,0x4,0x91,"Rhapsody DC- 360"},
+ {HPHW_NPROC,0x5CB,0x4,0x91,"Crescendo 440"},
+ {HPHW_NPROC,0x5CC,0x4,0x91,"Prelude W 440"},
+ {HPHW_NPROC,0x5CD,0x4,0x91,"SPP2600"},
+ {HPHW_NPROC,0x5CE,0x4,0x91,"M2600"},
+ {HPHW_NPROC,0x5CF,0x4,0x81,"Allegro W+"},
+ {HPHW_NPROC,0x5D0,0x4,0x81,"Kazoo W+"},
+ {HPHW_NPROC,0x5D1,0x4,0x91,"Forte W+ 2w"},
+ {HPHW_NPROC,0x5D2,0x4,0x91,"Forte W+ 4w"},
+ {HPHW_NPROC,0x5D3,0x4,0x91,"Prelude W+ 540"},
+ {HPHW_NPROC,0x5D4,0x4,0x91,"Duet W+"},
+ {HPHW_NPROC,0x5D5,0x4,0x91,"Crescendo 550"},
+ {HPHW_NPROC,0x5D6,0x4,0x81,"Crescendo DC- 440"},
+ {HPHW_NPROC,0x5D7,0x4,0x91,"Keystone W+"},
+ {HPHW_NPROC,0x5D8,0x4,0x91,"Rhapsody wave 2 W+ DC-"},
+ {HPHW_NPROC,0x5D9,0x4,0x91,"Rhapsody wave 2 W+"},
+ {HPHW_NPROC,0x5DA,0x4,0x91,"Marcato W+ DC-"},
+ {HPHW_NPROC,0x5DB,0x4,0x91,"Marcato W+"},
+ {HPHW_NPROC,0x5DC,0x4,0x91,"Allegro W2"},
+ {HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"},
+ {HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"},
+ {HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"},
+ {HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"},
+ {HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"},
+ {HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"},
+ {HPHW_NPROC,0x5E3,0x4,0x91,"Crescendo 750 W2"},
+ {HPHW_NPROC,0x5E4,0x4,0x91,"Keystone/Matterhorn W2 750"},
+ {HPHW_NPROC,0x5E5,0x4,0x91,"PowerBar W+"},
+ {HPHW_NPROC,0x5E6,0x4,0x91,"Keystone/Matterhorn W2 650"},
+ {HPHW_NPROC,0x5E7,0x4,0x91,"Caribe W2 800"},
+ {HPHW_NPROC,0x5E8,0x4,0x91,"Pikes Peak W2"},
+ {HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"},
+ {HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"},
+ {HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"},
+ {HPHW_NPROC,0x602,0x4,0x81,"Gecko 100 (712/100)"},
+ {HPHW_NPROC,0x603,0x4,0x81,"Anole 64 (743/64)"},
+ {HPHW_NPROC,0x604,0x4,0x81,"Anole 100 (743/100)"},
+ {HPHW_NPROC,0x605,0x4,0x81,"Gecko 120 (712/120)"},
+ {HPHW_NPROC,0x606,0x4,0x81,"Gila 80"},
+ {HPHW_NPROC,0x607,0x4,0x81,"Gila 100"},
+ {HPHW_NPROC,0x608,0x4,0x81,"Gila 120"},
+ {HPHW_NPROC,0x609,0x4,0x81,"Scorpio-L 80"},
+ {HPHW_NPROC,0x60A,0x4,0x81,"Mirage Jr (715/64)"},
+ {HPHW_NPROC,0x60B,0x4,0x81,"Mirage 100"},
+ {HPHW_NPROC,0x60C,0x4,0x81,"Mirage 100+"},
+ {HPHW_NPROC,0x60D,0x4,0x81,"Electra 100"},
+ {HPHW_NPROC,0x60E,0x4,0x81,"Electra 120"},
+ {HPHW_NPROC,0x610,0x4,0x81,"Scorpio-L 100"},
+ {HPHW_NPROC,0x611,0x4,0x81,"Scorpio-L 120"},
+ {HPHW_NPROC,0x612,0x4,0x81,"Spectra-L 80"},
+ {HPHW_NPROC,0x613,0x4,0x81,"Spectra-L 100"},
+ {HPHW_NPROC,0x614,0x4,0x81,"Spectra-L 120"},
+ {HPHW_NPROC,0x615,0x4,0x81,"Piranha 100"},
+ {HPHW_NPROC,0x616,0x4,0x81,"Piranha 120"},
+ {HPHW_NPROC,0x617,0x4,0x81,"Jason 50"},
+ {HPHW_NPROC,0x618,0x4,0x81,"Jason 100"},
+ {HPHW_NPROC,0x619,0x4,0x81,"Mirage 80"},
+ {HPHW_NPROC,0x61A,0x4,0x81,"SAIC L-80"},
+ {HPHW_NPROC,0x61B,0x4,0x81,"Rocky1 L-60"},
+ {HPHW_NPROC,0x61C,0x4,0x81,"Anole T (743/T)"},
+ {HPHW_NPROC,0x67E,0x4,0x81,"Hitachi Tiny 80"},
+ {HPHW_NPROC,0x67F,0x4,0x81,"Hitachi Tiny 64"},
+ {HPHW_NPROC,0x700,0x4,0x91,"NEC Aska Processor"},
+ {HPHW_NPROC,0x880,0x4,0x91,"Orca Mako"},
+ {HPHW_NPROC,0x881,0x4,0x91,"Everest Mako"},
+ {HPHW_NPROC,0x882,0x4,0x91,"Rainier/Medel Mako Slow"},
+ {HPHW_NPROC,0x883,0x4,0x91,"Rainier/Medel Mako Fast"},
+ {HPHW_NPROC,0x884,0x4,0x91,"Mt. Hamilton"},
+ {HPHW_NPROC,0x885,0x4,0x91,"Mt. Hamilton DC-"},
+ {HPHW_NPROC,0x886,0x4,0x91,"Storm Peak Slow DC-"},
+ {HPHW_NPROC,0x887,0x4,0x91,"Storm Peak Slow"},
+ {HPHW_NPROC,0x888,0x4,0x91,"Storm Peak Fast DC-"},
+ {HPHW_NPROC,0x889,0x4,0x91,"Storm Peak Fast"},
+ {HPHW_NPROC,0x88A,0x4,0x91,"Crestone Peak"},
+ {HPHW_A_DIRECT, 0x004, 0x0000D, 0x00, "Arrakis MUX"},
+ {HPHW_A_DIRECT, 0x005, 0x0000D, 0x00, "Dyun Kiuh MUX"},
+ {HPHW_A_DIRECT, 0x006, 0x0000D, 0x00, "Baat Kiuh AP/MUX (40299B)"},
+ {HPHW_A_DIRECT, 0x007, 0x0000D, 0x00, "Dino AP"},
+ {HPHW_A_DIRECT, 0x009, 0x0000D, 0x00, "Solaris Direct Connect MUX (J2092A)"},
+ {HPHW_A_DIRECT, 0x00A, 0x0000D, 0x00, "Solaris RS-422/423 MUX (J2093A)"},
+ {HPHW_A_DIRECT, 0x00B, 0x0000D, 0x00, "Solaris RS-422/423 Quadriloops MUX"},
+ {HPHW_A_DIRECT, 0x00C, 0x0000D, 0x00, "Solaris Modem MUX (J2094A)"},
+ {HPHW_A_DIRECT, 0x00D, 0x0000D, 0x00, "Twins Direct Connect MUX"},
+ {HPHW_A_DIRECT, 0x00E, 0x0000D, 0x00, "Twins Modem MUX"},
+ {HPHW_A_DIRECT, 0x00F, 0x0000D, 0x00, "Nautilus RS-485"},
+ {HPHW_A_DIRECT, 0x010, 0x0000D, 0x00, "UltraLight CAP/MUX"},
+ {HPHW_A_DIRECT, 0x015, 0x0000D, 0x00, "Eole CAP/MUX"},
+ {HPHW_A_DIRECT, 0x024, 0x0000D, 0x00, "Sahp Kiuh AP/MUX"},
+ {HPHW_A_DIRECT, 0x034, 0x0000D, 0x00, "Sahp Kiuh Low AP/MUX"},
+ {HPHW_A_DIRECT, 0x044, 0x0000D, 0x00, "Sahp Baat Kiuh AP/MUX"},
+ {HPHW_A_DIRECT, 0x004, 0x0000E, 0x80, "Burgundy RS-232"},
+ {HPHW_A_DIRECT, 0x005, 0x0000E, 0x80, "Silverfox RS-232"},
+ {HPHW_A_DIRECT, 0x006, 0x0000E, 0x80, "Lego RS-232"},
+ {HPHW_A_DIRECT, 0x004, 0x0000F, 0x00, "Peacock Graphics"},
+ {HPHW_A_DIRECT, 0x004, 0x00014, 0x80, "Burgundy HIL"},
+ {HPHW_A_DIRECT, 0x005, 0x00014, 0x80, "Peacock HIL"},
+ {HPHW_A_DIRECT, 0x004, 0x00015, 0x80, "Leonardo"},
+ {HPHW_A_DIRECT, 0x004, 0x00016, 0x80, "HP-PB HRM"},
+ {HPHW_A_DIRECT, 0x004, 0x00017, 0x80, "HP-PB HRC"},
+ {HPHW_A_DIRECT, 0x004, 0x0003A, 0x80, "Skunk Centronics (28655A)"},
+ {HPHW_A_DIRECT, 0x024, 0x0003A, 0x80, "Sahp Kiuh Centronics"},
+ {HPHW_A_DIRECT, 0x044, 0x0003A, 0x80, "Sahp Baat Kiuh Centronics"},
+ {HPHW_A_DIRECT, 0x004, 0x0004E, 0x80, "AT&T DataKit (AMSO)"},
+ {HPHW_A_DIRECT, 0x004, 0x0009B, 0x80, "Test&Meas GSC HPIB"},
+ {HPHW_A_DIRECT, 0x004, 0x000A8, 0x00, "Rocky2-120 Front Keyboard"},
+ {HPHW_A_DIRECT, 0x005, 0x000A8, 0x00, "Rocky2-150 Front Keyboard"},
+ {HPHW_A_DIRECT, 0x004, 0x00101, 0x80, "Hitachi Console Module"},
+ {HPHW_A_DIRECT, 0x004, 0x00102, 0x80, "Hitachi Boot Module"},
+ {HPHW_A_DIRECT, 0x004, 0x00203, 0x80, "MELCO HBMLA MLAIT"},
+ {HPHW_A_DIRECT, 0x004, 0x00208, 0x80, "MELCO HBDPC"},
+ {HPHW_A_DIRECT, 0x004, 0x00300, 0x00, "DCI TWINAX TERM IO MUX"},
+ {HPHW_A_DMA, 0x004, 0x00039, 0x80, "Skunk SCSI (28655A)"},
+ {HPHW_A_DMA, 0x005, 0x00039, 0x80, "KittyHawk CSY Core SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00039, 0x80, "Diablo SCSI"},
+ {HPHW_A_DMA, 0x024, 0x00039, 0x80, "Sahp Kiuh SCSI"},
+ {HPHW_A_DMA, 0x034, 0x00039, 0x80, "Sahp Kiuh Low SCSI"},
+ {HPHW_A_DMA, 0x044, 0x00039, 0x80, "Sahp Baat Kiuh SCSI"},
+ {HPHW_A_DMA, 0x004, 0x0003B, 0x80, "Wizard SCSI"},
+ {HPHW_A_DMA, 0x005, 0x0003B, 0x80, "KittyHawk CSY Core FW-SCSI"},
+ {HPHW_A_DMA, 0x006, 0x0003B, 0x80, "Symbios EPIC FW-SCSI"},
+ {HPHW_A_DMA, 0x004, 0x00040, 0x80, "HP-PB Shazam HPIB (28650A)"},
+ {HPHW_A_DMA, 0x005, 0x00040, 0x80, "Burgundy HPIB"},
+ {HPHW_A_DMA, 0x004, 0x00041, 0x80, "HP-PB HP-FL"},
+ {HPHW_A_DMA, 0x004, 0x00042, 0x80, "HP-PB LoQuix HPIB (28650B)"},
+ {HPHW_A_DMA, 0x004, 0x00043, 0x80, "HP-PB Crypt LoQuix"},
+ {HPHW_A_DMA, 0x004, 0x00044, 0x80, "HP-PB Shazam GPIO (28651A)"},
+ {HPHW_A_DMA, 0x004, 0x00045, 0x80, "HP-PB LoQuix GPIO"},
+ {HPHW_A_DMA, 0x004, 0x00046, 0x80, "2-Port X.25 NIO_ACC (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x00047, 0x80, "4-Port X.25 NIO_ACC (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x0004B, 0x80, "LGB Control"},
+ {HPHW_A_DMA, 0x004, 0x0004C, 0x80, "Martian RTI (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x0004D, 0x80, "ACC Mux (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x00050, 0x80, "Lanbrusca 802.3 (36967A)"},
+ {HPHW_A_DMA, 0x004, 0x00056, 0x80, "HP-PB LoQuix FDDI"},
+ {HPHW_A_DMA, 0x004, 0x00057, 0x80, "HP-PB LoQuix FDDI (28670A)"},
+ {HPHW_A_DMA, 0x004, 0x0005E, 0x00, "Gecko Add-on Token Ring"},
+ {HPHW_A_DMA, 0x012, 0x00089, 0x80, "Barracuda Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x013, 0x00089, 0x80, "Bluefish Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00089, 0x80, "Shrike Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x015, 0x00089, 0x80, "KittyHawk GSY Core FW-SCSI"},
+ {HPHW_A_DMA, 0x017, 0x00089, 0x80, "Shrike Jade Add-on FW-SCSI (A3644A)"},
+ {HPHW_A_DMA, 0x01F, 0x00089, 0x80, "SkyHawk 100/120 FW-SCSI"},
+ {HPHW_A_DMA, 0x027, 0x00089, 0x80, "Piranha 100 FW-SCSI"},
+ {HPHW_A_DMA, 0x032, 0x00089, 0x80, "Raven T' Core FW-SCSI"},
+ {HPHW_A_DMA, 0x03B, 0x00089, 0x80, "Raven U/L2 Core FW-SCSI"},
+ {HPHW_A_DMA, 0x03C, 0x00089, 0x80, "Merlin 132 Core FW-SCSI"},
+ {HPHW_A_DMA, 0x03D, 0x00089, 0x80, "Merlin 160 Core FW-SCSI"},
+ {HPHW_A_DMA, 0x044, 0x00089, 0x80, "Mohawk Core FW-SCSI"},
+ {HPHW_A_DMA, 0x051, 0x00089, 0x80, "Firehawk FW-SCSI"},
+ {HPHW_A_DMA, 0x058, 0x00089, 0x80, "FireHawk 200 FW-SCSI"},
+ {HPHW_A_DMA, 0x05C, 0x00089, 0x80, "SummitHawk 230 Ultra-SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00091, 0x80, "Baby Hugo Add-on Net FC (A3406A)"},
+ {HPHW_A_DMA, 0x020, 0x00091, 0x80, "Baby Jade Add-on Net FC (A3638A)"},
+ {HPHW_A_DMA, 0x004, 0x00092, 0x80, "GSC+ YLIASTER ATM"},
+ {HPHW_A_DMA, 0x004, 0x00095, 0x80, "Hamlyn GSC+ Network Card"},
+ {HPHW_A_DMA, 0x004, 0x00098, 0x80, "Lo-fat Emulator"},
+ {HPHW_A_DMA, 0x004, 0x0009A, 0x80, "GSC+ Venus ATM"},
+ {HPHW_A_DMA, 0x005, 0x0009A, 0x80, "GSC+ Samorobrive ATM"},
+ {HPHW_A_DMA, 0x004, 0x0009D, 0x80, "HP HSC-PCI Cards"},
+ {HPHW_A_DMA, 0x004, 0x0009E, 0x80, "Alaxis GSC+ 155Mb ATM"},
+ {HPHW_A_DMA, 0x005, 0x0009E, 0x80, "Alaxis GSC+ 622Mb ATM"},
+ {HPHW_A_DMA, 0x05C, 0x0009F, 0x80, "SummitHawk 230 USB"},
+ {HPHW_A_DMA, 0x05C, 0x000A0, 0x80, "SummitHawk 230 100BaseT"},
+ {HPHW_A_DMA, 0x015, 0x000A7, 0x80, "Baby Hugo Add-on mass FC (A3404A)"},
+ {HPHW_A_DMA, 0x018, 0x000A7, 0x80, "Mombasa GS Add-on mass FC (A3591)"},
+ {HPHW_A_DMA, 0x021, 0x000A7, 0x80, "Baby Jade Add-on mass FC (A3636A)"},
+ {HPHW_A_DMA, 0x004, 0x00201, 0x80, "MELCO HCMAP"},
+ {HPHW_A_DMA, 0x004, 0x00202, 0x80, "MELCO HBMLA MLAMA"},
+ {HPHW_A_DMA, 0x004, 0x00205, 0x80, "MELCO HBRFU"},
+ {HPHW_A_DMA, 0x004, 0x00380, 0x80, "Interphase NIO-FC"},
+ {HPHW_A_DMA, 0x004, 0x00381, 0x80, "Interphase NIO-ATM"},
+ {HPHW_A_DMA, 0x004, 0x00382, 0x80, "Interphase NIO-100BaseTX"},
+ {HPHW_BA, 0x004, 0x00070, 0x0, "Cobra Core BA"},
+ {HPHW_BA, 0x005, 0x00070, 0x0, "Coral Core BA"},
+ {HPHW_BA, 0x006, 0x00070, 0x0, "Bushmaster Core BA"},
+ {HPHW_BA, 0x007, 0x00070, 0x0, "Scorpio Core BA"},
+ {HPHW_BA, 0x008, 0x00070, 0x0, "Flounder Core BA"},
+ {HPHW_BA, 0x009, 0x00070, 0x0, "Outfield Core BA"},
+ {HPHW_BA, 0x00A, 0x00070, 0x0, "CoralII Core BA"},
+ {HPHW_BA, 0x00B, 0x00070, 0x0, "Scorpio Jr. Core BA"},
+ {HPHW_BA, 0x00C, 0x00070, 0x0, "Strider-50 Core BA"},
+ {HPHW_BA, 0x00D, 0x00070, 0x0, "Strider-33 Core BA"},
+ {HPHW_BA, 0x00E, 0x00070, 0x0, "Trailways-50 Core BA"},
+ {HPHW_BA, 0x00F, 0x00070, 0x0, "Trailways-33 Core BA"},
+ {HPHW_BA, 0x010, 0x00070, 0x0, "Pace Core BA"},
+ {HPHW_BA, 0x011, 0x00070, 0x0, "Sidewinder Core BA"},
+ {HPHW_BA, 0x019, 0x00070, 0x0, "Scorpio Sr. Core BA"},
+ {HPHW_BA, 0x020, 0x00070, 0x0, "Scorpio 100 Core BA"},
+ {HPHW_BA, 0x021, 0x00070, 0x0, "Spectra 50 Core BA"},
+ {HPHW_BA, 0x022, 0x00070, 0x0, "Spectra 75 Core BA"},
+ {HPHW_BA, 0x023, 0x00070, 0x0, "Spectra 100 Core BA"},
+ {HPHW_BA, 0x024, 0x00070, 0x0, "Fast Pace Core BA"},
+ {HPHW_BA, 0x026, 0x00070, 0x0, "CoralII Jaguar Core BA"},
+ {HPHW_BA, 0x004, 0x00076, 0x0, "Cobra EISA BA"},
+ {HPHW_BA, 0x005, 0x00076, 0x0, "Coral EISA BA"},
+ {HPHW_BA, 0x007, 0x00076, 0x0, "Scorpio EISA BA"},
+ {HPHW_BA, 0x00A, 0x00076, 0x0, "CoralII EISA BA"},
+ {HPHW_BA, 0x00B, 0x00076, 0x0, "Scorpio Jr. EISA BA"},
+ {HPHW_BA, 0x00C, 0x00076, 0x0, "Strider-50 Core EISA"},
+ {HPHW_BA, 0x00D, 0x00076, 0x0, "Strider-33 Core EISA"},
+ {HPHW_BA, 0x00E, 0x00076, 0x0, "Trailways-50 Core EISA"},
+ {HPHW_BA, 0x00F, 0x00076, 0x0, "Trailways-33 Core EISA"},
+ {HPHW_BA, 0x010, 0x00076, 0x0, "Pace Core EISA"},
+ {HPHW_BA, 0x019, 0x00076, 0x0, "Scorpio Sr. EISA BA"},
+ {HPHW_BA, 0x020, 0x00076, 0x0, "Scorpio 100 EISA BA"},
+ {HPHW_BA, 0x021, 0x00076, 0x0, "Spectra 50 EISA BA"},
+ {HPHW_BA, 0x022, 0x00076, 0x0, "Spectra 75 EISA BA"},
+ {HPHW_BA, 0x023, 0x00076, 0x0, "Spectra 100 EISA BA"},
+ {HPHW_BA, 0x026, 0x00076, 0x0, "CoralII Jaguar EISA BA"},
+ {HPHW_BA, 0x010, 0x00078, 0x0, "Pace VME BA"},
+ {HPHW_BA, 0x011, 0x00078, 0x0, "Sidewinder VME BA"},
+ {HPHW_BA, 0x01A, 0x00078, 0x0, "Anole 64 VME BA"},
+ {HPHW_BA, 0x01B, 0x00078, 0x0, "Anole 100 VME BA"},
+ {HPHW_BA, 0x024, 0x00078, 0x0, "Fast Pace VME BA"},
+ {HPHW_BA, 0x034, 0x00078, 0x0, "Anole T VME BA"},
+ {HPHW_BA, 0x04A, 0x00078, 0x0, "Anole L2 132 VME BA"},
+ {HPHW_BA, 0x04C, 0x00078, 0x0, "Anole L2 165 VME BA"},
+ {HPHW_BA, 0x011, 0x00081, 0x0, "WB-96 Core BA"},
+ {HPHW_BA, 0x012, 0x00081, 0x0, "Orville UX Core BA"},
+ {HPHW_BA, 0x013, 0x00081, 0x0, "Wilbur UX Core BA"},
+ {HPHW_BA, 0x014, 0x00081, 0x0, "WB-80 Core BA"},
+ {HPHW_BA, 0x015, 0x00081, 0x0, "KittyHawk GSY Core BA"},
+ {HPHW_BA, 0x016, 0x00081, 0x0, "Gecko Core BA"},
+ {HPHW_BA, 0x018, 0x00081, 0x0, "Gecko Optional BA"},
+ {HPHW_BA, 0x01A, 0x00081, 0x0, "Anole 64 Core BA"},
+ {HPHW_BA, 0x01B, 0x00081, 0x0, "Anole 100 Core BA"},
+ {HPHW_BA, 0x01C, 0x00081, 0x0, "Gecko 80 Core BA"},
+ {HPHW_BA, 0x01D, 0x00081, 0x0, "Gecko 100 Core BA"},
+ {HPHW_BA, 0x01F, 0x00081, 0x0, "SkyHawk 100/120 Core BA"},
+ {HPHW_BA, 0x027, 0x00081, 0x0, "Piranha 100 Core BA"},
+ {HPHW_BA, 0x028, 0x00081, 0x0, "Mirage Jr Core BA"},
+ {HPHW_BA, 0x029, 0x00081, 0x0, "Mirage Core BA"},
+ {HPHW_BA, 0x02A, 0x00081, 0x0, "Electra Core BA"},
+ {HPHW_BA, 0x02B, 0x00081, 0x0, "Mirage 80 Core BA"},
+ {HPHW_BA, 0x02C, 0x00081, 0x0, "Mirage 100+ Core BA"},
+ {HPHW_BA, 0x02E, 0x00081, 0x0, "UL 350 Lasi Core BA"},
+ {HPHW_BA, 0x02F, 0x00081, 0x0, "UL 550 Lasi Core BA"},
+ {HPHW_BA, 0x032, 0x00081, 0x0, "Raven T' Core BA"},
+ {HPHW_BA, 0x033, 0x00081, 0x0, "Anole T Core BA"},
+ {HPHW_BA, 0x034, 0x00081, 0x0, "SAIC L-80 Core BA"},
+ {HPHW_BA, 0x035, 0x00081, 0x0, "PCX-L2 712/132 Core BA"},
+ {HPHW_BA, 0x036, 0x00081, 0x0, "PCX-L2 712/160 Core BA"},
+ {HPHW_BA, 0x03B, 0x00081, 0x0, "Raven U/L2 Core BA"},
+ {HPHW_BA, 0x03C, 0x00081, 0x0, "Merlin 132 Core BA"},
+ {HPHW_BA, 0x03D, 0x00081, 0x0, "Merlin 160 Core BA"},
+ {HPHW_BA, 0x03E, 0x00081, 0x0, "Merlin+ 132 Core BA"},
+ {HPHW_BA, 0x03F, 0x00081, 0x0, "Merlin+ 180 Core BA"},
+ {HPHW_BA, 0x044, 0x00081, 0x0, "Mohawk Core BA"},
+ {HPHW_BA, 0x045, 0x00081, 0x0, "Rocky1 Core BA"},
+ {HPHW_BA, 0x046, 0x00081, 0x0, "Rocky2 120 Core BA"},
+ {HPHW_BA, 0x047, 0x00081, 0x0, "Rocky2 150 Core BA"},
+ {HPHW_BA, 0x04B, 0x00081, 0x0, "Anole L2 132 Core BA"},
+ {HPHW_BA, 0x04D, 0x00081, 0x0, "Anole L2 165 Core BA"},
+ {HPHW_BA, 0x04E, 0x00081, 0x0, "Kiji L2 132 Core BA"},
+ {HPHW_BA, 0x050, 0x00081, 0x0, "Merlin Jr 132 Core BA"},
+ {HPHW_BA, 0x051, 0x00081, 0x0, "Firehawk Core BA"},
+ {HPHW_BA, 0x056, 0x00081, 0x0, "Raven+ w SE FWSCSI Core BA"},
+ {HPHW_BA, 0x057, 0x00081, 0x0, "Raven+ w Diff FWSCSI Core BA"},
+ {HPHW_BA, 0x058, 0x00081, 0x0, "FireHawk 200 Core BA"},
+ {HPHW_BA, 0x05C, 0x00081, 0x0, "SummitHawk 230 Core BA"},
+ {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 132 Core BA"},
+ {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 180 Core BA"},
+ {HPHW_BA, 0x05F, 0x00081, 0x0, "Staccato 180 Lasi"},
+ {HPHW_BA, 0x800, 0x00081, 0x0, "Hitachi Tiny 64 Core BA"},
+ {HPHW_BA, 0x801, 0x00081, 0x0, "Hitachi Tiny 80 Core BA"},
+ {HPHW_BA, 0x004, 0x0008B, 0x0, "Anole Optional PCMCIA BA"},
+ {HPHW_BA, 0x004, 0x0008E, 0x0, "GSC ITR Wax BA"},
+ {HPHW_BA, 0x00C, 0x0008E, 0x0, "Gecko Optional Wax BA"},
+ {HPHW_BA, 0x010, 0x0008E, 0x0, "Pace Wax BA"},
+ {HPHW_BA, 0x011, 0x0008E, 0x0, "SuperPace Wax BA"},
+ {HPHW_BA, 0x012, 0x0008E, 0x0, "Mirage Jr Wax BA"},
+ {HPHW_BA, 0x013, 0x0008E, 0x0, "Mirage Wax BA"},
+ {HPHW_BA, 0x014, 0x0008E, 0x0, "Electra Wax BA"},
+ {HPHW_BA, 0x017, 0x0008E, 0x0, "Raven Backplane Wax BA"},
+ {HPHW_BA, 0x01E, 0x0008E, 0x0, "Raven T' Wax BA"},
+ {HPHW_BA, 0x01F, 0x0008E, 0x0, "SkyHawk Wax BA"},
+ {HPHW_BA, 0x023, 0x0008E, 0x0, "Rocky1 Wax BA"},
+ {HPHW_BA, 0x02B, 0x0008E, 0x0, "Mirage 80 Wax BA"},
+ {HPHW_BA, 0x02C, 0x0008E, 0x0, "Mirage 100+ Wax BA"},
+ {HPHW_BA, 0x030, 0x0008E, 0x0, "UL 350 Core Wax BA"},
+ {HPHW_BA, 0x031, 0x0008E, 0x0, "UL 550 Core Wax BA"},
+ {HPHW_BA, 0x034, 0x0008E, 0x0, "SAIC L-80 Wax BA"},
+ {HPHW_BA, 0x03A, 0x0008E, 0x0, "Merlin+ Wax BA"},
+ {HPHW_BA, 0x040, 0x0008E, 0x0, "Merlin 132 Wax BA"},
+ {HPHW_BA, 0x041, 0x0008E, 0x0, "Merlin 160 Wax BA"},
+ {HPHW_BA, 0x043, 0x0008E, 0x0, "Merlin 132/160 Wax BA"},
+ {HPHW_BA, 0x052, 0x0008E, 0x0, "Raven+ Hi Power Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x054, 0x0008E, 0x0, "Raven+ Lo Power Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x059, 0x0008E, 0x0, "FireHawk 200 Wax BA"},
+ {HPHW_BA, 0x05A, 0x0008E, 0x0, "Raven+ L2 Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x05D, 0x0008E, 0x0, "SummitHawk Wax BA"},
+ {HPHW_BA, 0x800, 0x0008E, 0x0, "Hitachi Tiny 64 Wax BA"},
+ {HPHW_BA, 0x801, 0x0008E, 0x0, "Hitachi Tiny 80 Wax BA"},
+ {HPHW_BA, 0x011, 0x00090, 0x0, "SuperPace Wax EISA BA"},
+ {HPHW_BA, 0x017, 0x00090, 0x0, "Raven Backplane Wax EISA BA"},
+ {HPHW_BA, 0x01E, 0x00090, 0x0, "Raven T' Wax EISA BA"},
+ {HPHW_BA, 0x01F, 0x00090, 0x0, "SkyHawk 100/120 Wax EISA BA"},
+ {HPHW_BA, 0x027, 0x00090, 0x0, "Piranha 100 Wax EISA BA"},
+ {HPHW_BA, 0x028, 0x00090, 0x0, "Mirage Jr Wax EISA BA"},
+ {HPHW_BA, 0x029, 0x00090, 0x0, "Mirage Wax EISA BA"},
+ {HPHW_BA, 0x02A, 0x00090, 0x0, "Electra Wax EISA BA"},
+ {HPHW_BA, 0x02B, 0x00090, 0x0, "Mirage 80 Wax EISA BA"},
+ {HPHW_BA, 0x02C, 0x00090, 0x0, "Mirage 100+ Wax EISA BA"},
+ {HPHW_BA, 0x030, 0x00090, 0x0, "UL 350 Wax EISA BA"},
+ {HPHW_BA, 0x031, 0x00090, 0x0, "UL 550 Wax EISA BA"},
+ {HPHW_BA, 0x034, 0x00090, 0x0, "SAIC L-80 Wax EISA BA"},
+ {HPHW_BA, 0x03A, 0x00090, 0x0, "Merlin+ Wax EISA BA"},
+ {HPHW_BA, 0x040, 0x00090, 0x0, "Merlin 132 Wax EISA BA"},
+ {HPHW_BA, 0x041, 0x00090, 0x0, "Merlin 160 Wax EISA BA"},
+ {HPHW_BA, 0x043, 0x00090, 0x0, "Merlin 132/160 Wax EISA BA"},
+ {HPHW_BA, 0x052, 0x00090, 0x0, "Raven Hi Power Backplane Wax EISA BA"},
+ {HPHW_BA, 0x054, 0x00090, 0x0, "Raven Lo Power Backplane Wax EISA BA"},
+ {HPHW_BA, 0x059, 0x00090, 0x0, "FireHawk 200 Wax EISA BA"},
+ {HPHW_BA, 0x05A, 0x00090, 0x0, "Raven L2 Backplane Wax EISA BA"},
+ {HPHW_BA, 0x05D, 0x00090, 0x0, "SummitHawk Wax EISA BA"},
+ {HPHW_BA, 0x800, 0x00090, 0x0, "Hitachi Tiny 64 Wax EISA BA"},
+ {HPHW_BA, 0x801, 0x00090, 0x0, "Hitachi Tiny 80 Wax EISA BA"},
+ {HPHW_BA, 0x01A, 0x00093, 0x0, "Anole 64 TIMI BA"},
+ {HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 100 TIMI BA"},
+ {HPHW_BA, 0x034, 0x00093, 0x0, "Anole T TIMI BA"},
+ {HPHW_BA, 0x04A, 0x00093, 0x0, "Anole L2 132 TIMI BA"},
+ {HPHW_BA, 0x04C, 0x00093, 0x0, "Anole L2 165 TIMI BA"},
+ {HPHW_BA, 0x582, 0x000A5, 0x00, "Epic PCI Bridge"},
+ {HPHW_BCPORT, 0x504, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"},
+ {HPHW_BCPORT, 0x505, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"},
+ {HPHW_BCPORT, 0x503, 0x0000C, 0x00, "Java BC GSC+ Port"},
+ {HPHW_BCPORT, 0x57F, 0x0000C, 0x00, "Hitachi Ghostview GSC+ Port"},
+ {HPHW_BCPORT, 0x501, 0x0000C, 0x00, "U2-IOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x502, 0x0000C, 0x00, "Uturn-IOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x780, 0x0000C, 0x00, "Astro BC Ropes Port"},
+ {HPHW_BCPORT, 0x506, 0x0000C, 0x00, "NEC-IOS BC HSC Port"},
+ {HPHW_BCPORT, 0x004, 0x0000C, 0x00, "Cheetah BC SMB Port"},
+ {HPHW_BCPORT, 0x006, 0x0000C, 0x00, "Cheetah BC MID_BUS Port"},
+ {HPHW_BCPORT, 0x005, 0x0000C, 0x00, "Condor BC MID_BUS Port"},
+ {HPHW_BCPORT, 0x100, 0x0000C, 0x00, "Condor BC HP-PB Port"},
+ {HPHW_BCPORT, 0x184, 0x0000C, 0x00, "Summit BC Port"},
+ {HPHW_BCPORT, 0x101, 0x0000C, 0x00, "Summit BC HP-PB Port"},
+ {HPHW_BCPORT, 0x102, 0x0000C, 0x00, "HP-PB Port (prefetch)"},
+ {HPHW_BCPORT, 0x500, 0x0000C, 0x00, "Gecko BOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x103, 0x0000C, 0x00, "Gecko BOA BC HP-PB Port"},
+ {HPHW_BCPORT, 0x507, 0x0000C, 0x00, "Keyaki BC GSC+ Port"},
+ {HPHW_BCPORT, 0x508, 0x0000C, 0x00, "Keyaki-DX BC GSC+ Port"},
+ {HPHW_BCPORT, 0x584, 0x0000C, 0x10, "DEW BC Runway Port"},
+ {HPHW_BCPORT, 0x800, 0x0000C, 0x10, "DEW BC Merced Port"},
+ {HPHW_BCPORT, 0x801, 0x0000C, 0x10, "SMC Bus Interface Merced Bus0"},
+ {HPHW_BCPORT, 0x802, 0x0000C, 0x10, "SMC Bus INterface Merced Bus1"},
+ {HPHW_BCPORT, 0x803, 0x0000C, 0x10, "IKE I/O BC Merced Port"},
+ {HPHW_BCPORT, 0x781, 0x0000C, 0x00, "IKE I/O BC Ropes Port"},
+ {HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O BC Merced Port"},
+ {HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O BC Ropes Port"},
+ {HPHW_BCPORT, 0x784, 0x0000C, 0x00, "Pluto I/O BC Ropes Port"},
+ {HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"},
+ {HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"},
+ {HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"},
+ {HPHW_BRIDGE, 0x583, 0x000A5, 0x00, "Saga PCI Bridge"},
+ {HPHW_BRIDGE, 0x783, 0x0000A, 0x00, "Mercury PCI Bridge"},
+ {HPHW_BRIDGE, 0x784, 0x0000A, 0x00, "Quicksilver AGP Bridge"},
+ {HPHW_B_DMA, 0x004, 0x00018, 0x00, "Parallel I/O"},
+ {HPHW_B_DMA, 0x004, 0x00019, 0x00, "Parallel RDB"},
+ {HPHW_B_DMA, 0x004, 0x00020, 0x80, "MID_BUS PSI"},
+ {HPHW_B_DMA, 0x004, 0x0002F, 0x80, "HP-PB Transit PSI (36960A)"},
+ {HPHW_B_DMA, 0x008, 0x00051, 0x80, "HP-PB Transit 802.3"},
+ {HPHW_B_DMA, 0x004, 0x00052, 0x80, "Miura LAN/Console (J2146A)"},
+ {HPHW_B_DMA, 0x008, 0x00058, 0x80, "HP-PB Transit 802.4"},
+ {HPHW_B_DMA, 0x005, 0x00060, 0x80, "KittyHawk CSY Core LAN/Console"},
+ {HPHW_B_DMA, 0x014, 0x00060, 0x80, "Diablo LAN/Console"},
+ {HPHW_B_DMA, 0x054, 0x00060, 0x80, "Countach LAN/Console"},
+ {HPHW_B_DMA, 0x004, 0x00094, 0x80, "KittyHawk GSC+ Exerciser"},
+ {HPHW_B_DMA, 0x004, 0x00100, 0x80, "HP-PB HF Interface"},
+ {HPHW_B_DMA, 0x000, 0x00206, 0x80, "MELCO HMPHA"},
+ {HPHW_B_DMA, 0x005, 0x00206, 0x80, "MELCO HMPHA_10"},
+ {HPHW_B_DMA, 0x006, 0x00206, 0x80, "MELCO HMQHA"},
+ {HPHW_B_DMA, 0x007, 0x00206, 0x80, "MELCO HMQHA_10"},
+ {HPHW_B_DMA, 0x004, 0x207, 0x80, "MELCO HNDWA MDWS-70"},
+ {HPHW_CIO, 0x004, 0x00010, 0x00, "VLSI CIO"},
+ {HPHW_CIO, 0x005, 0x00010, 0x00, "Silverfox CIO"},
+ {HPHW_CIO, 0x006, 0x00010, 0x00, "Emerald CIO"},
+ {HPHW_CIO, 0x008, 0x00010, 0x00, "Discrete CIO"},
+ {HPHW_CONSOLE, 0x004, 0x0001C, 0x00, "Cheetah console"},
+ {HPHW_CONSOLE, 0x005, 0x0001C, 0x00, "Emerald console"},
+ {HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"},
+ {HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"},
+ {HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"},
+ {HPHW_FABRIC, 0x007, 0x000AA, 0x80, "Caribe DNA Central Agent"},
+ {HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"},
+ {HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"},
+ {HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"},
+ {HPHW_FIO, 0x004, 0x0004F, 0x0, "8-Port X.25 EISA-ACC (AMSO)"},
+ {HPHW_FIO, 0x004, 0x00071, 0x0, "Cobra Core SCSI"},
+ {HPHW_FIO, 0x005, 0x00071, 0x0, "Coral Core SCSI"},
+ {HPHW_FIO, 0x006, 0x00071, 0x0, "Bushmaster Core SCSI"},
+ {HPHW_FIO, 0x007, 0x00071, 0x0, "Scorpio Core SCSI"},
+ {HPHW_FIO, 0x008, 0x00071, 0x0, "Flounder Core SCSI"},
+ {HPHW_FIO, 0x009, 0x00071, 0x0, "Outfield Core SCSI"},
+ {HPHW_FIO, 0x00A, 0x00071, 0x0, "CoralII Core SCSI"},
+ {HPHW_FIO, 0x00B, 0x00071, 0x0, "Scorpio Jr. Core SCSI"},
+ {HPHW_FIO, 0x00C, 0x00071, 0x0, "Strider-50 Core SCSI"},
+ {HPHW_FIO, 0x00D, 0x00071, 0x0, "Strider-33 Core SCSI"},
+ {HPHW_FIO, 0x00E, 0x00071, 0x0, "Trailways-50 Core SCSI"},
+ {HPHW_FIO, 0x00F, 0x00071, 0x0, "Trailways-33 Core SCSI"},
+ {HPHW_FIO, 0x010, 0x00071, 0x0, "Pace Core SCSI"},
+ {HPHW_FIO, 0x011, 0x00071, 0x0, "Sidewinder Core SCSI"},
+ {HPHW_FIO, 0x019, 0x00071, 0x0, "Scorpio Sr. Core SCSI"},
+ {HPHW_FIO, 0x020, 0x00071, 0x0, "Scorpio 100 Core SCSI"},
+ {HPHW_FIO, 0x021, 0x00071, 0x0, "Spectra 50 Core SCSI"},
+ {HPHW_FIO, 0x022, 0x00071, 0x0, "Spectra 75 Core SCSI"},
+ {HPHW_FIO, 0x023, 0x00071, 0x0, "Spectra 100 Core SCSI"},
+ {HPHW_FIO, 0x024, 0x00071, 0x0, "Fast Pace Core SCSI"},
+ {HPHW_FIO, 0x026, 0x00071, 0x0, "CoralII Jaguar Core SCSI"},
+ {HPHW_FIO, 0x004, 0x00072, 0x0, "Cobra Core LAN (802.3)"},
+ {HPHW_FIO, 0x005, 0x00072, 0x0, "Coral Core LAN (802.3)"},
+ {HPHW_FIO, 0x006, 0x00072, 0x0, "Bushmaster Core LAN (802.3)"},
+ {HPHW_FIO, 0x007, 0x00072, 0x0, "Scorpio Core LAN (802.3)"},
+ {HPHW_FIO, 0x008, 0x00072, 0x0, "Flounder Core LAN (802.3)"},
+ {HPHW_FIO, 0x009, 0x00072, 0x0, "Outfield Core LAN (802.3)"},
+ {HPHW_FIO, 0x00A, 0x00072, 0x0, "CoralII Core LAN (802.3)"},
+ {HPHW_FIO, 0x00B, 0x00072, 0x0, "Scorpio Jr. Core LAN (802.3)"},
+ {HPHW_FIO, 0x00C, 0x00072, 0x0, "Strider-50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00D, 0x00072, 0x0, "Strider-33 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00E, 0x00072, 0x0, "Trailways-50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00F, 0x00072, 0x0, "Trailways-33 Core LAN (802.3)"},
+ {HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core LAN (802.3)"},
+ {HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core LAN (802.3)"},
+ {HPHW_FIO, 0x019, 0x00072, 0x0, "Scorpio Sr. Core LAN (802.3)"},
+ {HPHW_FIO, 0x020, 0x00072, 0x0, "Scorpio 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x021, 0x00072, 0x0, "Spectra 50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x022, 0x00072, 0x0, "Spectra 75 Core LAN (802.3)"},
+ {HPHW_FIO, 0x023, 0x00072, 0x0, "Spectra 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core LAN (802.3)"},
+ {HPHW_FIO, 0x026, 0x00072, 0x0, "CoralII Jaguar Core LAN (802.3)"},
+ {HPHW_FIO, 0x004, 0x00073, 0x0, "Cobra Core HIL"},
+ {HPHW_FIO, 0x005, 0x00073, 0x0, "Coral Core HIL"},
+ {HPHW_FIO, 0x006, 0x00073, 0x0, "Bushmaster Core HIL"},
+ {HPHW_FIO, 0x007, 0x00073, 0x0, "Scorpio Core HIL"},
+ {HPHW_FIO, 0x008, 0x00073, 0x0, "Flounder Core HIL"},
+ {HPHW_FIO, 0x009, 0x00073, 0x0, "Outfield Core HIL"},
+ {HPHW_FIO, 0x00A, 0x00073, 0x0, "CoralII Core HIL"},
+ {HPHW_FIO, 0x00B, 0x00073, 0x0, "Scorpio Jr. Core HIL"},
+ {HPHW_FIO, 0x00C, 0x00073, 0x0, "Strider-50 Core HIL"},
+ {HPHW_FIO, 0x00D, 0x00073, 0x0, "Strider-33 Core HIL"},
+ {HPHW_FIO, 0x00E, 0x00073, 0x0, "Trailways-50 Core HIL"},
+ {HPHW_FIO, 0x00F, 0x00073, 0x0, "Trailways-33 Core HIL"},
+ {HPHW_FIO, 0x010, 0x00073, 0x0, "Pace Core HIL"},
+ {HPHW_FIO, 0x011, 0x00073, 0xcc, "SuperPace Wax HIL"},
+ {HPHW_FIO, 0x012, 0x00073, 0x0, "Mirage Jr Wax HIL"},
+ {HPHW_FIO, 0x013, 0x00073, 0x0, "Mirage 100 Wax HIL"},
+ {HPHW_FIO, 0x014, 0x00073, 0x0, "Electra Wax HIL"},
+ {HPHW_FIO, 0x017, 0x00073, 0x0, "Raven Backplane Wax HIL"},
+ {HPHW_FIO, 0x019, 0x00073, 0x0, "Scorpio Sr. Core HIL"},
+ {HPHW_FIO, 0x01E, 0x00073, 0x0, "Raven T' Wax HIL"},
+ {HPHW_FIO, 0x01F, 0x00073, 0x0, "SkyHawk 100/120 Wax HIL"},
+ {HPHW_FIO, 0x020, 0x00073, 0x0, "Scorpio 100 Core HIL"},
+ {HPHW_FIO, 0x021, 0x00073, 0x0, "Spectra 50 Core HIL"},
+ {HPHW_FIO, 0x022, 0x00073, 0x0, "Spectra 75 Core HIL"},
+ {HPHW_FIO, 0x023, 0x00073, 0x0, "Spectra 100 Core HIL"},
+ {HPHW_FIO, 0x024, 0x00073, 0x0, "Fast Pace Core HIL"},
+ {HPHW_FIO, 0x026, 0x00073, 0x0, "CoralII Jaguar Core HIL"},
+ {HPHW_FIO, 0x02B, 0x00073, 0x0, "Mirage 80 Wax HIL"},
+ {HPHW_FIO, 0x02C, 0x00073, 0x0, "Mirage 100+ Wax HIL"},
+ {HPHW_FIO, 0x03A, 0x00073, 0x0, "Merlin+ Wax HIL"},
+ {HPHW_FIO, 0x040, 0x00073, 0x0, "Merlin 132 Wax HIL"},
+ {HPHW_FIO, 0x041, 0x00073, 0x0, "Merlin 160 Wax HIL"},
+ {HPHW_FIO, 0x043, 0x00073, 0x0, "Merlin 132/160 Wax HIL"},
+ {HPHW_FIO, 0x052, 0x00073, 0x0, "Raven+ Hi Power Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x053, 0x00073, 0x0, "Raven+ Hi Power Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x054, 0x00073, 0x0, "Raven+ Lo Power Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x055, 0x00073, 0x0, "Raven+ Lo Power Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x059, 0x00073, 0x0, "FireHawk 200 Wax HIL"},
+ {HPHW_FIO, 0x05A, 0x00073, 0x0, "Raven+ L2 Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x05B, 0x00073, 0x0, "Raven+ L2 Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x05D, 0x00073, 0x0, "SummitHawk Wax HIL"},
+ {HPHW_FIO, 0x800, 0x00073, 0x0, "Hitachi Tiny 64 Wax HIL"},
+ {HPHW_FIO, 0x801, 0x00073, 0x0, "Hitachi Tiny 80 Wax HIL"},
+ {HPHW_FIO, 0x004, 0x00074, 0x0, "Cobra Core Centronics"},
+ {HPHW_FIO, 0x005, 0x00074, 0x0, "Coral Core Centronics"},
+ {HPHW_FIO, 0x006, 0x00074, 0x0, "Bushmaster Core Centronics"},
+ {HPHW_FIO, 0x007, 0x00074, 0x0, "Scorpio Core Centronics"},
+ {HPHW_FIO, 0x008, 0x00074, 0x0, "Flounder Core Centronics"},
+ {HPHW_FIO, 0x009, 0x00074, 0x0, "Outfield Core Centronics"},
+ {HPHW_FIO, 0x00A, 0x00074, 0x0, "CoralII Core Centronics"},
+ {HPHW_FIO, 0x00B, 0x00074, 0x0, "Scorpio Jr. Core Centronics"},
+ {HPHW_FIO, 0x00C, 0x00074, 0x0, "Strider-50 Core Centronics"},
+ {HPHW_FIO, 0x00D, 0x00074, 0x0, "Strider-33 Core Centronics"},
+ {HPHW_FIO, 0x00E, 0x00074, 0x0, "Trailways-50 Core Centronics"},
+ {HPHW_FIO, 0x00F, 0x00074, 0x0, "Trailways-33 Core Centronics"},
+ {HPHW_FIO, 0x010, 0x00074, 0x0, "Pace Core Centronics"},
+ {HPHW_FIO, 0x011, 0x00074, 0x0, "Sidewinder Core Centronics"},
+ {HPHW_FIO, 0x015, 0x00074, 0x0, "KittyHawk GSY Core Centronics"},
+ {HPHW_FIO, 0x016, 0x00074, 0x0, "Gecko Core Centronics"},
+ {HPHW_FIO, 0x019, 0x00074, 0x0, "Scorpio Sr. Core Centronics"},
+ {HPHW_FIO, 0x01A, 0x00074, 0x0, "Anole 64 Core Centronics"},
+ {HPHW_FIO, 0x01B, 0x00074, 0x0, "Anole 100 Core Centronics"},
+ {HPHW_FIO, 0x01C, 0x00074, 0x0, "Gecko 80 Core Centronics"},
+ {HPHW_FIO, 0x01D, 0x00074, 0x0, "Gecko 100 Core Centronics"},
+ {HPHW_FIO, 0x01F, 0x00074, 0x0, "SkyHawk 100/120 Core Centronics"},
+ {HPHW_FIO, 0x020, 0x00074, 0x0, "Scorpio 100 Core Centronics"},
+ {HPHW_FIO, 0x021, 0x00074, 0x0, "Spectra 50 Core Centronics"},
+ {HPHW_FIO, 0x022, 0x00074, 0x0, "Spectra 75 Core Centronics"},
+ {HPHW_FIO, 0x023, 0x00074, 0x0, "Spectra 100 Core Centronics"},
+ {HPHW_FIO, 0x024, 0x00074, 0x0, "Fast Pace Core Centronics"},
+ {HPHW_FIO, 0x026, 0x00074, 0x0, "CoralII Jaguar Core Centronics"},
+ {HPHW_FIO, 0x027, 0x00074, 0x0, "Piranha 100 Core Centronics"},
+ {HPHW_FIO, 0x028, 0x00074, 0x0, "Mirage Jr Core Centronics"},
+ {HPHW_FIO, 0x029, 0x00074, 0x0, "Mirage Core Centronics"},
+ {HPHW_FIO, 0x02A, 0x00074, 0x0, "Electra Core Centronics"},
+ {HPHW_FIO, 0x02B, 0x00074, 0x0, "Mirage 80 Core Centronics"},
+ {HPHW_FIO, 0x02C, 0x00074, 0x0, "Mirage 100+ Core Centronics"},
+ {HPHW_FIO, 0x02E, 0x00074, 0x0, "UL 350 Core Centronics"},
+ {HPHW_FIO, 0x02F, 0x00074, 0x0, "UL 550 Core Centronics"},
+ {HPHW_FIO, 0x032, 0x00074, 0x0, "Raven T' Core Centronics"},
+ {HPHW_FIO, 0x033, 0x00074, 0x0, "Anole T Core Centronics"},
+ {HPHW_FIO, 0x034, 0x00074, 0x0, "SAIC L-80 Core Centronics"},
+ {HPHW_FIO, 0x035, 0x00074, 0x0, "PCX-L2 712/132 Core Centronics"},
+ {HPHW_FIO, 0x036, 0x00074, 0x0, "PCX-L2 712/160 Core Centronics"},
+ {HPHW_FIO, 0x03B, 0x00074, 0x0, "Raven U/L2 Core Centronics"},
+ {HPHW_FIO, 0x03C, 0x00074, 0x0, "Merlin 132 Core Centronics"},
+ {HPHW_FIO, 0x03D, 0x00074, 0x0, "Merlin 160 Core Centronics"},
+ {HPHW_FIO, 0x03E, 0x00074, 0x0, "Merlin+ 132 Core Centronics"},
+ {HPHW_FIO, 0x03F, 0x00074, 0x0, "Merlin+ 180 Core Centronics"},
+ {HPHW_FIO, 0x044, 0x00074, 0x0, "Mohawk Core Centronics"},
+ {HPHW_FIO, 0x045, 0x00074, 0x0, "Rocky1 Core Centronics"},
+ {HPHW_FIO, 0x046, 0x00074, 0x0, "Rocky2 120 Core Centronics"},
+ {HPHW_FIO, 0x047, 0x00074, 0x0, "Rocky2 150 Core Centronics"},
+ {HPHW_FIO, 0x04B, 0x00074, 0x0, "Anole L2 132 Core Centronics"},
+ {HPHW_FIO, 0x04D, 0x00074, 0x0, "Anole L2 165 Core Centronics"},
+ {HPHW_FIO, 0x050, 0x00074, 0x0, "Merlin Jr 132 Core Centronics"},
+ {HPHW_FIO, 0x051, 0x00074, 0x0, "Firehawk Core Centronics"},
+ {HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ w SE FWSCSI Core Centronics"},
+ {HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ w Diff FWSCSI Core Centronics"},
+ {HPHW_FIO, 0x058, 0x00074, 0x0, "FireHawk 200 Core Centronics"},
+ {HPHW_FIO, 0x05C, 0x00074, 0x0, "SummitHawk 230 Core Centronics"},
+ {HPHW_FIO, 0x800, 0x00074, 0x0, "Hitachi Tiny 64 Core Centronics"},
+ {HPHW_FIO, 0x801, 0x00074, 0x0, "Hitachi Tiny 80 Core Centronics"},
+ {HPHW_FIO, 0x004, 0x00075, 0x0, "Cobra Core RS-232"},
+ {HPHW_FIO, 0x005, 0x00075, 0x0, "Coral Core RS-232"},
+ {HPHW_FIO, 0x006, 0x00075, 0x0, "Bushmaster Core RS-232"},
+ {HPHW_FIO, 0x007, 0x00075, 0x0, "Scorpio Core RS-232"},
+ {HPHW_FIO, 0x008, 0x00075, 0x0, "Flounder Core RS-232"},
+ {HPHW_FIO, 0x009, 0x00075, 0x0, "Outfield Core RS-232"},
+ {HPHW_FIO, 0x00A, 0x00075, 0x0, "CoralII Core RS-232"},
+ {HPHW_FIO, 0x00B, 0x00075, 0x0, "Scorpio Jr. Core RS-232"},
+ {HPHW_FIO, 0x00C, 0x00075, 0x0, "Strider-50 Core RS-232"},
+ {HPHW_FIO, 0x00D, 0x00075, 0x0, "Strider-33 Core RS-232"},
+ {HPHW_FIO, 0x00E, 0x00075, 0x0, "Trailways-50 Core RS-232"},
+ {HPHW_FIO, 0x00F, 0x00075, 0x0, "Trailways-33 Core RS-232"},
+ {HPHW_FIO, 0x010, 0x00075, 0x0, "Pace Core RS-232"},
+ {HPHW_FIO, 0x011, 0x00075, 0x0, "Sidewinder Core RS-232"},
+ {HPHW_FIO, 0x019, 0x00075, 0x0, "Scorpio Sr. Core RS-232"},
+ {HPHW_FIO, 0x020, 0x00075, 0x0, "Scorpio 100 Core RS-232"},
+ {HPHW_FIO, 0x021, 0x00075, 0x0, "Spectra 50 Core RS-232"},
+ {HPHW_FIO, 0x022, 0x00075, 0x0, "Spectra 75 Core RS-232"},
+ {HPHW_FIO, 0x023, 0x00075, 0x0, "Spectra 100 Core RS-232"},
+ {HPHW_FIO, 0x024, 0x00075, 0x0, "Fast Pace Core RS-232"},
+ {HPHW_FIO, 0x026, 0x00075, 0x0, "CoralII Jaguar Core RS-232"},
+ {HPHW_FIO, 0x004, 0x00077, 0x0, "Coral SGC Graphics"},
+ {HPHW_FIO, 0x005, 0x00077, 0x0, "Hyperdrive Optional Graphics"},
+ {HPHW_FIO, 0x006, 0x00077, 0x0, "Stinger Optional Graphics"},
+ {HPHW_FIO, 0x007, 0x00077, 0x0, "Scorpio Builtin Graphics"},
+ {HPHW_FIO, 0x008, 0x00077, 0x0, "Anole Hyperdrive Optional Graphics"},
+ {HPHW_FIO, 0x009, 0x00077, 0x0, "Thunder II graphics EISA form"},
+ {HPHW_FIO, 0x00A, 0x00077, 0x0, "Thunder II graphics GSA form"},
+ {HPHW_FIO, 0x00B, 0x00077, 0x0, "Scorpio Jr Builtin Graphics"},
+ {HPHW_FIO, 0x00C, 0x00077, 0x0, "Strider-50 SSC Graphics"},
+ {HPHW_FIO, 0x00D, 0x00077, 0x0, "Strider-33 SSC Graphics"},
+ {HPHW_FIO, 0x00E, 0x00077, 0x0, "Trailways-50 SSC Graphics"},
+ {HPHW_FIO, 0x00F, 0x00077, 0x0, "Trailways-33 SSC Graphics"},
+ {HPHW_FIO, 0x010, 0x00077, 0x0, "Pace SGC Graphics"},
+ {HPHW_FIO, 0x011, 0x00077, 0x0, "Mohawk Opt. 2D Graphics (Kid)"},
+ {HPHW_FIO, 0x012, 0x00077, 0x0, "Raven Opt. 2D Graphics (Goat)"},
+ {HPHW_FIO, 0x016, 0x00077, 0x0, "Lego 24 SCG Graphics"},
+ {HPHW_FIO, 0x017, 0x00077, 0x0, "Lego 24Z SCG Graphics"},
+ {HPHW_FIO, 0x018, 0x00077, 0x0, "Lego 48Z SCG Graphics"},
+ {HPHW_FIO, 0x019, 0x00077, 0x0, "Scorpio Sr Builtin Graphics"},
+ {HPHW_FIO, 0x020, 0x00077, 0x0, "Scorpio 100 Builtin Graphics"},
+ {HPHW_FIO, 0x021, 0x00077, 0x0, "Spectra 50 Builtin Graphics"},
+ {HPHW_FIO, 0x022, 0x00077, 0x0, "Spectra 75 Builtin Graphics"},
+ {HPHW_FIO, 0x023, 0x00077, 0x0, "Spectra 100 Builtin Graphics"},
+ {HPHW_FIO, 0x024, 0x00077, 0x0, "Fast Pace SGC Graphics"},
+ {HPHW_FIO, 0x006, 0x0007A, 0x0, "Bushmaster Audio"},
+ {HPHW_FIO, 0x008, 0x0007A, 0x0, "Flounder Audio"},
+ {HPHW_FIO, 0x004, 0x0007B, 0x0, "UL Optional Audio"},
+ {HPHW_FIO, 0x007, 0x0007B, 0x0, "Scorpio Audio"},
+ {HPHW_FIO, 0x00B, 0x0007B, 0x0, "Scorpio Jr. Audio"},
+ {HPHW_FIO, 0x00C, 0x0007B, 0x0, "Strider-50 Audio"},
+ {HPHW_FIO, 0x00D, 0x0007B, 0x0, "Strider-33 Audio"},
+ {HPHW_FIO, 0x00E, 0x0007B, 0x0, "Trailways-50 Audio"},
+ {HPHW_FIO, 0x00F, 0x0007B, 0x0, "Trailways-33 Audio"},
+ {HPHW_FIO, 0x015, 0x0007B, 0x0, "KittyHawk GSY Core Audio"},
+ {HPHW_FIO, 0x016, 0x0007B, 0x0, "Gecko Audio"},
+ {HPHW_FIO, 0x019, 0x0007B, 0x0, "Scorpio Sr. Audio"},
+ {HPHW_FIO, 0x01A, 0x0007B, 0x0, "Anole 64 Audio"},
+ {HPHW_FIO, 0x01B, 0x0007B, 0x0, "Anole 100 Audio"},
+ {HPHW_FIO, 0x01C, 0x0007B, 0x0, "Gecko 80 Audio"},
+ {HPHW_FIO, 0x01D, 0x0007B, 0x0, "Gecko 100 Audio"},
+ {HPHW_FIO, 0x01F, 0x0007B, 0x0, "SkyHawk 100/120 Audio"},
+ {HPHW_FIO, 0x020, 0x0007B, 0x0, "Scorpio 100 Audio"},
+ {HPHW_FIO, 0x021, 0x0007B, 0x0, "Spectra 50 Audio"},
+ {HPHW_FIO, 0x022, 0x0007B, 0x0, "Spectra 75 Audio"},
+ {HPHW_FIO, 0x023, 0x0007B, 0x0, "Spectra 100 Audio"},
+ {HPHW_FIO, 0x028, 0x0007B, 0x0, "Mirage Jr Audio"},
+ {HPHW_FIO, 0x029, 0x0007B, 0x0, "Mirage Audio"},
+ {HPHW_FIO, 0x02A, 0x0007B, 0x0, "Electra Audio"},
+ {HPHW_FIO, 0x02B, 0x0007B, 0x0, "Mirage 80 Audio"},
+ {HPHW_FIO, 0x02C, 0x0007B, 0x0, "Mirage 100+ Audio"},
+ {HPHW_FIO, 0x032, 0x0007B, 0x0, "Raven T' Audio"},
+ {HPHW_FIO, 0x034, 0x0007B, 0x0, "SAIC L-80 Audio"},
+ {HPHW_FIO, 0x035, 0x0007B, 0x0, "PCX-L2 712/132 Core Audio"},
+ {HPHW_FIO, 0x036, 0x0007B, 0x0, "PCX-L2 712/160 Core Audio"},
+ {HPHW_FIO, 0x03B, 0x0007B, 0x0, "Raven U/L2 Core Audio"},
+ {HPHW_FIO, 0x03C, 0x0007B, 0x0, "Merlin 132 Core Audio"},
+ {HPHW_FIO, 0x03D, 0x0007B, 0x0, "Merlin 160 Core Audio"},
+ {HPHW_FIO, 0x03E, 0x0007B, 0x0, "Merlin+ 132 Core Audio"},
+ {HPHW_FIO, 0x03F, 0x0007B, 0x0, "Merlin+ 180 Core Audio"},
+ {HPHW_FIO, 0x044, 0x0007B, 0x0, "Mohawk Core Audio"},
+ {HPHW_FIO, 0x046, 0x0007B, 0x0, "Rocky2 120 Core Audio"},
+ {HPHW_FIO, 0x047, 0x0007B, 0x0, "Rocky2 150 Core Audio"},
+ {HPHW_FIO, 0x04B, 0x0007B, 0x0, "Anole L2 132 Core Audio"},
+ {HPHW_FIO, 0x04D, 0x0007B, 0x0, "Anole L2 165 Core Audio"},
+ {HPHW_FIO, 0x04E, 0x0007B, 0x0, "Kiji L2 132 Core Audio"},
+ {HPHW_FIO, 0x050, 0x0007B, 0x0, "Merlin Jr 132 Core Audio"},
+ {HPHW_FIO, 0x051, 0x0007B, 0x0, "Firehawk Audio"},
+ {HPHW_FIO, 0x056, 0x0007B, 0x0, "Raven+ w SE FWSCSI Core Audio"},
+ {HPHW_FIO, 0x057, 0x0007B, 0x0, "Raven+ w Diff FWSCSI Core Audio"},
+ {HPHW_FIO, 0x058, 0x0007B, 0x0, "FireHawk 200 Audio"},
+ {HPHW_FIO, 0x05C, 0x0007B, 0x0, "SummitHawk 230 Core Audio"},
+ {HPHW_FIO, 0x800, 0x0007B, 0x0, "Hitachi Tiny 64 Audio"},
+ {HPHW_FIO, 0x801, 0x0007B, 0x0, "Hitachi Tiny 80 Audio"},
+ {HPHW_FIO, 0x009, 0x0007C, 0x0, "Outfield FW SCSI"},
+ {HPHW_FIO, 0x00A, 0x0007C, 0x0, "CoralII FW SCSI"},
+ {HPHW_FIO, 0x026, 0x0007C, 0x0, "CoralII Jaguar FW SCSI"},
+ {HPHW_FIO, 0x009, 0x0007D, 0x0, "Outfield FDDI"},
+ {HPHW_FIO, 0x00A, 0x0007D, 0x0, "CoralII FDDI"},
+ {HPHW_FIO, 0x026, 0x0007D, 0x0, "CoralII Jaguar FDDI"},
+ {HPHW_FIO, 0x010, 0x0007E, 0x0, "Pace Audio"},
+ {HPHW_FIO, 0x024, 0x0007E, 0x0, "Fast Pace Audio"},
+ {HPHW_FIO, 0x009, 0x0007F, 0x0, "Outfield Audio"},
+ {HPHW_FIO, 0x00A, 0x0007F, 0x0, "CoralII Audio"},
+ {HPHW_FIO, 0x026, 0x0007F, 0x0, "CoralII Jaguar Audio"},
+ {HPHW_FIO, 0x010, 0x00080, 0x0, "Pace Core HPIB"},
+ {HPHW_FIO, 0x024, 0x00080, 0x0, "Fast Pace Core HPIB"},
+ {HPHW_FIO, 0x015, 0x00082, 0x0, "KittyHawk GSY Core SCSI"},
+ {HPHW_FIO, 0x016, 0x00082, 0x0, "Gecko Core SCSI"},
+ {HPHW_FIO, 0x01A, 0x00082, 0x0, "Anole 64 Core SCSI"},
+ {HPHW_FIO, 0x01B, 0x00082, 0x0, "Anole 100 Core SCSI"},
+ {HPHW_FIO, 0x01C, 0x00082, 0x0, "Gecko 80 Core SCSI"},
+ {HPHW_FIO, 0x01D, 0x00082, 0x0, "Gecko 100 Core SCSI"},
+ {HPHW_FIO, 0x01F, 0x00082, 0x0, "SkyHawk 100/120 Core SCSI"},
+ {HPHW_FIO, 0x027, 0x00082, 0x0, "Piranha 100 Core SCSI"},
+ {HPHW_FIO, 0x028, 0x00082, 0x0, "Mirage Jr Core SCSI"},
+ {HPHW_FIO, 0x029, 0x00082, 0x0, "Mirage Core SCSI"},
+ {HPHW_FIO, 0x02A, 0x00082, 0x0, "Electra Core SCSI"},
+ {HPHW_FIO, 0x02B, 0x00082, 0x0, "Mirage 80 Core SCSI"},
+ {HPHW_FIO, 0x02C, 0x00082, 0x0, "Mirage 100+ Core SCSI"},
+ {HPHW_FIO, 0x02E, 0x00082, 0x0, "UL 350 Core SCSI"},
+ {HPHW_FIO, 0x02F, 0x00082, 0x0, "UL 550 Core SCSI"},
+ {HPHW_FIO, 0x032, 0x00082, 0x0, "Raven T' Core SCSI"},
+ {HPHW_FIO, 0x033, 0x00082, 0x0, "Anole T Core SCSI"},
+ {HPHW_FIO, 0x034, 0x00082, 0x0, "SAIC L-80 Core SCSI"},
+ {HPHW_FIO, 0x035, 0x00082, 0x0, "PCX-L2 712/132 Core SCSI"},
+ {HPHW_FIO, 0x036, 0x00082, 0x0, "PCX-L2 712/160 Core SCSI"},
+ {HPHW_FIO, 0x03B, 0x00082, 0x0, "Raven U/L2 Core SCSI"},
+ {HPHW_FIO, 0x03C, 0x00082, 0x0, "Merlin 132 Core SCSI"},
+ {HPHW_FIO, 0x03D, 0x00082, 0x0, "Merlin 160 Core SCSI"},
+ {HPHW_FIO, 0x03E, 0x00082, 0x0, "Merlin+ 132 Core SCSI"},
+ {HPHW_FIO, 0x03F, 0x00082, 0x0, "Merlin+ 180 Core SCSI"},
+ {HPHW_FIO, 0x044, 0x00082, 0x0, "Mohawk Core SCSI"},
+ {HPHW_FIO, 0x045, 0x00082, 0x0, "Rocky1 Core SCSI"},
+ {HPHW_FIO, 0x046, 0x00082, 0x0, "Rocky2 120 Core SCSI"},
+ {HPHW_FIO, 0x047, 0x00082, 0x0, "Rocky2 150 Core SCSI"},
+ {HPHW_FIO, 0x04B, 0x00082, 0x0, "Anole L2 132 Core SCSI"},
+ {HPHW_FIO, 0x04D, 0x00082, 0x0, "Anole L2 165 Core SCSI"},
+ {HPHW_FIO, 0x04E, 0x00082, 0x0, "Kiji L2 132 Core SCSI"},
+ {HPHW_FIO, 0x050, 0x00082, 0x0, "Merlin Jr 132 Core SCSI"},
+ {HPHW_FIO, 0x051, 0x00082, 0x0, "Firehawk Core SCSI"},
+ {HPHW_FIO, 0x056, 0x00082, 0x0, "Raven+ w SE FWSCSI Core SCSI"},
+ {HPHW_FIO, 0x057, 0x00082, 0x0, "Raven+ w Diff FWSCSI Core SCSI"},
+ {HPHW_FIO, 0x058, 0x00082, 0x0, "FireHawk 200 Core SCSI"},
+ {HPHW_FIO, 0x05C, 0x00082, 0x0, "SummitHawk 230 Core SCSI"},
+ {HPHW_FIO, 0x05E, 0x00082, 0x0, "Staccato 132 Core SCSI"},
+ {HPHW_FIO, 0x05F, 0x00082, 0x0, "Staccato 180 Core SCSI"},
+ {HPHW_FIO, 0x800, 0x00082, 0x0, "Hitachi Tiny 64 Core SCSI"},
+ {HPHW_FIO, 0x801, 0x00082, 0x0, "Hitachi Tiny 80 Core SCSI"},
+ {HPHW_FIO, 0x016, 0x00083, 0x0, "Gecko Core PC Floppy"},
+ {HPHW_FIO, 0x01C, 0x00083, 0x0, "Gecko 80 Core PC Floppy"},
+ {HPHW_FIO, 0x01D, 0x00083, 0x0, "Gecko 100 Core PC Floppy"},
+ {HPHW_FIO, 0x051, 0x00083, 0x0, "Firehawk Core PC Floppy"},
+ {HPHW_FIO, 0x058, 0x00083, 0x0, "FireHawk 200 Core PC Floppy"},
+ {HPHW_FIO, 0x027, 0x00083, 0x0, "Piranha 100 Core PC Floppy"},
+ {HPHW_FIO, 0x028, 0x00083, 0x0, "Mirage Jr Core PC Floppy"},
+ {HPHW_FIO, 0x029, 0x00083, 0x0, "Mirage Core PC Floppy"},
+ {HPHW_FIO, 0x02A, 0x00083, 0x0, "Electra Core PC Floppy"},
+ {HPHW_FIO, 0x02B, 0x00083, 0x0, "Mirage 80 Core PC Floppy"},
+ {HPHW_FIO, 0x02C, 0x00083, 0x0, "Mirage 100+ Core PC Floppy"},
+ {HPHW_FIO, 0x02E, 0x00083, 0x0, "UL 350 Core PC Floppy"},
+ {HPHW_FIO, 0x02F, 0x00083, 0x0, "UL 550 Core PC Floppy"},
+ {HPHW_FIO, 0x032, 0x00083, 0x0, "Raven T' Core PC Floppy"},
+ {HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floppy"},
+ {HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floppy"},
+ {HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floppy"},
+ {HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floppy"},
+ {HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floppy"},
+ {HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floppy"},
+ {HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floppy"},
+ {HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floppy"},
+ {HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floppy"},
+ {HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floppy"},
+ {HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floppy"},
+ {HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floppy"},
+ {HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floppy"},
+ {HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floppy"},
+ {HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floppy"},
+ {HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floppy"},
+ {HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floppy"},
+ {HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PS/2 Port"},
+ {HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PS/2 Port"},
+ {HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PS/2 Port"},
+ {HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PS/2 Port"},
+ {HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PS/2 Port"},
+ {HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PS/2 Port"},
+ {HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PS/2 Port"},
+ {HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PS/2 Port"},
+ {HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PS/2 Port"},
+ {HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PS/2 Port"},
+ {HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PS/2 Port"},
+ {HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PS/2 Port"},
+ {HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PS/2 Port"},
+ {HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PS/2 Port"},
+ {HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PS/2 Port"},
+ {HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PS/2 Port"},
+ {HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PS/2 Port"},
+ {HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PS/2 Port"},
+ {HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PS/2 Port"},
+ {HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core PS/2 Port"},
+ {HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core PS/2 Port"},
+ {HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PS/2 Port"},
+ {HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PS/2 Port"},
+ {HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PS/2 Port"},
+ {HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PS/2 Port"},
+ {HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PS/2 Port"},
+ {HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PS/2 Port"},
+ {HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PS/2 Port"},
+ {HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PS/2 Port"},
+ {HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PS/2 Port"},
+ {HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PS/2 Port"},
+ {HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PS/2 Port"},
+ {HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PS/2 Port"},
+ {HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PS/2 Port"},
+ {HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PS/2 Port"},
+ {HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PS/2 Port"},
+ {HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PS/2 Port"},
+ {HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PS/2 Port"},
+ {HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PS/2 Port"},
+ {HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PS/2 Port"},
+ {HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PS/2 Port"},
+ {HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PS/2 Port"},
+ {HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PS/2 Port"},
+ {HPHW_FIO, 0x004, 0x00085, 0x0, "Solo GSC Optional Graphics"},
+ {HPHW_FIO, 0x005, 0x00085, 0x0, "Duet GSC Optional Graphics"},
+ {HPHW_FIO, 0x008, 0x00085, 0x0, "Anole Artist Optional Graphics"},
+ {HPHW_FIO, 0x010, 0x00085, 0x0, "Mirage 80 GSC Builtin Graphics"},
+ {HPHW_FIO, 0x011, 0x00085, 0x0, "Mirage 100+ GSC Builtin Graphics"},
+ {HPHW_FIO, 0x012, 0x00085, 0x0, "Mirage Jr GSC Builtin Graphics"},
+ {HPHW_FIO, 0x013, 0x00085, 0x0, "Mirage GSC Builtin Graphics"},
+ {HPHW_FIO, 0x014, 0x00085, 0x0, "Electra GSC Builtin Graphics"},
+ {HPHW_FIO, 0x016, 0x00085, 0x0, "Gecko GSC Core Graphics"},
+ {HPHW_FIO, 0x017, 0x00085, 0x0, "Gecko GSC Optional Graphics"},
+ {HPHW_FIO, 0x01A, 0x00085, 0x0, "Anole 64 Artist Builtin Graphics"},
+ {HPHW_FIO, 0x01B, 0x00085, 0x0, "Anole 100 Artist Builtin Graphics"},
+ {HPHW_FIO, 0x01C, 0x00085, 0x0, "Gecko 80 GSC Core Graphics"},
+ {HPHW_FIO, 0x01D, 0x00085, 0x0, "Gecko 100 GSC Core Graphics"},
+ {HPHW_FIO, 0x032, 0x00085, 0x0, "Raven T' GSC Core Graphics"},
+ {HPHW_FIO, 0x033, 0x00085, 0x0, "Anole T Artist Builtin Graphics"},
+ {HPHW_FIO, 0x034, 0x00085, 0x0, "SAIC L-80 GSC Core Graphics"},
+ {HPHW_FIO, 0x035, 0x00085, 0x0, "PCX-L2 712/132 Core Graphics"},
+ {HPHW_FIO, 0x036, 0x00085, 0x0, "PCX-L2 712/160 Core Graphics"},
+ {HPHW_FIO, 0x03B, 0x00085, 0x0, "Raven U/L2 Core Graphics"},
+ {HPHW_FIO, 0x03C, 0x00085, 0x0, "Merlin 132 Core Graphics"},
+ {HPHW_FIO, 0x03D, 0x00085, 0x0, "Merlin 160 Core Graphics"},
+ {HPHW_FIO, 0x03E, 0x00085, 0x0, "Merlin+ 132 Core Graphics"},
+ {HPHW_FIO, 0x03F, 0x00085, 0x0, "Merlin+ 180 Core Graphics"},
+ {HPHW_FIO, 0x045, 0x00085, 0x0, "Rocky1 Core Graphics"},
+ {HPHW_FIO, 0x046, 0x00085, 0x0, "Rocky2 120 Core Graphics"},
+ {HPHW_FIO, 0x047, 0x00085, 0x0, "Rocky2 150 Core Graphics"},
+ {HPHW_FIO, 0x04B, 0x00085, 0x0, "Anole L2 132 Core Graphics"},
+ {HPHW_FIO, 0x04D, 0x00085, 0x0, "Anole L2 165 Core Graphics"},
+ {HPHW_FIO, 0x04E, 0x00085, 0x0, "Kiji L2 132 Core Graphics"},
+ {HPHW_FIO, 0x050, 0x00085, 0x0, "Merlin Jr 132 Core Graphics"},
+ {HPHW_FIO, 0x056, 0x00085, 0x0, "Raven+ w SE FWSCSI Core Graphics"},
+ {HPHW_FIO, 0x057, 0x00085, 0x0, "Raven+ w Diff FWSCSI Core Graphics"},
+ {HPHW_FIO, 0x800, 0x00085, 0x0, "Hitachi Tiny 64 Core Graphics"},
+ {HPHW_FIO, 0x801, 0x00085, 0x0, "Hitachi Tiny 80 Core Graphics"},
+ {HPHW_FIO, 0x004, 0x00086, 0x0, "GSC IBM Token Ring"},
+ {HPHW_FIO, 0x015, 0x00087, 0x0, "Gecko Optional ISDN"},
+ {HPHW_FIO, 0x016, 0x00087, 0x0, "Gecko Core ISDN"},
+ {HPHW_FIO, 0x01C, 0x00087, 0x0, "Gecko 80 Core ISDN"},
+ {HPHW_FIO, 0x01D, 0x00087, 0x0, "Gecko 100 Core ISDN"},
+ {HPHW_FIO, 0x010, 0x00088, 0x0, "Pace VME Networking"},
+ {HPHW_FIO, 0x011, 0x00088, 0x0, "Sidewinder VME Networking"},
+ {HPHW_FIO, 0x01A, 0x00088, 0x0, "Anole 64 VME Networking"},
+ {HPHW_FIO, 0x01B, 0x00088, 0x0, "Anole 100 VME Networking"},
+ {HPHW_FIO, 0x024, 0x00088, 0x0, "Fast Pace VME Networking"},
+ {HPHW_FIO, 0x034, 0x00088, 0x0, "Anole T VME Networking"},
+ {HPHW_FIO, 0x04A, 0x00088, 0x0, "Anole L2 132 VME Networking"},
+ {HPHW_FIO, 0x04C, 0x00088, 0x0, "Anole L2 165 VME Networking"},
+ {HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core LAN (802.3)"},
+ {HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core LAN (802.3)"},
+ {HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core LAN (802.3)"},
+ {HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core LAN (802.3)"},
+ {HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core LAN (802.3)"},
+ {HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core LAN (802.3)"},
+ {HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional LAN (802.3)"},
+ {HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core LAN (802.3)"},
+ {HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core LAN (802.3)"},
+ {HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x01F, 0x0008A, 0x0, "SkyHawk 100/120 Core LAN (802.3)"},
+ {HPHW_FIO, 0x027, 0x0008A, 0x0, "Piranha 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x028, 0x0008A, 0x0, "Mirage Jr Core LAN (802.3)"},
+ {HPHW_FIO, 0x029, 0x0008A, 0x0, "Mirage Core LAN (802.3)"},
+ {HPHW_FIO, 0x02A, 0x0008A, 0x0, "Electra Core LAN (802.3)"},
+ {HPHW_FIO, 0x02B, 0x0008A, 0x0, "Mirage 80 Core LAN (802.3)"},
+ {HPHW_FIO, 0x02C, 0x0008A, 0x0, "Mirage 100+ Core LAN (802.3)"},
+ {HPHW_FIO, 0x02E, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"},
+ {HPHW_FIO, 0x02F, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"},
+ {HPHW_FIO, 0x032, 0x0008A, 0x0, "Raven T' Core LAN (802.3)"},
+ {HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core LAN (802.3)"},
+ {HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core LAN (802.3)"},
+ {HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core LAN (802.3)"},
+ {HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core LAN (802.3)"},
+ {HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core LAN (802.3)"},
+ {HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core LAN (802.3)"},
+ {HPHW_FIO, 0x045, 0x0008A, 0x0, "Rocky1 Core LAN (802.3)"},
+ {HPHW_FIO, 0x046, 0x0008A, 0x0, "Rocky2 120 Core LAN (802.3)"},
+ {HPHW_FIO, 0x047, 0x0008A, 0x0, "Rocky2 150 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04B, 0x0008A, 0x0, "Anole L2 132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04D, 0x0008A, 0x0, "Anole L2 165 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04E, 0x0008A, 0x0, "Kiji L2 132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x058, 0x0008A, 0x0, "FireHawk 200 Core LAN (802.3)"},
+ {HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core LAN (802.3)"},
+ {HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core LAN (802.3)"},
+ {HPHW_FIO, 0x004, 0x0008C, 0x0, "SkyHawk 100/120 Wax RS-232"},
+ {HPHW_FIO, 0x005, 0x0008C, 0x0, "SAIC L-80 Wax RS-232"},
+ {HPHW_FIO, 0x006, 0x0008C, 0x0, "Raven U/L2 Dino RS-232"},
+ {HPHW_FIO, 0x007, 0x0008C, 0x0, "Dino RS-232"},
+ {HPHW_FIO, 0x008, 0x0008C, 0x0, "Merlin 132 Dino RS-232"},
+ {HPHW_FIO, 0x009, 0x0008C, 0x0, "Merlin 160 Dino RS-232"},
+ {HPHW_FIO, 0x00A, 0x0008C, 0x0, "Merlin Jr 132 Dino RS-232"},
+ {HPHW_FIO, 0x010, 0x0008C, 0x0, "Mirage 80 Wax RS-232"},
+ {HPHW_FIO, 0x011, 0x0008C, 0x0, "Mirage 100+ Wax RS-232"},
+ {HPHW_FIO, 0x012, 0x0008C, 0x0, "Mirage Jr Wax RS-232"},
+ {HPHW_FIO, 0x013, 0x0008C, 0x0, "Mirage Wax RS-232"},
+ {HPHW_FIO, 0x014, 0x0008C, 0x0, "Electra Wax RS-232"},
+ {HPHW_FIO, 0x015, 0x0008C, 0x0, "KittyHawk GSY Core RS-232"},
+ {HPHW_FIO, 0x016, 0x0008C, 0x0, "Gecko Core RS-232"},
+ {HPHW_FIO, 0x017, 0x0008C, 0x0, "Raven Backplane RS-232"},
+ {HPHW_FIO, 0x018, 0x0008C, 0x0, "Gecko Optional RS-232"},
+ {HPHW_FIO, 0x019, 0x0008C, 0x0, "Merlin+ 180 Dino RS-232"},
+ {HPHW_FIO, 0x01A, 0x0008C, 0x0, "Anole 64 Core RS-232"},
+ {HPHW_FIO, 0x01B, 0x0008C, 0x0, "Anole 100 Core RS-232"},
+ {HPHW_FIO, 0x01C, 0x0008C, 0x0, "Gecko 80 Core RS-232"},
+ {HPHW_FIO, 0x01D, 0x0008C, 0x0, "Gecko 100 Core RS-232"},
+ {HPHW_FIO, 0x01E, 0x0008C, 0x0, "Raven T' Wax RS-232"},
+ {HPHW_FIO, 0x01F, 0x0008C, 0x0, "SkyHawk 100/120 Core RS-232"},
+ {HPHW_FIO, 0x020, 0x0008C, 0x0, "Anole 64 Timi RS-232"},
+ {HPHW_FIO, 0x021, 0x0008C, 0x0, "Anole 100 Timi RS-232"},
+ {HPHW_FIO, 0x022, 0x0008C, 0x0, "Merlin+ 132 Dino RS-232"},
+ {HPHW_FIO, 0x023, 0x0008C, 0x0, "Rocky1 Wax RS-232"},
+ {HPHW_FIO, 0x025, 0x0008C, 0x0, "Armyknife Optional RS-232"},
+ {HPHW_FIO, 0x026, 0x0008C, 0x0, "Piranha 100 Wax RS-232"},
+ {HPHW_FIO, 0x027, 0x0008C, 0x0, "Piranha 100 Core RS-232"},
+ {HPHW_FIO, 0x028, 0x0008C, 0x0, "Mirage Jr Core RS-232"},
+ {HPHW_FIO, 0x029, 0x0008C, 0x0, "Mirage Core RS-232"},
+ {HPHW_FIO, 0x02A, 0x0008C, 0x0, "Electra Core RS-232"},
+ {HPHW_FIO, 0x02B, 0x0008C, 0x0, "Mirage 80 Core RS-232"},
+ {HPHW_FIO, 0x02C, 0x0008C, 0x0, "Mirage 100+ Core RS-232"},
+ {HPHW_FIO, 0x02E, 0x0008C, 0x0, "UL 350 Lasi Core RS-232"},
+ {HPHW_FIO, 0x02F, 0x0008C, 0x0, "UL 550 Lasi Core RS-232"},
+ {HPHW_FIO, 0x030, 0x0008C, 0x0, "UL 350 Wax Core RS-232"},
+ {HPHW_FIO, 0x031, 0x0008C, 0x0, "UL 550 Wax Core RS-232"},
+ {HPHW_FIO, 0x032, 0x0008C, 0x0, "Raven T' Lasi Core RS-232"},
+ {HPHW_FIO, 0x033, 0x0008C, 0x0, "Anole T Core RS-232"},
+ {HPHW_FIO, 0x034, 0x0008C, 0x0, "SAIC L-80 Core RS-232"},
+ {HPHW_FIO, 0x035, 0x0008C, 0x0, "PCX-L2 712/132 Core RS-232"},
+ {HPHW_FIO, 0x036, 0x0008C, 0x0, "PCX-L2 712/160 Core RS-232"},
+ {HPHW_FIO, 0x03A, 0x0008C, 0x0, "Merlin+ Wax RS-232"},
+ {HPHW_FIO, 0x03B, 0x0008C, 0x0, "Raven U/L2 Core RS-232"},
+ {HPHW_FIO, 0x03C, 0x0008C, 0x0, "Merlin 132 Core RS-232"},
+ {HPHW_FIO, 0x03D, 0x0008C, 0x0, "Merlin 160 Core RS-232"},
+ {HPHW_FIO, 0x03E, 0x0008C, 0x0, "Merlin+ 132 Core RS-232"},
+ {HPHW_FIO, 0x03F, 0x0008C, 0x0, "Merlin+ 180 Core RS-232"},
+ {HPHW_FIO, 0x040, 0x0008C, 0x0, "Merlin 132 Wax RS-232"},
+ {HPHW_FIO, 0x041, 0x0008C, 0x0, "Merlin 160 Wax RS-232"},
+ {HPHW_FIO, 0x043, 0x0008C, 0x0, "Merlin 132/160 Wax RS-232"},
+ {HPHW_FIO, 0x044, 0x0008C, 0x0, "Mohawk Core RS-232"},
+ {HPHW_FIO, 0x045, 0x0008C, 0x0, "Rocky1 Core RS-232"},
+ {HPHW_FIO, 0x046, 0x0008C, 0x0, "Rocky2 120 Core RS-232"},
+ {HPHW_FIO, 0x047, 0x0008C, 0x0, "Rocky2 150 Core RS-232"},
+ {HPHW_FIO, 0x048, 0x0008C, 0x0, "Rocky2 120 Dino RS-232"},
+ {HPHW_FIO, 0x049, 0x0008C, 0x0, "Rocky2 150 Dino RS-232"},
+ {HPHW_FIO, 0x04A, 0x0008C, 0x0, "Anole L2 132 TIMI RS-232"},
+ {HPHW_FIO, 0x04B, 0x0008C, 0x0, "Anole L2 l32 Core RS-232"},
+ {HPHW_FIO, 0x04C, 0x0008D, 0x0, "Anole L2 165 TIMI RS-232"},
+ {HPHW_FIO, 0x04D, 0x0008C, 0x0, "Anole L2 165 Core RS-232"},
+ {HPHW_FIO, 0x04E, 0x0008C, 0x0, "Kiji L2 132 Core RS-232"},
+ {HPHW_FIO, 0x04F, 0x0008C, 0x0, "Kiji L2 132 Dino RS-232"},
+ {HPHW_FIO, 0x050, 0x0008C, 0x0, "Merlin Jr 132 Core RS-232"},
+ {HPHW_FIO, 0x051, 0x0008C, 0x0, "Firehawk Core RS-232"},
+ {HPHW_FIO, 0x052, 0x0008C, 0x0, "Raven+ Hi Power Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x053, 0x0008C, 0x0, "Raven+ Hi Power Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x054, 0x0008C, 0x0, "Raven+ Lo Power Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x055, 0x0008C, 0x0, "Raven+ Lo Power Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x056, 0x0008C, 0x0, "Raven+ w SE FWSCSI Core RS-232"},
+ {HPHW_FIO, 0x057, 0x0008C, 0x0, "Raven+ w Diff FWSCSI Core RS-232"},
+ {HPHW_FIO, 0x058, 0x0008C, 0x0, "FireHawk 200 Core RS-232"},
+ {HPHW_FIO, 0x059, 0x0008C, 0x0, "FireHawk 200 Wax RS-232"},
+ {HPHW_FIO, 0x05A, 0x0008C, 0x0, "Raven+ L2 Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x05B, 0x0008C, 0x0, "Raven+ L2 Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x05D, 0x0008C, 0x0, "SummitHawk Dino RS-232"},
+ {HPHW_FIO, 0x05E, 0x0008C, 0x0, "Staccato 132 Core LAN RS-232"},
+ {HPHW_FIO, 0x05F, 0x0008C, 0x0, "Staccato 180 Core LAN RS-232"},
+ {HPHW_FIO, 0x800, 0x0008C, 0x0, "Hitachi Tiny 64 Core RS-232"},
+ {HPHW_FIO, 0x801, 0x0008C, 0x0, "Hitachi Tiny 80 Core RS-232"},
+ {HPHW_FIO, 0x015, 0x0008D, 0x0, "Gecko Optional RJ-16"},
+ {HPHW_FIO, 0x016, 0x0008D, 0x0, "Gecko Core RJ-16"},
+ {HPHW_FIO, 0x01C, 0x0008D, 0x0, "Gecko 80 Core RJ-16"},
+ {HPHW_FIO, 0x01D, 0x0008D, 0x0, "Gecko 100 Core RJ-16"},
+ {HPHW_FIO, 0x004, 0x0008F, 0x0, "Anole Boot Rom"},
+ {HPHW_FIO, 0x005, 0x0008F, 0x0, "Rocky1 Boot Rom"},
+ {HPHW_FIO, 0x006, 0x0008F, 0x0, "Rocky2 120 Boot Rom"},
+ {HPHW_FIO, 0x007, 0x0008F, 0x0, "Rocky2 150 Boot Rom"},
+ {HPHW_FIO, 0x01B, 0x0008F, 0x0, "Anole 100 Boot Rom"},
+ {HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS/2 Port"},
+ {HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS/2 Port"},
+ {HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS/2 Port"},
+ {HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS/2 Port"},
+ {HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS/2 Port"},
+ {HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS/2 Port"},
+ {HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS/2 Port"},
+ {HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG LAN"},
+ {HPHW_FIO, 0x023, 0x00099, 0x0, "Rocky1 Wax HPIB"},
+ {HPHW_FIO, 0x048, 0x00099, 0x0, "Rocky2 120 Clark/Dino HPIB"},
+ {HPHW_FIO, 0x049, 0x00099, 0x0, "Rocky2 150 Clark/Dino HPIB"},
+ {HPHW_FIO, 0x004, 0x000A1, 0x0, "SPP2000 Console TTY"},
+ {HPHW_FIO, 0x004, 0x000A2, 0x0, "Forte Core PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x005, 0x000A2, 0x0, "AllegroLow PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x006, 0x000A2, 0x0, "AllegroHIgh Core PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in LAN"},
+ {HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI LAN"},
+ {HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI LAN"},
+ {HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI LAN"},
+ {HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI LAN"},
+ {HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI LAN"},
+ {HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI LAN"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI SE UltraSCSI"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x007, 0x000A3, 0x0, "PCI Plug-in Disk"},
+ {HPHW_FIO, 0x008, 0x000A3, 0x0, "A5158A S FC Tachlite HBA"},
+ {HPHW_FIO, 0x009, 0x000A3, 0x0, "A5157A D FC HBA"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI NSE UltraSCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI WSE UltraSCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x03E, 0x000A3, 0x0, "Merlin+ 132 Core SE FWSCSI PCI Disk"},
+ {HPHW_FIO, 0x03F, 0x000A3, 0x0, "Merlin+ 180 Core SE FWSCSI PCI Disk"},
+ {HPHW_FIO, 0x056, 0x000A3, 0x0, "Raven+ w SE FWSCSI Core PCI Disk"},
+ {HPHW_FIO, 0x057, 0x000A3, 0x0, "Raven+ w Diff FWSCSI Core PCI Disk"},
+ {HPHW_FIO, 0x004, 0x000A4, 0x0, "SPP2000 Core BA"},
+ {HPHW_FIO, 0x004, 0x000A6, 0x0, "Sonic Ethernet 802.3 Card"},
+ {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI USB KB"},
+ {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI USB KB"},
+ {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI USB KB"},
+ {HPHW_FIO, 0x007, 0x000A9, 0x0, "Miscelaneous PCI Plug-in"},
+ {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI USB KB"},
+ {HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"},
+ {HPHW_FIO, 0x004, 0x00340, 0x0, "BARCO CX4500 VME Grphx Cnsl"},
+ {HPHW_FIO, 0x004, 0x00360, 0x0, "Hughes TOG VME FDDI"},
+ {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"},
+ {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"},
+ {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"},
+ {HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"},
+ {HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"},
+ {HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"},
+ {HPHW_IOA, 0x880, 0x0000C, 0x10, "Pluto BC McKinley Port"},
+ {HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"},
+ {HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"},
+ {HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"},
+ {HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"},
+ {HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"},
+ {HPHW_MEMORY, 0x0AF, 0x00009, 0x00, "Everest Mako Memory"},
+ {HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"},
+ {HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"},
+ {HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"},
+ {HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"},
+ {HPHW_MC, 0x004, 0x000C0, 0x00, "BMC IPMI Mgmt Ctlr"},
+ {HPHW_FAULTY, 0, } /* Special Marker for last entry */
+};
+
+
+static struct hp_cpu_type_mask {
+ unsigned short model;
+ unsigned short mask;
+ enum cpu_type cpu;
+} hp_cpu_type_mask_list[] __initdata = {
+
+ { 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */
+ { 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */
+ { 0x0080, 0x0ff0, pcx }, /* 0x0080 - 0x008f */
+ { 0x0100, 0x0ff0, pcx }, /* 0x0100 - 0x010f */
+ { 0x0182, 0x0ffe, pcx }, /* 0x0182 - 0x0183 */
+ { 0x0182, 0x0ffe, pcxt }, /* 0x0182 - 0x0183 */
+ { 0x0184, 0x0fff, pcxu }, /* 0x0184 - 0x0184 */
+ { 0x0200, 0x0ffe, pcxs }, /* 0x0200 - 0x0201 */
+ { 0x0202, 0x0fff, pcxs }, /* 0x0202 - 0x0202 */
+ { 0x0203, 0x0fff, pcxt }, /* 0x0203 - 0x0203 */
+ { 0x0204, 0x0ffc, pcxt }, /* 0x0204 - 0x0207 */
+ { 0x0280, 0x0ffc, pcxs }, /* 0x0280 - 0x0283 */
+ { 0x0284, 0x0ffc, pcxt }, /* 0x0284 - 0x0287 */
+ { 0x0288, 0x0fff, pcxt }, /* 0x0288 - 0x0288 */
+ { 0x0300, 0x0ffc, pcxs }, /* 0x0300 - 0x0303 */
+ { 0x0310, 0x0ff0, pcxt }, /* 0x0310 - 0x031f */
+ { 0x0320, 0x0ff0, pcxt }, /* 0x0320 - 0x032f */
+ { 0x0400, 0x0ff0, pcxt }, /* 0x0400 - 0x040f */
+ { 0x0480, 0x0ff0, pcxl }, /* 0x0480 - 0x048f */
+ { 0x0500, 0x0ff0, pcxl2 }, /* 0x0500 - 0x050f */
+ { 0x0510, 0x0ff0, pcxl2 }, /* 0x0510 - 0x051f */
+ { 0x0580, 0x0ff8, pcxt_ }, /* 0x0580 - 0x0587 */
+ { 0x0588, 0x0ffc, pcxt_ }, /* 0x0588 - 0x058b */
+ { 0x058c, 0x0ffe, pcxt_ }, /* 0x058c - 0x058d */
+ { 0x058e, 0x0fff, pcxt_ }, /* 0x058e - 0x058e */
+ { 0x058f, 0x0fff, pcxu }, /* 0x058f - 0x058f */
+ { 0x0590, 0x0ffe, pcxu }, /* 0x0590 - 0x0591 */
+ { 0x0592, 0x0fff, pcxt_ }, /* 0x0592 - 0x0592 */
+ { 0x0593, 0x0fff, pcxu }, /* 0x0593 - 0x0593 */
+ { 0x0594, 0x0ffc, pcxu }, /* 0x0594 - 0x0597 */
+ { 0x0598, 0x0ffe, pcxu_ }, /* 0x0598 - 0x0599 */
+ { 0x059a, 0x0ffe, pcxu }, /* 0x059a - 0x059b */
+ { 0x059c, 0x0fff, pcxu }, /* 0x059c - 0x059c */
+ { 0x059d, 0x0fff, pcxu_ }, /* 0x059d - 0x059d */
+ { 0x059e, 0x0fff, pcxt_ }, /* 0x059e - 0x059e */
+ { 0x059f, 0x0fff, pcxu }, /* 0x059f - 0x059f */
+ { 0x05a0, 0x0ffe, pcxt_ }, /* 0x05a0 - 0x05a1 */
+ { 0x05a2, 0x0ffe, pcxu }, /* 0x05a2 - 0x05a3 */
+ { 0x05a4, 0x0ffc, pcxu }, /* 0x05a4 - 0x05a7 */
+ { 0x05a8, 0x0ffc, pcxu }, /* 0x05a8 - 0x05ab */
+ { 0x05ad, 0x0fff, pcxu_ }, /* 0x05ad - 0x05ad */
+ { 0x05ae, 0x0ffe, pcxu_ }, /* 0x05ae - 0x05af */
+ { 0x05b0, 0x0ffe, pcxu_ }, /* 0x05b0 - 0x05b1 */
+ { 0x05b2, 0x0fff, pcxu_ }, /* 0x05b2 - 0x05b2 */
+ { 0x05b3, 0x0fff, pcxu }, /* 0x05b3 - 0x05b3 */
+ { 0x05b4, 0x0fff, pcxw }, /* 0x05b4 - 0x05b4 */
+ { 0x05b5, 0x0fff, pcxu_ }, /* 0x05b5 - 0x05b5 */
+ { 0x05b6, 0x0ffe, pcxu_ }, /* 0x05b6 - 0x05b7 */
+ { 0x05b8, 0x0ffe, pcxu_ }, /* 0x05b8 - 0x05b9 */
+ { 0x05ba, 0x0fff, pcxu_ }, /* 0x05ba - 0x05ba */
+ { 0x05bb, 0x0fff, pcxw }, /* 0x05bb - 0x05bb */
+ { 0x05bc, 0x0ffc, pcxw }, /* 0x05bc - 0x05bf */
+ { 0x05c0, 0x0ffc, pcxw }, /* 0x05c0 - 0x05c3 */
+ { 0x05c4, 0x0ffe, pcxw }, /* 0x05c4 - 0x05c5 */
+ { 0x05c6, 0x0fff, pcxw }, /* 0x05c6 - 0x05c6 */
+ { 0x05c7, 0x0fff, pcxw_ }, /* 0x05c7 - 0x05c7 */
+ { 0x05c8, 0x0ffc, pcxw }, /* 0x05c8 - 0x05cb */
+ { 0x05cc, 0x0ffe, pcxw }, /* 0x05cc - 0x05cd */
+ { 0x05ce, 0x0ffe, pcxw_ }, /* 0x05ce - 0x05cf */
+ { 0x05d0, 0x0ffc, pcxw_ }, /* 0x05d0 - 0x05d3 */
+ { 0x05d4, 0x0ffe, pcxw_ }, /* 0x05d4 - 0x05d5 */
+ { 0x05d6, 0x0fff, pcxw }, /* 0x05d6 - 0x05d6 */
+ { 0x05d7, 0x0fff, pcxw_ }, /* 0x05d7 - 0x05d7 */
+ { 0x05d8, 0x0ffc, pcxw_ }, /* 0x05d8 - 0x05db */
+ { 0x05dc, 0x0ffe, pcxw2 }, /* 0x05dc - 0x05dd */
+ { 0x05de, 0x0fff, pcxw_ }, /* 0x05de - 0x05de */
+ { 0x05df, 0x0fff, pcxw2 }, /* 0x05df - 0x05df */
+ { 0x05e0, 0x0ffc, pcxw2 }, /* 0x05e0 - 0x05e3 */
+ { 0x05e4, 0x0fff, pcxw2 }, /* 0x05e4 - 0x05e4 */
+ { 0x05e5, 0x0fff, pcxw_ }, /* 0x05e5 - 0x05e5 */
+ { 0x05e6, 0x0ffe, pcxw2 }, /* 0x05e6 - 0x05e7 */
+ { 0x05e8, 0x0ff8, pcxw2 }, /* 0x05e8 - 0x05ef */
+ { 0x05f0, 0x0ff0, pcxw2 }, /* 0x05f0 - 0x05ff */
+ { 0x0600, 0x0fe0, pcxl }, /* 0x0600 - 0x061f */
+ { 0x0880, 0x0ff0, mako }, /* 0x0880 - 0x088f */
+ { 0x0000, 0x0000, pcx } /* terminate table */
+};
+
+char *cpu_name_version[][2] = {
+ [pcx] = { "PA7000 (PCX)", "1.0" },
+ [pcxs] = { "PA7000 (PCX-S)", "1.1a" },
+ [pcxt] = { "PA7100 (PCX-T)", "1.1b" },
+ [pcxt_] = { "PA7200 (PCX-T')", "1.1c" },
+ [pcxl] = { "PA7100LC (PCX-L)", "1.1d" },
+ [pcxl2] = { "PA7300LC (PCX-L2)", "1.1e" },
+ [pcxu] = { "PA8000 (PCX-U)", "2.0" },
+ [pcxu_] = { "PA8200 (PCX-U+)", "2.0" },
+ [pcxw] = { "PA8500 (PCX-W)", "2.0" },
+ [pcxw_] = { "PA8600 (PCX-W+)", "2.0" },
+ [pcxw2] = { "PA8700 (PCX-W2)", "2.0" },
+ [mako] = { "PA8800 (Mako)", "2.0" }
+};
+
+const char * __init
+parisc_hardware_description(struct parisc_device_id *id)
+{
+ struct hp_hardware *listptr;
+
+ for (listptr = hp_hardware_list; listptr->hw_type != HPHW_FAULTY; listptr++) {
+ if ((listptr->hw_type == id->hw_type) &&
+ (listptr->hversion == id->hversion) &&
+ (listptr->sversion == id->sversion)){
+ return listptr->name;
+ }
+ }
+
+ /*
+ * ok, the above hardware table isn't complete, and we haven't found
+ * our device in this table. So let's now try to find a generic name
+ * to describe the given hardware...
+ */
+ switch (id->hw_type) {
+ case HPHW_NPROC:
+ return "Unknown machine";
+
+ case HPHW_A_DIRECT:
+ switch (id->sversion) {
+ case 0x0D: return "MUX port";
+ case 0x0E: return "RS-232 port";
+ }
+ break;
+
+ case HPHW_MEMORY:
+ return "Memory";
+
+ }
+
+ return "unknown device";
+}
+
+
+/* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */
+enum cpu_type __init
+parisc_get_cpu_type(unsigned long hversion)
+{
+ struct hp_cpu_type_mask *ptr;
+ unsigned short model = ((unsigned short) (hversion)) >> 4;
+
+ for (ptr = hp_cpu_type_mask_list; 0 != ptr->mask; ptr++) {
+ if (ptr->model == (model & ptr->mask))
+ return ptr->cpu;
+ }
+ panic("could not identify CPU type\n");
+
+ return pcx; /* not reached: */
+}
+
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
new file mode 100644
index 000000000000..ddf7e914f15e
--- /dev/null
+++ b/arch/parisc/kernel/head.S
@@ -0,0 +1,386 @@
+/* This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 by Helge Deller
+ * Copyright 1999 SuSE GmbH (Philipp Rumpf)
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com)
+ * Copyright (C) 2001 Grant Grundler (Hewlett Packard)
+ * Copyright (C) 2004 Kyle McMartin <kyle@debian.org>
+ *
+ * Initial Version 04-23-1999 by Helge Deller <deller@gmx.de>
+ */
+
+#include <linux/autoconf.h> /* for CONFIG_SMP */
+
+#include <asm/offsets.h>
+#include <asm/psw.h>
+#include <asm/pdc.h>
+
+#include <asm/assembly.h>
+#include <asm/pgtable.h>
+
+ .level LEVEL
+
+ .data
+
+ .export boot_args
+boot_args:
+ .word 0 /* arg0 */
+ .word 0 /* arg1 */
+ .word 0 /* arg2 */
+ .word 0 /* arg3 */
+
+ .text
+ .align 4
+ .import init_thread_union,data
+ .import fault_vector_20,code /* IVA parisc 2.0 32 bit */
+#ifndef __LP64__
+ .import fault_vector_11,code /* IVA parisc 1.1 32 bit */
+ .import $global$ /* forward declaration */
+#endif /*!LP64*/
+ .export stext
+ .export _stext,data /* Kernel want it this way! */
+_stext:
+stext:
+ .proc
+ .callinfo
+
+ /* Make sure sr4-sr7 are set to zero for the kernel address space */
+ mtsp %r0,%sr4
+ mtsp %r0,%sr5
+ mtsp %r0,%sr6
+ mtsp %r0,%sr7
+
+ /* Clear BSS (shouldn't the boot loader do this?) */
+
+ .import __bss_start,data
+ .import __bss_stop,data
+
+ load32 PA(__bss_start),%r3
+ load32 PA(__bss_stop),%r4
+$bss_loop:
+ cmpb,<<,n %r3,%r4,$bss_loop
+ stw,ma %r0,4(%r3)
+
+ /* Save away the arguments the boot loader passed in (32 bit args) */
+ load32 PA(boot_args),%r1
+ stw,ma %arg0,4(%r1)
+ stw,ma %arg1,4(%r1)
+ stw,ma %arg2,4(%r1)
+ stw,ma %arg3,4(%r1)
+
+ /* Initialize startup VM. Just map first 8/16 MB of memory */
+ load32 PA(swapper_pg_dir),%r4
+ mtctl %r4,%cr24 /* Initialize kernel root pointer */
+ mtctl %r4,%cr25 /* Initialize user root pointer */
+
+#ifdef __LP64__
+ /* Set pmd in pgd */
+ load32 PA(pmd0),%r5
+ shrd %r5,PxD_VALUE_SHIFT,%r3
+ ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
+ stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
+ ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
+#else
+ /* 2-level page table, so pmd == pgd */
+ ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
+#endif
+
+ /* Fill in pmd with enough pte directories */
+ load32 PA(pg0),%r1
+ SHRREG %r1,PxD_VALUE_SHIFT,%r3
+ ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
+
+ ldi ASM_PT_INITIAL,%r1
+
+1:
+ stw %r3,0(%r4)
+ ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
+ addib,> -1,%r1,1b
+#ifdef __LP64__
+ ldo ASM_PMD_ENTRY_SIZE(%r4),%r4
+#else
+ ldo ASM_PGD_ENTRY_SIZE(%r4),%r4
+#endif
+
+
+ /* Now initialize the PTEs themselves */
+ ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+ load32 PA(pg0),%r1
+
+$pgt_fill_loop:
+ STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1)
+ ldo ASM_PAGE_SIZE(%r3),%r3
+ bb,>= %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop
+ nop
+
+ /* Load the return address...er...crash 'n burn */
+ copy %r0,%r2
+
+ /* And the RFI Target address too */
+ load32 start_kernel,%r11
+
+ /* And the initial task pointer */
+ load32 init_thread_union,%r6
+ mtctl %r6,%cr30
+
+ /* And the stack pointer too */
+ ldo THREAD_SZ_ALGN(%r6),%sp
+
+ /* And the interrupt stack */
+ load32 interrupt_stack,%r6
+ mtctl %r6,%cr31
+
+#ifdef CONFIG_SMP
+ /* Set the smp rendevous address into page zero.
+ ** It would be safer to do this in init_smp_config() but
+ ** it's just way easier to deal with here because
+ ** of 64-bit function ptrs and the address is local to this file.
+ */
+ load32 PA(smp_slave_stext),%r10
+ stw %r10,0x10(%r0) /* MEM_RENDEZ */
+ stw %r0,0x28(%r0) /* MEM_RENDEZ_HI - assume addr < 4GB */
+
+ /* FALLTHROUGH */
+ .procend
+
+ /*
+ ** Code Common to both Monarch and Slave processors.
+ ** Entry:
+ **
+ ** 1.1:
+ ** %r11 must contain RFI target address.
+ ** %r25/%r26 args to pass to target function
+ ** %r2 in case rfi target decides it didn't like something
+ **
+ ** 2.0w:
+ ** %r3 PDCE_PROC address
+ ** %r11 RFI target address
+ **
+ ** Caller must init: SR4-7, %sp, %r10, %cr24/25,
+ */
+common_stext:
+ .proc
+ .callinfo
+#else
+ /* Clear PDC entry point - we won't use it */
+ stw %r0,0x10(%r0) /* MEM_RENDEZ */
+ stw %r0,0x28(%r0) /* MEM_RENDEZ_HI */
+#endif /*CONFIG_SMP*/
+
+#ifdef __LP64__
+ tophys_r1 %sp
+
+ /* Save the rfi target address */
+ ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10
+ tophys_r1 %r10
+ std %r11, TASK_PT_GR11(%r10)
+ /* Switch to wide mode Superdome doesn't support narrow PDC
+ ** calls.
+ */
+1: mfia %rp /* clear upper part of pcoq */
+ ldo 2f-1b(%rp),%rp
+ depdi 0,31,32,%rp
+ bv (%rp)
+ ssm PSW_SM_W,%r0
+
+ /* Set Wide mode as the "Default" (eg for traps)
+ ** First trap occurs *right* after (or part of) rfi for slave CPUs.
+ ** Someday, palo might not do this for the Monarch either.
+ */
+2:
+#define MEM_PDC_LO 0x388
+#define MEM_PDC_HI 0x35C
+ ldw MEM_PDC_LO(%r0),%r3
+ ldw MEM_PDC_HI(%r0),%r6
+ depd %r6, 31, 32, %r3 /* move to upper word */
+
+ ldo PDC_PSW(%r0),%arg0 /* 21 */
+ ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */
+ ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */
+ load32 PA(stext_pdc_ret), %rp
+ bv (%r3)
+ copy %r0,%arg3
+
+stext_pdc_ret:
+ /* restore rfi target address*/
+ ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10
+ tophys_r1 %r10
+ ldd TASK_PT_GR11(%r10), %r11
+ tovirt_r1 %sp
+#endif
+
+ /* PARANOID: clear user scratch/user space SR's */
+ mtsp %r0,%sr0
+ mtsp %r0,%sr1
+ mtsp %r0,%sr2
+ mtsp %r0,%sr3
+
+ /* Initialize Protection Registers */
+ mtctl %r0,%cr8
+ mtctl %r0,%cr9
+ mtctl %r0,%cr12
+ mtctl %r0,%cr13
+
+ /* Prepare to RFI! Man all the cannons! */
+
+ /* Initialize the global data pointer */
+ loadgp
+
+ /* Set up our interrupt table. HPMCs might not work after this!
+ *
+ * We need to install the correct iva for PA1.1 or PA2.0. The
+ * following short sequence of instructions can determine this
+ * (without being illegal on a PA1.1 machine).
+ */
+#ifndef __LP64__
+ ldi 32,%r10
+ mtctl %r10,%cr11
+ .level 2.0
+ mfctl,w %cr11,%r10
+ .level 1.1
+ comib,<>,n 0,%r10,$is_pa20
+ ldil L%PA(fault_vector_11),%r10
+ b $install_iva
+ ldo R%PA(fault_vector_11)(%r10),%r10
+
+$is_pa20:
+ .level LEVEL /* restore 1.1 || 2.0w */
+#endif /*!LP64*/
+ load32 PA(fault_vector_20),%r10
+
+$install_iva:
+ mtctl %r10,%cr14
+
+#ifdef __LP64__
+ b aligned_rfi
+ nop
+
+ .align 256
+aligned_rfi:
+ ssm 0,0
+ nop /* 1 */
+ nop /* 2 */
+ nop /* 3 */
+ nop /* 4 */
+ nop /* 5 */
+ nop /* 6 */
+ nop /* 7 */
+ nop /* 8 */
+#endif
+
+#ifdef __LP64__ /* move to psw.h? */
+#define PSW_BITS PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R
+#else
+#define PSW_BITS PSW_SM_Q
+#endif
+
+$rfi:
+ /* turn off troublesome PSW bits */
+ rsm PSW_BITS,%r0
+
+ /* kernel PSW:
+ * - no interruptions except HPMC and TOC (which are handled by PDC)
+ * - Q bit set (IODC / PDC interruptions)
+ * - big-endian
+ * - virtually mapped
+ */
+ load32 KERNEL_PSW,%r10
+ mtctl %r10,%ipsw
+
+ /* Set the space pointers for the post-RFI world
+ ** Clear the two-level IIA Space Queue, effectively setting
+ ** Kernel space.
+ */
+ mtctl %r0,%cr17 /* Clear IIASQ tail */
+ mtctl %r0,%cr17 /* Clear IIASQ head */
+
+ /* Load RFI target into PC queue */
+ mtctl %r11,%cr18 /* IIAOQ head */
+ ldo 4(%r11),%r11
+ mtctl %r11,%cr18 /* IIAOQ tail */
+
+ /* Jump to hyperspace */
+ rfi
+ nop
+
+ .procend
+
+#ifdef CONFIG_SMP
+
+ .import smp_init_current_idle_task,data
+ .import smp_callin,code
+
+#ifndef __LP64__
+smp_callin_rtn:
+ .proc
+ .callinfo
+ break 1,1 /* Break if returned from start_secondary */
+ nop
+ nop
+ .procend
+#endif /*!LP64*/
+
+/***************************************************************************
+* smp_slave_stext is executed by all non-monarch Processors when the Monarch
+* pokes the slave CPUs in smp.c:smp_boot_cpus().
+*
+* Once here, registers values are initialized in order to branch to virtual
+* mode. Once all available/eligible CPUs are in virtual mode, all are
+* released and start out by executing their own idle task.
+*****************************************************************************/
+smp_slave_stext:
+ .proc
+ .callinfo
+
+ /*
+ ** Initialize Space registers
+ */
+ mtsp %r0,%sr4
+ mtsp %r0,%sr5
+ mtsp %r0,%sr6
+ mtsp %r0,%sr7
+
+ /* Initialize the SP - monarch sets up smp_init_current_idle_task */
+ load32 PA(smp_init_current_idle_task),%sp
+ LDREG 0(%sp),%sp /* load task address */
+ tophys_r1 %sp
+ LDREG TASK_THREAD_INFO(%sp),%sp
+ mtctl %sp,%cr30 /* store in cr30 */
+ ldo THREAD_SZ_ALGN(%sp),%sp
+
+ /* point CPU to kernel page tables */
+ load32 PA(swapper_pg_dir),%r4
+ mtctl %r4,%cr24 /* Initialize kernel root pointer */
+ mtctl %r4,%cr25 /* Initialize user root pointer */
+
+#ifdef __LP64__
+ /* Setup PDCE_PROC entry */
+ copy %arg0,%r3
+#else
+ /* Load RFI *return* address in case smp_callin bails */
+ load32 smp_callin_rtn,%r2
+#endif
+
+ /* Load RFI target address. */
+ load32 smp_callin,%r11
+
+ /* ok...common code can handle the rest */
+ b common_stext
+ nop
+
+ .procend
+#endif /* CONFIG_SMP */
+#ifndef __LP64__
+ .data
+
+ .align 4
+ .export $global$,data
+
+ .type $global$,@object
+ .size $global$,4
+$global$:
+ .word 0
+#endif /*!LP64*/
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
new file mode 100644
index 000000000000..c412c0adc4a9
--- /dev/null
+++ b/arch/parisc/kernel/hpmc.S
@@ -0,0 +1,304 @@
+/*
+ * HPMC (High Priority Machine Check) handler.
+ *
+ * Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/*
+ * This HPMC handler retrieves the HPMC pim data, resets IO and
+ * returns to the default trap handler with code set to 1 (HPMC).
+ * The default trap handler calls handle interruption, which
+ * does a stack and register dump. This at least allows kernel
+ * developers to get back to C code in virtual mode, where they
+ * have the option to examine and print values from memory that
+ * would help in debugging an HPMC caused by a software bug.
+ *
+ * There is more to do here:
+ *
+ * 1) On MP systems we need to synchronize processors
+ * before calling pdc/iodc.
+ * 2) We should be checking the system state and not
+ * returning to the fault handler if things are really
+ * bad.
+ *
+ */
+
+ .level 1.1
+ .data
+
+#include <asm/assembly.h>
+#include <asm/pdc.h>
+
+ /*
+ * stack for os_hpmc, the HPMC handler.
+ * buffer for IODC procedures (for the HPMC handler).
+ *
+ * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc.
+ */
+
+ .align 4096
+hpmc_stack:
+ .block 16384
+
+#define HPMC_IODC_BUF_SIZE 0x8000
+
+ .align 4096
+hpmc_iodc_buf:
+ .block HPMC_IODC_BUF_SIZE
+
+ .align 8
+hpmc_raddr:
+ .block 128
+
+#define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */
+
+ .export hpmc_pim_data, data
+ .align 8
+hpmc_pim_data:
+ .block HPMC_PIM_DATA_SIZE
+
+ .text
+
+ .export os_hpmc, code
+ .import intr_save, code
+
+os_hpmc:
+
+ /*
+ * registers modified:
+ *
+ * Using callee saves registers without saving them. The
+ * original values are in the pim dump if we need them.
+ *
+ * r2 (rp) return pointer
+ * r3 address of PDCE_PROC
+ * r4 scratch
+ * r5 scratch
+ * r23 (arg3) procedure arg
+ * r24 (arg2) procedure arg
+ * r25 (arg1) procedure arg
+ * r26 (arg0) procedure arg
+ * r30 (sp) stack pointer
+ *
+ * registers read:
+ *
+ * r26 contains address of PDCE_PROC on entry
+ * r28 (ret0) return value from procedure
+ */
+
+ copy arg0, %r3 /* save address of PDCE_PROC */
+
+ /*
+ * disable nested HPMCs
+ *
+ * Increment os_hpmc checksum to invalidate it.
+ * Do this before turning the PSW M bit off.
+ */
+
+ mfctl %cr14, %r4
+ ldw 52(%r4),%r5
+ addi 1,%r5,%r5
+ stw %r5,52(%r4)
+
+ /* MP_FIXME: synchronize all processors. */
+
+ /* Setup stack pointer. */
+
+ load32 PA(hpmc_stack),sp
+
+ ldo 128(sp),sp /* leave room for arguments */
+
+ /*
+ * Most PDC routines require that the M bit be off.
+ * So turn on the Q bit and turn off the M bit.
+ */
+
+ ldo 8(%r0),%r4 /* PSW Q on, PSW M off */
+ mtctl %r4,ipsw
+ mtctl %r0,pcsq
+ mtctl %r0,pcsq
+ load32 PA(os_hpmc_1),%r4
+ mtctl %r4,pcoq
+ ldo 4(%r4),%r4
+ mtctl %r4,pcoq
+ rfi
+ nop
+
+os_hpmc_1:
+
+ /* Call PDC_PIM to get HPMC pim info */
+
+ /*
+ * Note that on some newer boxes, PDC_PIM must be called
+ * before PDC_IO if you want IO to be reset. PDC_PIM sets
+ * a flag that PDC_IO examines.
+ */
+
+ ldo PDC_PIM(%r0), arg0
+ ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */
+ load32 PA(hpmc_raddr),arg2
+ load32 PA(hpmc_pim_data),arg3
+ load32 HPMC_PIM_DATA_SIZE,%r4
+ stw %r4,-52(sp)
+
+ ldil L%PA(os_hpmc_2), rp
+ bv (r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_2)(rp), rp
+
+os_hpmc_2:
+ comib,<> 0,ret0, os_hpmc_fail
+
+ /* Reset IO by calling the hversion dependent PDC_IO routine */
+
+ ldo PDC_IO(%r0),arg0
+ ldo 0(%r0),arg1 /* log IO errors */
+ ldo 0(%r0),arg2 /* reserved */
+ ldo 0(%r0),arg3 /* reserved */
+ stw %r0,-52(sp) /* reserved */
+
+ ldil L%PA(os_hpmc_3),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_3)(rp),rp
+
+os_hpmc_3:
+
+ /* FIXME? Check for errors from PDC_IO (-1 might be OK) */
+
+ /*
+ * Initialize the IODC console device (HPA,SPA, path etc.
+ * are stored on page 0.
+ */
+
+ /*
+ * Load IODC into hpmc_iodc_buf by calling PDC_IODC.
+ * Note that PDC_IODC handles flushing the appropriate
+ * data and instruction cache lines.
+ */
+
+ ldo PDC_IODC(%r0),arg0
+ ldo PDC_IODC_READ(%r0),arg1
+ load32 PA(hpmc_raddr),arg2
+ ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */
+ ldo PDC_IODC_RI_INIT(%r0),%r4
+ stw %r4,-52(sp)
+ load32 PA(hpmc_iodc_buf),%r4
+ stw %r4,-56(sp)
+ load32 HPMC_IODC_BUF_SIZE,%r4
+ stw %r4,-60(sp)
+
+ ldil L%PA(os_hpmc_4),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_4)(rp),rp
+
+os_hpmc_4:
+ comib,<> 0,ret0,os_hpmc_fail
+
+ /* Call the entry init (just loaded by PDC_IODC) */
+
+ ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg0 /* console hpa */
+ ldo ENTRY_INIT_MOD_DEV(%r0), arg1
+ ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */
+ depi 0,31,11,arg2 /* clear bits 21-31 */
+ ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */
+ load32 PA(hpmc_raddr),%r4
+ stw %r4, -52(sp)
+ stw %r0, -56(sp) /* HV */
+ stw %r0, -60(sp) /* HV */
+ stw %r0, -64(sp) /* HV */
+ stw %r0, -68(sp) /* lang, must be zero */
+
+ load32 PA(hpmc_iodc_buf),%r5
+ ldil L%PA(os_hpmc_5),rp
+ bv (%r5)
+ ldo R%PA(os_hpmc_5)(rp),rp
+
+os_hpmc_5:
+ comib,<> 0,ret0,os_hpmc_fail
+
+ /* Prepare to call intr_save */
+
+ /*
+ * Load kernel page directory (load into user also, since
+ * we don't intend to ever return to user land anyway)
+ */
+
+ load32 PA(swapper_pg_dir),%r4
+ mtctl %r4,%cr24 /* Initialize kernel root pointer */
+ mtctl %r4,%cr25 /* Initialize user root pointer */
+
+ /* Clear sr4-sr7 */
+
+ mtsp %r0, %sr4
+ mtsp %r0, %sr5
+ mtsp %r0, %sr6
+ mtsp %r0, %sr7
+
+ tovirt_r1 %r30 /* make sp virtual */
+
+ rsm 8,%r0 /* Clear Q bit */
+ ldi 1,%r8 /* Set trap code to "1" for HPMC */
+ load32 PA(intr_save),%r1
+ be 0(%sr7,%r1)
+ nop
+
+os_hpmc_fail:
+
+ /*
+ * Reset the system
+ *
+ * Some systems may lockup from a broadcast reset, so try the
+ * hversion PDC_BROADCAST_RESET() first.
+ * MP_FIXME: reset all processors if more than one central bus.
+ */
+
+ /* PDC_BROADCAST_RESET() */
+
+ ldo PDC_BROADCAST_RESET(%r0),arg0
+ ldo 0(%r0),arg1 /* do reset */
+
+ ldil L%PA(os_hpmc_6),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_6)(rp),rp
+
+os_hpmc_6:
+
+ /*
+ * possible return values:
+ * -1 non-existent procedure
+ * -2 non-existent option
+ * -16 unaligned stack
+ *
+ * If call returned, do a broadcast reset.
+ */
+
+ ldil L%0xfffc0000,%r4 /* IO_BROADCAST */
+ ldo 5(%r0),%r5
+ stw %r5,48(%r4) /* CMD_RESET to IO_COMMAND offset */
+
+ b .
+ nop
+
+ /* this label used to compute os_hpmc checksum */
+
+ .export os_hpmc_end, code
+
+os_hpmc_end:
+
+ nop
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
new file mode 100644
index 000000000000..7e898fd64415
--- /dev/null
+++ b/arch/parisc/kernel/init_task.c
@@ -0,0 +1,76 @@
+/*
+ * Static declaration of "init" task data structure.
+ *
+ * Copyright (C) 2000 Paul Bame <bame at parisc-linux.org>
+ * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org>
+ * Copyright (C) 2001 Helge Deller <deller @ parisc-linux.org>
+ * Copyright (C) 2002 Matthew Wilcox <willy with parisc-linux.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * We need to make sure that this is 16384-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+unsigned char interrupt_stack[ISTACK_SIZE] __attribute__ ((section("init_istack"), aligned(4096)));
+union thread_union init_thread_union
+ __attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) =
+ { INIT_THREAD_INFO(init_task) };
+
+#ifdef __LP64__
+/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
+ * with the first pmd adjacent to the pgd and below it. gcc doesn't actually
+ * guarantee that global objects will be laid out in memory in the same order
+ * as the order of declaration, so put these in different sections and use
+ * the linker script to order them. */
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pmd"))) = { {0}, };
+
+#endif
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pgd"))) = { {0}, };
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pte"))) = { {0}, };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+EXPORT_SYMBOL(init_task);
+
+__asm__(".data");
+struct task_struct init_task = INIT_TASK(init_task);
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c
new file mode 100644
index 000000000000..1a1c66422736
--- /dev/null
+++ b/arch/parisc/kernel/inventory.c
@@ -0,0 +1,612 @@
+/*
+ * inventory.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Copyright (c) 1999 The Puffin Group (David Kennedy and Alex deVries)
+ * Copyright (c) 2001 Matthew Wilcox for Hewlett-Packard
+ *
+ * These are the routines to discover what hardware exists in this box.
+ * This task is complicated by there being 3 different ways of
+ * performing an inventory, depending largely on the age of the box.
+ * The recommended way to do this is to check to see whether the machine
+ * is a `Snake' first, then try System Map, then try PAT. We try System
+ * Map before checking for a Snake -- this probably doesn't cause any
+ * problems, but...
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mmzone.h>
+#include <asm/pdc.h>
+#include <asm/pdcpat.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/parisc-device.h>
+
+/*
+** Debug options
+** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices.
+*/
+#undef DEBUG_PAT
+
+int pdc_type = PDC_TYPE_ILLEGAL;
+
+void __init setup_pdc(void)
+{
+ long status;
+ unsigned int bus_id;
+ struct pdc_system_map_mod_info module_result;
+ struct pdc_module_path module_path;
+ struct pdc_model model;
+#ifdef __LP64__
+ struct pdc_pat_cell_num cell_info;
+#endif
+
+ /* Determine the pdc "type" used on this machine */
+
+ printk(KERN_INFO "Determining PDC firmware type: ");
+
+ status = pdc_system_map_find_mods(&module_result, &module_path, 0);
+ if (status == PDC_OK) {
+ pdc_type = PDC_TYPE_SYSTEM_MAP;
+ printk("System Map.\n");
+ return;
+ }
+
+ /*
+ * If the machine doesn't support PDC_SYSTEM_MAP then either it
+ * is a pdc pat box, or it is an older box. All 64 bit capable
+ * machines are either pdc pat boxes or they support PDC_SYSTEM_MAP.
+ */
+
+ /*
+ * TODO: We should test for 64 bit capability and give a
+ * clearer message.
+ */
+
+#ifdef __LP64__
+ status = pdc_pat_cell_get_number(&cell_info);
+ if (status == PDC_OK) {
+ pdc_type = PDC_TYPE_PAT;
+ printk("64 bit PAT.\n");
+ return;
+ }
+#endif
+
+ /* Check the CPU's bus ID. There's probably a better test. */
+
+ status = pdc_model_info(&model);
+
+ bus_id = (model.hversion >> (4 + 7)) & 0x1f;
+
+ switch (bus_id) {
+ case 0x4: /* 720, 730, 750, 735, 755 */
+ case 0x6: /* 705, 710 */
+ case 0x7: /* 715, 725 */
+ case 0x8: /* 745, 747, 742 */
+ case 0xA: /* 712 and similiar */
+ case 0xC: /* 715/64, at least */
+
+ pdc_type = PDC_TYPE_SNAKE;
+ printk("Snake.\n");
+ return;
+
+ default: /* Everything else */
+
+ printk("Unsupported.\n");
+ panic("If this is a 64-bit machine, please try a 64-bit kernel.\n");
+ }
+}
+
+#define PDC_PAGE_ADJ_SHIFT (PAGE_SHIFT - 12) /* pdc pages are always 4k */
+
+static void __init
+set_pmem_entry(physmem_range_t *pmem_ptr, unsigned long start,
+ unsigned long pages4k)
+{
+ /* Rather than aligning and potentially throwing away
+ * memory, we'll assume that any ranges are already
+ * nicely aligned with any reasonable page size, and
+ * panic if they are not (it's more likely that the
+ * pdc info is bad in this case).
+ */
+
+ if ( ((start & (PAGE_SIZE - 1)) != 0)
+ || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) ) {
+
+ panic("Memory range doesn't align with page size!\n");
+ }
+
+ pmem_ptr->start_pfn = (start >> PAGE_SHIFT);
+ pmem_ptr->pages = (pages4k >> PDC_PAGE_ADJ_SHIFT);
+}
+
+static void __init pagezero_memconfig(void)
+{
+ unsigned long npages;
+
+ /* Use the 32 bit information from page zero to create a single
+ * entry in the pmem_ranges[] table.
+ *
+ * We currently don't support machines with contiguous memory
+ * >= 4 Gb, who report that memory using 64 bit only fields
+ * on page zero. It's not worth doing until it can be tested,
+ * and it is not clear we can support those machines for other
+ * reasons.
+ *
+ * If that support is done in the future, this is where it
+ * should be done.
+ */
+
+ npages = (PAGE_ALIGN(PAGE0->imm_max_mem) >> PAGE_SHIFT);
+ set_pmem_entry(pmem_ranges,0UL,npages);
+ npmem_ranges = 1;
+}
+
+#ifdef __LP64__
+
+/* All of the PDC PAT specific code is 64-bit only */
+
+/*
+** The module object is filled via PDC_PAT_CELL[Return Cell Module].
+** If a module is found, register module will get the IODC bytes via
+** pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter.
+**
+** The IO view can be used by PDC_PAT_CELL[Return Cell Module]
+** only for SBAs and LBAs. This view will cause an invalid
+** argument error for all other cell module types.
+**
+*/
+
+static int __init
+pat_query_module(ulong pcell_loc, ulong mod_index)
+{
+ pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+ unsigned long bytecnt;
+ unsigned long temp; /* 64-bit scratch value */
+ long status; /* PDC return value status */
+ struct parisc_device *dev;
+
+ /* return cell module (PA or Processor view) */
+ status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
+ PA_VIEW, &pa_pdc_cell);
+
+ if (status != PDC_OK) {
+ /* no more cell modules or error */
+ return status;
+ }
+
+ temp = pa_pdc_cell.cba;
+ dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path);
+ if (!dev) {
+ return PDC_NE_MOD;
+ }
+
+ /* alloc_pa_dev sets dev->hpa */
+
+ /*
+ ** save parameters in the parisc_device
+ ** (The idea being the device driver will call pdc_pat_cell_module()
+ ** and store the results in its own data structure.)
+ */
+ dev->pcell_loc = pcell_loc;
+ dev->mod_index = mod_index;
+
+ /* save generic info returned from the call */
+ /* REVISIT: who is the consumer of this? not sure yet... */
+ dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */
+ dev->pmod_loc = pa_pdc_cell.mod_location;
+
+ register_parisc_device(dev); /* advertise device */
+
+#ifdef DEBUG_PAT
+ pdc_pat_cell_mod_maddr_block_t io_pdc_cell;
+ /* dump what we see so far... */
+ switch (PAT_GET_ENTITY(dev->mod_info)) {
+ unsigned long i;
+
+ case PAT_ENTITY_PROC:
+ printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n",
+ pa_pdc_cell.mod[0]);
+ break;
+
+ case PAT_ENTITY_MEM:
+ printk(KERN_DEBUG
+ "PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",
+ pa_pdc_cell.mod[0], pa_pdc_cell.mod[1],
+ pa_pdc_cell.mod[2]);
+ break;
+ case PAT_ENTITY_CA:
+ printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc);
+ break;
+
+ case PAT_ENTITY_PBC:
+ printk(KERN_DEBUG "PAT_ENTITY_PBC: ");
+ goto print_ranges;
+
+ case PAT_ENTITY_SBA:
+ printk(KERN_DEBUG "PAT_ENTITY_SBA: ");
+ goto print_ranges;
+
+ case PAT_ENTITY_LBA:
+ printk(KERN_DEBUG "PAT_ENTITY_LBA: ");
+
+ print_ranges:
+ pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
+ IO_VIEW, &io_pdc_cell);
+ printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]);
+ for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
+ printk(KERN_DEBUG
+ " PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n",
+ i, pa_pdc_cell.mod[2 + i * 3], /* type */
+ pa_pdc_cell.mod[3 + i * 3], /* start */
+ pa_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */
+ printk(KERN_DEBUG
+ " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n",
+ i, io_pdc_cell.mod[2 + i * 3], /* type */
+ io_pdc_cell.mod[3 + i * 3], /* start */
+ io_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */
+ }
+ printk(KERN_DEBUG "\n");
+ break;
+ }
+#endif /* DEBUG_PAT */
+ return PDC_OK;
+}
+
+
+/* pat pdc can return information about a variety of different
+ * types of memory (e.g. firmware,i/o, etc) but we only care about
+ * the usable physical ram right now. Since the firmware specific
+ * information is allocated on the stack, we'll be generous, in
+ * case there is a lot of other information we don't care about.
+ */
+
+#define PAT_MAX_RANGES (4 * MAX_PHYSMEM_RANGES)
+
+static void __init pat_memconfig(void)
+{
+ unsigned long actual_len;
+ struct pdc_pat_pd_addr_map_entry mem_table[PAT_MAX_RANGES+1];
+ struct pdc_pat_pd_addr_map_entry *mtbl_ptr;
+ physmem_range_t *pmem_ptr;
+ long status;
+ int entries;
+ unsigned long length;
+ int i;
+
+ length = (PAT_MAX_RANGES + 1) * sizeof(struct pdc_pat_pd_addr_map_entry);
+
+ status = pdc_pat_pd_get_addr_map(&actual_len, mem_table, length, 0L);
+
+ if ((status != PDC_OK)
+ || ((actual_len % sizeof(struct pdc_pat_pd_addr_map_entry)) != 0)) {
+
+ /* The above pdc call shouldn't fail, but, just in
+ * case, just use the PAGE0 info.
+ */
+
+ printk("\n\n\n");
+ printk(KERN_WARNING "WARNING! Could not get full memory configuration. "
+ "All memory may not be used!\n\n\n");
+ pagezero_memconfig();
+ return;
+ }
+
+ entries = actual_len / sizeof(struct pdc_pat_pd_addr_map_entry);
+
+ if (entries > PAT_MAX_RANGES) {
+ printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
+ printk(KERN_WARNING "Some memory may not be used!\n");
+ }
+
+ /* Copy information into the firmware independent pmem_ranges
+ * array, skipping types we don't care about. Notice we said
+ * "may" above. We'll use all the entries that were returned.
+ */
+
+ npmem_ranges = 0;
+ mtbl_ptr = mem_table;
+ pmem_ptr = pmem_ranges; /* Global firmware independent table */
+ for (i = 0; i < entries; i++,mtbl_ptr++) {
+ if ( (mtbl_ptr->entry_type != PAT_MEMORY_DESCRIPTOR)
+ || (mtbl_ptr->memory_type != PAT_MEMTYPE_MEMORY)
+ || (mtbl_ptr->pages == 0)
+ || ( (mtbl_ptr->memory_usage != PAT_MEMUSE_GENERAL)
+ && (mtbl_ptr->memory_usage != PAT_MEMUSE_GI)
+ && (mtbl_ptr->memory_usage != PAT_MEMUSE_GNI) ) ) {
+
+ continue;
+ }
+
+ if (npmem_ranges == MAX_PHYSMEM_RANGES) {
+ printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
+ printk(KERN_WARNING "Some memory will not be used!\n");
+ break;
+ }
+
+ set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages);
+ npmem_ranges++;
+ }
+}
+
+static int __init pat_inventory(void)
+{
+ int status;
+ ulong mod_index = 0;
+ struct pdc_pat_cell_num cell_info;
+
+ /*
+ ** Note: Prelude (and it's successors: Lclass, A400/500) only
+ ** implement PDC_PAT_CELL sub-options 0 and 2.
+ */
+ status = pdc_pat_cell_get_number(&cell_info);
+ if (status != PDC_OK) {
+ return 0;
+ }
+
+#ifdef DEBUG_PAT
+ printk(KERN_DEBUG "CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_info.cell_num,
+ cell_info.cell_loc);
+#endif
+
+ while (PDC_OK == pat_query_module(cell_info.cell_loc, mod_index)) {
+ mod_index++;
+ }
+
+ return mod_index;
+}
+
+/* We only look for extended memory ranges on a 64 bit capable box */
+static void __init sprockets_memconfig(void)
+{
+ struct pdc_memory_table_raddr r_addr;
+ struct pdc_memory_table mem_table[MAX_PHYSMEM_RANGES];
+ struct pdc_memory_table *mtbl_ptr;
+ physmem_range_t *pmem_ptr;
+ long status;
+ int entries;
+ int i;
+
+ status = pdc_mem_mem_table(&r_addr,mem_table,
+ (unsigned long)MAX_PHYSMEM_RANGES);
+
+ if (status != PDC_OK) {
+
+ /* The above pdc call only works on boxes with sprockets
+ * firmware (newer B,C,J class). Other non PAT PDC machines
+ * do support more than 3.75 Gb of memory, but we don't
+ * support them yet.
+ */
+
+ pagezero_memconfig();
+ return;
+ }
+
+ if (r_addr.entries_total > MAX_PHYSMEM_RANGES) {
+ printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
+ printk(KERN_WARNING "Some memory will not be used!\n");
+ }
+
+ entries = (int)r_addr.entries_returned;
+
+ npmem_ranges = 0;
+ mtbl_ptr = mem_table;
+ pmem_ptr = pmem_ranges; /* Global firmware independent table */
+ for (i = 0; i < entries; i++,mtbl_ptr++) {
+ set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages);
+ npmem_ranges++;
+ }
+}
+
+#else /* !__LP64__ */
+
+#define pat_inventory() do { } while (0)
+#define pat_memconfig() do { } while (0)
+#define sprockets_memconfig() pagezero_memconfig()
+
+#endif /* !__LP64__ */
+
+
+#ifndef CONFIG_PA20
+
+/* Code to support Snake machines (7[2350], 7[235]5, 715/Scorpio) */
+
+static struct parisc_device * __init
+legacy_create_device(struct pdc_memory_map *r_addr,
+ struct pdc_module_path *module_path)
+{
+ struct parisc_device *dev;
+ int status = pdc_mem_map_hpa(r_addr, module_path);
+ if (status != PDC_OK)
+ return NULL;
+
+ dev = alloc_pa_dev(r_addr->hpa, &module_path->path);
+ if (dev == NULL)
+ return NULL;
+
+ register_parisc_device(dev);
+ return dev;
+}
+
+/**
+ * snake_inventory
+ *
+ * Before PDC_SYSTEM_MAP was invented, the PDC_MEM_MAP call was used.
+ * To use it, we initialise the mod_path.bc to 0xff and try all values of
+ * mod to get the HPA for the top-level devices. Bus adapters may have
+ * sub-devices which are discovered by setting bc[5] to 0 and bc[4] to the
+ * module, then trying all possible functions.
+ */
+static void __init snake_inventory(void)
+{
+ int mod;
+ for (mod = 0; mod < 16; mod++) {
+ struct parisc_device *dev;
+ struct pdc_module_path module_path;
+ struct pdc_memory_map r_addr;
+ unsigned int func;
+
+ memset(module_path.path.bc, 0xff, 6);
+ module_path.path.mod = mod;
+ dev = legacy_create_device(&r_addr, &module_path);
+ if ((!dev) || (dev->id.hw_type != HPHW_BA))
+ continue;
+
+ memset(module_path.path.bc, 0xff, 4);
+ module_path.path.bc[4] = mod;
+
+ for (func = 0; func < 16; func++) {
+ module_path.path.bc[5] = 0;
+ module_path.path.mod = func;
+ legacy_create_device(&r_addr, &module_path);
+ }
+ }
+}
+
+#else /* CONFIG_PA20 */
+#define snake_inventory() do { } while (0)
+#endif /* CONFIG_PA20 */
+
+/* Common 32/64 bit based code goes here */
+
+/**
+ * add_system_map_addresses - Add additional addresses to the parisc device.
+ * @dev: The parisc device.
+ * @num_addrs: Then number of addresses to add;
+ * @module_instance: The system_map module instance.
+ *
+ * This function adds any additional addresses reported by the system_map
+ * firmware to the parisc device.
+ */
+static void __init
+add_system_map_addresses(struct parisc_device *dev, int num_addrs,
+ int module_instance)
+{
+ int i;
+ long status;
+ struct pdc_system_map_addr_info addr_result;
+
+ dev->addr = kmalloc(num_addrs * sizeof(unsigned long), GFP_KERNEL);
+ if(!dev->addr) {
+ printk(KERN_ERR "%s %s(): memory allocation failure\n",
+ __FILE__, __FUNCTION__);
+ return;
+ }
+
+ for(i = 1; i <= num_addrs; ++i) {
+ status = pdc_system_map_find_addrs(&addr_result,
+ module_instance, i);
+ if(PDC_OK == status) {
+ dev->addr[dev->num_addrs] = (unsigned long)addr_result.mod_addr;
+ dev->num_addrs++;
+ } else {
+ printk(KERN_WARNING
+ "Bad PDC_FIND_ADDRESS status return (%ld) for index %d\n",
+ status, i);
+ }
+ }
+}
+
+/**
+ * system_map_inventory - Retrieve firmware devices via SYSTEM_MAP.
+ *
+ * This function attempts to retrieve and register all the devices firmware
+ * knows about via the SYSTEM_MAP PDC call.
+ */
+static void __init system_map_inventory(void)
+{
+ int i;
+ long status = PDC_OK;
+
+ for (i = 0; i < 256; i++) {
+ struct parisc_device *dev;
+ struct pdc_system_map_mod_info module_result;
+ struct pdc_module_path module_path;
+
+ status = pdc_system_map_find_mods(&module_result,
+ &module_path, i);
+ if ((status == PDC_BAD_PROC) || (status == PDC_NE_MOD))
+ break;
+ if (status != PDC_OK)
+ continue;
+
+ dev = alloc_pa_dev(module_result.mod_addr, &module_path.path);
+ if (!dev)
+ continue;
+
+ register_parisc_device(dev);
+
+ /* if available, get the additional addresses for a module */
+ if (!module_result.add_addrs)
+ continue;
+
+ add_system_map_addresses(dev, module_result.add_addrs, i);
+ }
+
+ walk_central_bus();
+ return;
+}
+
+void __init do_memory_inventory(void)
+{
+ switch (pdc_type) {
+
+ case PDC_TYPE_PAT:
+ pat_memconfig();
+ break;
+
+ case PDC_TYPE_SYSTEM_MAP:
+ sprockets_memconfig();
+ break;
+
+ case PDC_TYPE_SNAKE:
+ pagezero_memconfig();
+ return;
+
+ default:
+ panic("Unknown PDC type!\n");
+ }
+
+ if (npmem_ranges == 0 || pmem_ranges[0].start_pfn != 0) {
+ printk(KERN_WARNING "Bad memory configuration returned!\n");
+ printk(KERN_WARNING "Some memory may not be used!\n");
+ pagezero_memconfig();
+ }
+}
+
+void __init do_device_inventory(void)
+{
+ printk(KERN_INFO "Searching for devices...\n");
+
+ init_parisc_bus();
+
+ switch (pdc_type) {
+
+ case PDC_TYPE_PAT:
+ pat_inventory();
+ break;
+
+ case PDC_TYPE_SYSTEM_MAP:
+ system_map_inventory();
+ break;
+
+ case PDC_TYPE_SNAKE:
+ snake_inventory();
+ break;
+
+ default:
+ panic("Unknown PDC type!\n");
+ }
+ printk(KERN_INFO "Found devices:\n");
+ print_parisc_devices();
+}
diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
new file mode 100644
index 000000000000..1d3824b670d1
--- /dev/null
+++ b/arch/parisc/kernel/ioctl32.c
@@ -0,0 +1,625 @@
+/* $Id: ioctl32.c,v 1.5 2002/10/18 00:21:43 varenet Exp $
+ * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
+ *
+ * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * ioctls.
+ */
+
+#include <linux/syscalls.h>
+
+#define INCLUDES
+#include "compat_ioctl.c"
+
+#include <asm/perf.h>
+#include <asm/ioctls.h>
+
+#define CODE
+#include "compat_ioctl.c"
+
+/* Use this to get at 32-bit user passed pointers.
+ See sys_sparc32.c for description about these. */
+#define A(__x) ((unsigned long)(__x))
+/* The same for use with copy_from_user() and copy_to_user(). */
+#define B(__x) ((void *)(unsigned long)(__x))
+
+#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
+/* This really belongs in include/linux/drm.h -DaveM */
+#include "../../../drivers/char/drm/drm.h"
+
+typedef struct drm32_version {
+ int version_major; /* Major version */
+ int version_minor; /* Minor version */
+ int version_patchlevel;/* Patch level */
+ int name_len; /* Length of name buffer */
+ u32 name; /* Name of driver */
+ int date_len; /* Length of date buffer */
+ u32 date; /* User-space buffer to hold date */
+ int desc_len; /* Length of desc buffer */
+ u32 desc; /* User-space buffer to hold desc */
+} drm32_version_t;
+#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t)
+
+static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ drm32_version_t *uversion = (drm32_version_t *)arg;
+ char *name_ptr, *date_ptr, *desc_ptr;
+ u32 tmp1, tmp2, tmp3;
+ drm_version_t kversion;
+ mm_segment_t old_fs;
+ int ret;
+
+ memset(&kversion, 0, sizeof(kversion));
+ if (get_user(kversion.name_len, &uversion->name_len) ||
+ get_user(kversion.date_len, &uversion->date_len) ||
+ get_user(kversion.desc_len, &uversion->desc_len) ||
+ get_user(tmp1, &uversion->name) ||
+ get_user(tmp2, &uversion->date) ||
+ get_user(tmp3, &uversion->desc))
+ return -EFAULT;
+
+ name_ptr = (char *) A(tmp1);
+ date_ptr = (char *) A(tmp2);
+ desc_ptr = (char *) A(tmp3);
+
+ ret = -ENOMEM;
+ if (kversion.name_len && name_ptr) {
+ kversion.name = kmalloc(kversion.name_len, GFP_KERNEL);
+ if (!kversion.name)
+ goto out;
+ }
+ if (kversion.date_len && date_ptr) {
+ kversion.date = kmalloc(kversion.date_len, GFP_KERNEL);
+ if (!kversion.date)
+ goto out;
+ }
+ if (kversion.desc_len && desc_ptr) {
+ kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL);
+ if (!kversion.desc)
+ goto out;
+ }
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion);
+ set_fs(old_fs);
+
+ if (!ret) {
+ if ((kversion.name &&
+ copy_to_user(name_ptr, kversion.name, kversion.name_len)) ||
+ (kversion.date &&
+ copy_to_user(date_ptr, kversion.date, kversion.date_len)) ||
+ (kversion.desc &&
+ copy_to_user(desc_ptr, kversion.desc, kversion.desc_len)))
+ ret = -EFAULT;
+ if (put_user(kversion.version_major, &uversion->version_major) ||
+ put_user(kversion.version_minor, &uversion->version_minor) ||
+ put_user(kversion.version_patchlevel, &uversion->version_patchlevel) ||
+ put_user(kversion.name_len, &uversion->name_len) ||
+ put_user(kversion.date_len, &uversion->date_len) ||
+ put_user(kversion.desc_len, &uversion->desc_len))
+ ret = -EFAULT;
+ }
+
+out:
+ if (kversion.name)
+ kfree(kversion.name);
+ if (kversion.date)
+ kfree(kversion.date);
+ if (kversion.desc)
+ kfree(kversion.desc);
+ return ret;
+}
+
+typedef struct drm32_unique {
+ int unique_len; /* Length of unique */
+ u32 unique; /* Unique name for driver instantiation */
+} drm32_unique_t;
+#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t)
+#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t)
+
+static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ drm32_unique_t *uarg = (drm32_unique_t *)arg;
+ drm_unique_t karg;
+ mm_segment_t old_fs;
+ char *uptr;
+ u32 tmp;
+ int ret;
+
+ if (get_user(karg.unique_len, &uarg->unique_len))
+ return -EFAULT;
+ karg.unique = NULL;
+
+ if (get_user(tmp, &uarg->unique))
+ return -EFAULT;
+
+ uptr = (char *) A(tmp);
+
+ if (uptr) {
+ karg.unique = kmalloc(karg.unique_len, GFP_KERNEL);
+ if (!karg.unique)
+ return -ENOMEM;
+ if (cmd == DRM32_IOCTL_SET_UNIQUE &&
+ copy_from_user(karg.unique, uptr, karg.unique_len)) {
+ kfree(karg.unique);
+ return -EFAULT;
+ }
+ }
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ if (cmd == DRM32_IOCTL_GET_UNIQUE)
+ ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg);
+ else
+ ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg);
+ set_fs(old_fs);
+
+ if (!ret) {
+ if (cmd == DRM32_IOCTL_GET_UNIQUE &&
+ uptr != NULL &&
+ copy_to_user(uptr, karg.unique, karg.unique_len))
+ ret = -EFAULT;
+ if (put_user(karg.unique_len, &uarg->unique_len))
+ ret = -EFAULT;
+ }
+
+ if (karg.unique != NULL)
+ kfree(karg.unique);
+
+ return ret;
+}
+
+typedef struct drm32_map {
+ u32 offset; /* Requested physical address (0 for SAREA)*/
+ u32 size; /* Requested physical size (bytes) */
+ drm_map_type_t type; /* Type of memory to map */
+ drm_map_flags_t flags; /* Flags */
+ u32 handle; /* User-space: "Handle" to pass to mmap */
+ /* Kernel-space: kernel-virtual address */
+ int mtrr; /* MTRR slot used */
+ /* Private data */
+} drm32_map_t;
+#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t)
+
+static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ drm32_map_t *uarg = (drm32_map_t *) arg;
+ drm_map_t karg;
+ mm_segment_t old_fs;
+ u32 tmp;
+ int ret;
+
+ ret = get_user(karg.offset, &uarg->offset);
+ ret |= get_user(karg.size, &uarg->size);
+ ret |= get_user(karg.type, &uarg->type);
+ ret |= get_user(karg.flags, &uarg->flags);
+ ret |= get_user(tmp, &uarg->handle);
+ ret |= get_user(karg.mtrr, &uarg->mtrr);
+ if (ret)
+ return -EFAULT;
+
+ karg.handle = (void *) A(tmp);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg);
+ set_fs(old_fs);
+
+ if (!ret) {
+ ret = put_user(karg.offset, &uarg->offset);
+ ret |= put_user(karg.size, &uarg->size);
+ ret |= put_user(karg.type, &uarg->type);
+ ret |= put_user(karg.flags, &uarg->flags);
+ tmp = (u32) (long)karg.handle;
+ ret |= put_user(tmp, &uarg->handle);
+ ret |= put_user(karg.mtrr, &uarg->mtrr);
+ if (ret)
+ ret = -EFAULT;
+ }
+
+ return ret;
+}
+
+typedef struct drm32_buf_info {
+ int count; /* Entries in list */
+ u32 list; /* (drm_buf_desc_t *) */
+} drm32_buf_info_t;
+#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t)
+
+static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg;
+ drm_buf_desc_t *ulist;
+ drm_buf_info_t karg;
+ mm_segment_t old_fs;
+ int orig_count, ret;
+ u32 tmp;
+
+ if (get_user(karg.count, &uarg->count) ||
+ get_user(tmp, &uarg->list))
+ return -EFAULT;
+
+ ulist = (drm_buf_desc_t *) A(tmp);
+
+ orig_count = karg.count;
+
+ karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL);
+ if (!karg.list)
+ return -EFAULT;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg);
+ set_fs(old_fs);
+
+ if (!ret) {
+ if (karg.count <= orig_count &&
+ (copy_to_user(ulist, karg.list,
+ karg.count * sizeof(drm_buf_desc_t))))
+ ret = -EFAULT;
+ if (put_user(karg.count, &uarg->count))
+ ret = -EFAULT;
+ }
+
+ kfree(karg.list);
+
+ return ret;
+}
+
+typedef struct drm32_buf_free {
+ int count;
+ u32 list; /* (int *) */
+} drm32_buf_free_t;
+#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t)
+
+static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg;
+ drm_buf_free_t karg;
+ mm_segment_t old_fs;
+ int *ulist;
+ int ret;
+ u32 tmp;
+
+ if (get_user(karg.count, &uarg->count) ||
+ get_user(tmp, &uarg->list))
+ return -EFAULT;
+
+ ulist = (int *) A(tmp);
+
+ karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL);
+ if (!karg.list)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int))))
+ goto out;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg);
+ set_fs(old_fs);
+
+out:
+ kfree(karg.list);
+
+ return ret;
+}
+
+typedef struct drm32_buf_pub {
+ int idx; /* Index into master buflist */
+ int total; /* Buffer size */
+ int used; /* Amount of buffer in use (for DMA) */
+ u32 address; /* Address of buffer (void *) */
+} drm32_buf_pub_t;
+
+typedef struct drm32_buf_map {
+ int count; /* Length of buflist */
+ u32 virtual; /* Mmaped area in user-virtual (void *) */
+ u32 list; /* Buffer information (drm_buf_pub_t *) */
+} drm32_buf_map_t;
+#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t)
+
+static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg;
+ drm32_buf_pub_t *ulist;
+ drm_buf_map_t karg;
+ mm_segment_t old_fs;
+ int orig_count, ret, i;
+ u32 tmp1, tmp2;
+
+ if (get_user(karg.count, &uarg->count) ||
+ get_user(tmp1, &uarg->virtual) ||
+ get_user(tmp2, &uarg->list))
+ return -EFAULT;
+
+ karg.virtual = (void *) A(tmp1);
+ ulist = (drm32_buf_pub_t *) A(tmp2);
+
+ orig_count = karg.count;
+
+ karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL);
+ if (!karg.list)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ for (i = 0; i < karg.count; i++) {
+ if (get_user(karg.list[i].idx, &ulist[i].idx) ||
+ get_user(karg.list[i].total, &ulist[i].total) ||
+ get_user(karg.list[i].used, &ulist[i].used) ||
+ get_user(tmp1, &ulist[i].address))
+ goto out;
+
+ karg.list[i].address = (void *) A(tmp1);
+ }
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg);
+ set_fs(old_fs);
+
+ if (!ret) {
+ for (i = 0; i < orig_count; i++) {
+ tmp1 = (u32) (long) karg.list[i].address;
+ if (put_user(karg.list[i].idx, &ulist[i].idx) ||
+ put_user(karg.list[i].total, &ulist[i].total) ||
+ put_user(karg.list[i].used, &ulist[i].used) ||
+ put_user(tmp1, &ulist[i].address)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+ if (put_user(karg.count, &uarg->count))
+ ret = -EFAULT;
+ }
+
+out:
+ kfree(karg.list);
+ return ret;
+}
+
+typedef struct drm32_dma {
+ /* Indices here refer to the offset into
+ buflist in drm_buf_get_t. */
+ int context; /* Context handle */
+ int send_count; /* Number of buffers to send */
+ u32 send_indices; /* List of handles to buffers (int *) */
+ u32 send_sizes; /* Lengths of data to send (int *) */
+ drm_dma_flags_t flags; /* Flags */
+ int request_count; /* Number of buffers requested */
+ int request_size; /* Desired size for buffers */
+ u32 request_indices; /* Buffer information (int *) */
+ u32 request_sizes; /* (int *) */
+ int granted_count; /* Number of buffers granted */
+} drm32_dma_t;
+#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t)
+
+/* RED PEN The DRM layer blindly dereferences the send/request
+ * indice/size arrays even though they are userland
+ * pointers. -DaveM
+ */
+static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ drm32_dma_t *uarg = (drm32_dma_t *) arg;
+ int *u_si, *u_ss, *u_ri, *u_rs;
+ drm_dma_t karg;
+ mm_segment_t old_fs;
+ int ret;
+ u32 tmp1, tmp2, tmp3, tmp4;
+
+ karg.send_indices = karg.send_sizes = NULL;
+ karg.request_indices = karg.request_sizes = NULL;
+
+ if (get_user(karg.context, &uarg->context) ||
+ get_user(karg.send_count, &uarg->send_count) ||
+ get_user(tmp1, &uarg->send_indices) ||
+ get_user(tmp2, &uarg->send_sizes) ||
+ get_user(karg.flags, &uarg->flags) ||
+ get_user(karg.request_count, &uarg->request_count) ||
+ get_user(karg.request_size, &uarg->request_size) ||
+ get_user(tmp3, &uarg->request_indices) ||
+ get_user(tmp4, &uarg->request_sizes) ||
+ get_user(karg.granted_count, &uarg->granted_count))
+ return -EFAULT;
+
+ u_si = (int *) A(tmp1);
+ u_ss = (int *) A(tmp2);
+ u_ri = (int *) A(tmp3);
+ u_rs = (int *) A(tmp4);
+
+ if (karg.send_count) {
+ karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL);
+ karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL);
+
+ ret = -ENOMEM;
+ if (!karg.send_indices || !karg.send_sizes)
+ goto out;
+
+ ret = -EFAULT;
+ if (copy_from_user(karg.send_indices, u_si,
+ (karg.send_count * sizeof(int))) ||
+ copy_from_user(karg.send_sizes, u_ss,
+ (karg.send_count * sizeof(int))))
+ goto out;
+ }
+
+ if (karg.request_count) {
+ karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL);
+ karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL);
+
+ ret = -ENOMEM;
+ if (!karg.request_indices || !karg.request_sizes)
+ goto out;
+
+ ret = -EFAULT;
+ if (copy_from_user(karg.request_indices, u_ri,
+ (karg.request_count * sizeof(int))) ||
+ copy_from_user(karg.request_sizes, u_rs,
+ (karg.request_count * sizeof(int))))
+ goto out;
+ }
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg);
+ set_fs(old_fs);
+
+ if (!ret) {
+ if (put_user(karg.context, &uarg->context) ||
+ put_user(karg.send_count, &uarg->send_count) ||
+ put_user(karg.flags, &uarg->flags) ||
+ put_user(karg.request_count, &uarg->request_count) ||
+ put_user(karg.request_size, &uarg->request_size) ||
+ put_user(karg.granted_count, &uarg->granted_count))
+ ret = -EFAULT;
+
+ if (karg.send_count) {
+ if (copy_to_user(u_si, karg.send_indices,
+ (karg.send_count * sizeof(int))) ||
+ copy_to_user(u_ss, karg.send_sizes,
+ (karg.send_count * sizeof(int))))
+ ret = -EFAULT;
+ }
+ if (karg.request_count) {
+ if (copy_to_user(u_ri, karg.request_indices,
+ (karg.request_count * sizeof(int))) ||
+ copy_to_user(u_rs, karg.request_sizes,
+ (karg.request_count * sizeof(int))))
+ ret = -EFAULT;
+ }
+ }
+
+out:
+ if (karg.send_indices)
+ kfree(karg.send_indices);
+ if (karg.send_sizes)
+ kfree(karg.send_sizes);
+ if (karg.request_indices)
+ kfree(karg.request_indices);
+ if (karg.request_sizes)
+ kfree(karg.request_sizes);
+
+ return ret;
+}
+
+typedef struct drm32_ctx_res {
+ int count;
+ u32 contexts; /* (drm_ctx_t *) */
+} drm32_ctx_res_t;
+#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t)
+
+static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg;
+ drm_ctx_t *ulist;
+ drm_ctx_res_t karg;
+ mm_segment_t old_fs;
+ int orig_count, ret;
+ u32 tmp;
+
+ karg.contexts = NULL;
+ if (get_user(karg.count, &uarg->count) ||
+ get_user(tmp, &uarg->contexts))
+ return -EFAULT;
+
+ ulist = (drm_ctx_t *) A(tmp);
+
+ orig_count = karg.count;
+ if (karg.count && ulist) {
+ karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL);
+ if (!karg.contexts)
+ return -ENOMEM;
+ if (copy_from_user(karg.contexts, ulist,
+ (karg.count * sizeof(drm_ctx_t)))) {
+ kfree(karg.contexts);
+ return -EFAULT;
+ }
+ }
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg);
+ set_fs(old_fs);
+
+ if (!ret) {
+ if (orig_count) {
+ if (copy_to_user(ulist, karg.contexts,
+ (orig_count * sizeof(drm_ctx_t))))
+ ret = -EFAULT;
+ }
+ if (put_user(karg.count, &uarg->count))
+ ret = -EFAULT;
+ }
+
+ if (karg.contexts)
+ kfree(karg.contexts);
+
+ return ret;
+}
+
+#endif
+
+#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
+#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl)
+
+#define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = {
+#define IOCTL_TABLE_END };
+
+IOCTL_TABLE_START
+#include <linux/compat_ioctl.h>
+
+#define DECLARES
+#include "compat_ioctl.c"
+
+/* Might be moved to compat_ioctl.h with some ifdefs... */
+COMPATIBLE_IOCTL(TIOCSTART)
+COMPATIBLE_IOCTL(TIOCSTOP)
+COMPATIBLE_IOCTL(TIOCSLTC)
+
+/* PA-specific ioctls */
+COMPATIBLE_IOCTL(PA_PERF_ON)
+COMPATIBLE_IOCTL(PA_PERF_OFF)
+COMPATIBLE_IOCTL(PA_PERF_VERSION)
+
+/* And these ioctls need translation */
+HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
+
+#if defined(CONFIG_GEN_RTC)
+COMPATIBLE_IOCTL(RTC_AIE_ON)
+COMPATIBLE_IOCTL(RTC_AIE_OFF)
+COMPATIBLE_IOCTL(RTC_UIE_ON)
+COMPATIBLE_IOCTL(RTC_UIE_OFF)
+COMPATIBLE_IOCTL(RTC_PIE_ON)
+COMPATIBLE_IOCTL(RTC_PIE_OFF)
+COMPATIBLE_IOCTL(RTC_WIE_ON)
+COMPATIBLE_IOCTL(RTC_WIE_OFF)
+COMPATIBLE_IOCTL(RTC_ALM_SET) /* struct rtc_time only has ints */
+COMPATIBLE_IOCTL(RTC_ALM_READ) /* struct rtc_time only has ints */
+COMPATIBLE_IOCTL(RTC_RD_TIME) /* struct rtc_time only has ints */
+COMPATIBLE_IOCTL(RTC_SET_TIME) /* struct rtc_time only has ints */
+HANDLE_IOCTL(RTC_IRQP_READ, w_long)
+COMPATIBLE_IOCTL(RTC_IRQP_SET)
+HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
+COMPATIBLE_IOCTL(RTC_EPOCH_SET)
+#endif
+
+#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
+HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version);
+HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique);
+HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique);
+HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap);
+HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs);
+HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs);
+HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs);
+HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma);
+HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx);
+#endif /* DRM */
+IOCTL_TABLE_END
+
+int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
new file mode 100644
index 000000000000..006385dbee66
--- /dev/null
+++ b/arch/parisc/kernel/irq.c
@@ -0,0 +1,343 @@
+/*
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
+ * Copyright (C) 1999-2000 Grant Grundler
+ * Copyright (c) 2005 Matthew Wilcox
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/bitops.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#undef PARISC_IRQ_CR16_COUNTS
+
+extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
+extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
+
+#define EIEM_MASK(irq) (1UL<<(CPU_IRQ_MAX - irq))
+
+/* Bits in EIEM correlate with cpu_irq_action[].
+** Numbered *Big Endian*! (ie bit 0 is MSB)
+*/
+static volatile unsigned long cpu_eiem = 0;
+
+static void cpu_set_eiem(void *info)
+{
+ set_eiem((unsigned long) info);
+}
+
+static inline void cpu_disable_irq(unsigned int irq)
+{
+ unsigned long eirr_bit = EIEM_MASK(irq);
+
+ cpu_eiem &= ~eirr_bit;
+ on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
+}
+
+static void cpu_enable_irq(unsigned int irq)
+{
+ unsigned long eirr_bit = EIEM_MASK(irq);
+
+ mtctl(eirr_bit, 23); /* clear EIRR bit before unmasking */
+ cpu_eiem |= eirr_bit;
+ on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
+}
+
+static unsigned int cpu_startup_irq(unsigned int irq)
+{
+ cpu_enable_irq(irq);
+ return 0;
+}
+
+void no_ack_irq(unsigned int irq) { }
+void no_end_irq(unsigned int irq) { }
+
+static struct hw_interrupt_type cpu_interrupt_type = {
+ .typename = "CPU",
+ .startup = cpu_startup_irq,
+ .shutdown = cpu_disable_irq,
+ .enable = cpu_enable_irq,
+ .disable = cpu_disable_irq,
+ .ack = no_ack_irq,
+ .end = no_end_irq,
+// .set_affinity = cpu_set_affinity_irq,
+};
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v, j;
+ unsigned long flags;
+
+ if (i == 0) {
+ seq_puts(p, " ");
+ for_each_online_cpu(j)
+ seq_printf(p, " CPU%d", j);
+
+#ifdef PARISC_IRQ_CR16_COUNTS
+ seq_printf(p, " [min/avg/max] (CPU cycle counts)");
+#endif
+ seq_putc(p, '\n');
+ }
+
+ if (i < NR_IRQS) {
+ struct irqaction *action;
+
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto skip;
+ seq_printf(p, "%3d: ", i);
+#ifdef CONFIG_SMP
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#else
+ seq_printf(p, "%10u ", kstat_irqs(i));
+#endif
+
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+#ifndef PARISC_IRQ_CR16_COUNTS
+ seq_printf(p, " %s", action->name);
+
+ while ((action = action->next))
+ seq_printf(p, ", %s", action->name);
+#else
+ for ( ;action; action = action->next) {
+ unsigned int k, avg, min, max;
+
+ min = max = action->cr16_hist[0];
+
+ for (avg = k = 0; k < PARISC_CR16_HIST_SIZE; k++) {
+ int hist = action->cr16_hist[k];
+
+ if (hist) {
+ avg += hist;
+ } else
+ break;
+
+ if (hist > max) max = hist;
+ if (hist < min) min = hist;
+ }
+
+ avg /= k;
+ seq_printf(p, " %s[%d/%d/%d]", action->name,
+ min,avg,max);
+ }
+#endif
+
+ seq_putc(p, '\n');
+ skip:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ }
+
+ return 0;
+}
+
+
+
+/*
+** The following form a "set": Virtual IRQ, Transaction Address, Trans Data.
+** Respectively, these map to IRQ region+EIRR, Processor HPA, EIRR bit.
+**
+** To use txn_XXX() interfaces, get a Virtual IRQ first.
+** Then use that to get the Transaction address and data.
+*/
+
+int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *type, void *data)
+{
+ if (irq_desc[irq].action)
+ return -EBUSY;
+ if (irq_desc[irq].handler != &cpu_interrupt_type)
+ return -EBUSY;
+
+ if (type) {
+ irq_desc[irq].handler = type;
+ irq_desc[irq].handler_data = data;
+ cpu_interrupt_type.enable(irq);
+ }
+ return 0;
+}
+
+int txn_claim_irq(int irq)
+{
+ return cpu_claim_irq(irq, NULL, NULL) ? -1 : irq;
+}
+
+/*
+ * The bits_wide parameter accommodates the limitations of the HW/SW which
+ * use these bits:
+ * Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register)
+ * V-class (EPIC): 6 bits
+ * N/L/A-class (iosapic): 8 bits
+ * PCI 2.2 MSI: 16 bits
+ * Some PCI devices: 32 bits (Symbios SCSI/ATM/HyperFabric)
+ *
+ * On the service provider side:
+ * o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register)
+ * o PA 2.0 wide mode 6-bits (per processor)
+ * o IA64 8-bits (0-256 total)
+ *
+ * So a Legacy PA I/O device on a PA 2.0 box can't use all the bits supported
+ * by the processor...and the N/L-class I/O subsystem supports more bits than
+ * PA2.0 has. The first case is the problem.
+ */
+int txn_alloc_irq(unsigned int bits_wide)
+{
+ int irq;
+
+ /* never return irq 0 cause that's the interval timer */
+ for (irq = CPU_IRQ_BASE + 1; irq <= CPU_IRQ_MAX; irq++) {
+ if (cpu_claim_irq(irq, NULL, NULL) < 0)
+ continue;
+ if ((irq - CPU_IRQ_BASE) >= (1 << bits_wide))
+ continue;
+ return irq;
+ }
+
+ /* unlikely, but be prepared */
+ return -1;
+}
+
+unsigned long txn_alloc_addr(unsigned int virt_irq)
+{
+ static int next_cpu = -1;
+
+ next_cpu++; /* assign to "next" CPU we want this bugger on */
+
+ /* validate entry */
+ while ((next_cpu < NR_CPUS) && (!cpu_data[next_cpu].txn_addr ||
+ !cpu_online(next_cpu)))
+ next_cpu++;
+
+ if (next_cpu >= NR_CPUS)
+ next_cpu = 0; /* nothing else, assign monarch */
+
+ return cpu_data[next_cpu].txn_addr;
+}
+
+
+unsigned int txn_alloc_data(unsigned int virt_irq)
+{
+ return virt_irq - CPU_IRQ_BASE;
+}
+
+/* ONLY called from entry.S:intr_extint() */
+void do_cpu_irq_mask(struct pt_regs *regs)
+{
+ unsigned long eirr_val;
+
+ irq_enter();
+
+ /*
+ * Only allow interrupt processing to be interrupted by the
+ * timer tick
+ */
+ set_eiem(EIEM_MASK(TIMER_IRQ));
+
+ /* 1) only process IRQs that are enabled/unmasked (cpu_eiem)
+ * 2) We loop here on EIRR contents in order to avoid
+ * nested interrupts or having to take another interrupt
+ * when we could have just handled it right away.
+ */
+ for (;;) {
+ unsigned long bit = (1UL << (BITS_PER_LONG - 1));
+ unsigned int irq;
+ eirr_val = mfctl(23) & cpu_eiem;
+ if (!eirr_val)
+ break;
+
+ if (eirr_val & EIEM_MASK(TIMER_IRQ))
+ set_eiem(0);
+
+ mtctl(eirr_val, 23); /* reset bits we are going to process */
+
+ /* Work our way from MSb to LSb...same order we alloc EIRs */
+ for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) {
+ if (!(bit & eirr_val))
+ continue;
+
+ /* clear bit in mask - can exit loop sooner */
+ eirr_val &= ~bit;
+
+ __do_IRQ(irq, regs);
+ }
+ }
+ set_eiem(cpu_eiem);
+ irq_exit();
+}
+
+
+static struct irqaction timer_action = {
+ .handler = timer_interrupt,
+ .name = "timer",
+};
+
+#ifdef CONFIG_SMP
+static struct irqaction ipi_action = {
+ .handler = ipi_interrupt,
+ .name = "IPI",
+};
+#endif
+
+static void claim_cpu_irqs(void)
+{
+ int i;
+ for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) {
+ irq_desc[i].handler = &cpu_interrupt_type;
+ }
+
+ irq_desc[TIMER_IRQ].action = &timer_action;
+ irq_desc[TIMER_IRQ].status |= IRQ_PER_CPU;
+#ifdef CONFIG_SMP
+ irq_desc[IPI_IRQ].action = &ipi_action;
+ irq_desc[IPI_IRQ].status = IRQ_PER_CPU;
+#endif
+}
+
+void __init init_IRQ(void)
+{
+ local_irq_disable(); /* PARANOID - should already be disabled */
+ mtctl(~0UL, 23); /* EIRR : clear all pending external intr */
+ claim_cpu_irqs();
+#ifdef CONFIG_SMP
+ if (!cpu_eiem)
+ cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ);
+#else
+ cpu_eiem = EIEM_MASK(TIMER_IRQ);
+#endif
+ set_eiem(cpu_eiem); /* EIEM : enable all external intr */
+
+}
+
+void hw_resend_irq(struct hw_interrupt_type *type, unsigned int irq)
+{
+ /* XXX: Needs to be written. We managed without it so far, but
+ * we really ought to write it.
+ */
+}
+
+void ack_bad_irq(unsigned int irq)
+{
+ printk("unexpected IRQ %d\n", irq);
+}
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
new file mode 100644
index 000000000000..f27cfe4771b8
--- /dev/null
+++ b/arch/parisc/kernel/module.c
@@ -0,0 +1,822 @@
+/* Kernel dynamically loadable module help for PARISC.
+ *
+ * The best reference for this stuff is probably the Processor-
+ * Specific ELF Supplement for PA-RISC:
+ * http://ftp.parisc-linux.org/docs/arch/elf-pa-hp.pdf
+ *
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ * Copyright (C) 2003 Randolph Chung <tausq at debian . org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * Notes:
+ * - SEGREL32 handling
+ * We are not doing SEGREL32 handling correctly. According to the ABI, we
+ * should do a value offset, like this:
+ * if (is_init(me, (void *)val))
+ * val -= (uint32_t)me->module_init;
+ * else
+ * val -= (uint32_t)me->module_core;
+ * However, SEGREL32 is used only for PARISC unwind entries, and we want
+ * those entries to have an absolute address, and not just an offset.
+ *
+ * The unwind table mechanism has the ability to specify an offset for
+ * the unwind table; however, because we split off the init functions into
+ * a different piece of memory, it is not possible to do this using a
+ * single offset. Instead, we use the above hack for now.
+ */
+
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/unwind.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+#define CHECK_RELOC(val, bits) \
+ if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
+ ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \
+ printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \
+ me->name, strtab + sym->st_name, (unsigned long)val, bits); \
+ return -ENOEXEC; \
+ }
+
+/* Maximum number of GOT entries. We use a long displacement ldd from
+ * the bottom of the table, which has a maximum signed displacement of
+ * 0x3fff; however, since we're only going forward, this becomes
+ * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have
+ * at most 1023 entries */
+#define MAX_GOTS 1023
+
+/* three functions to determine where in the module core
+ * or init pieces the location is */
+static inline int is_init(struct module *me, void *loc)
+{
+ return (loc >= me->module_init &&
+ loc <= (me->module_init + me->init_size));
+}
+
+static inline int is_core(struct module *me, void *loc)
+{
+ return (loc >= me->module_core &&
+ loc <= (me->module_core + me->core_size));
+}
+
+static inline int is_local(struct module *me, void *loc)
+{
+ return is_init(me, loc) || is_core(me, loc);
+}
+
+
+#ifndef __LP64__
+struct got_entry {
+ Elf32_Addr addr;
+};
+
+#define Elf_Fdesc Elf32_Fdesc
+
+struct stub_entry {
+ Elf32_Word insns[2]; /* each stub entry has two insns */
+};
+#else
+struct got_entry {
+ Elf64_Addr addr;
+};
+
+#define Elf_Fdesc Elf64_Fdesc
+
+struct stub_entry {
+ Elf64_Word insns[4]; /* each stub entry has four insns */
+};
+#endif
+
+/* Field selection types defined by hppa */
+#define rnd(x) (((x)+0x1000)&~0x1fff)
+/* fsel: full 32 bits */
+#define fsel(v,a) ((v)+(a))
+/* lsel: select left 21 bits */
+#define lsel(v,a) (((v)+(a))>>11)
+/* rsel: select right 11 bits */
+#define rsel(v,a) (((v)+(a))&0x7ff)
+/* lrsel with rounding of addend to nearest 8k */
+#define lrsel(v,a) (((v)+rnd(a))>>11)
+/* rrsel with rounding of addend to nearest 8k */
+#define rrsel(v,a) ((((v)+rnd(a))&0x7ff)+((a)-rnd(a)))
+
+#define mask(x,sz) ((x) & ~((1<<(sz))-1))
+
+
+/* The reassemble_* functions prepare an immediate value for
+ insertion into an opcode. pa-risc uses all sorts of weird bitfields
+ in the instruction to hold the value. */
+static inline int reassemble_14(int as14)
+{
+ return (((as14 & 0x1fff) << 1) |
+ ((as14 & 0x2000) >> 13));
+}
+
+static inline int reassemble_17(int as17)
+{
+ return (((as17 & 0x10000) >> 16) |
+ ((as17 & 0x0f800) << 5) |
+ ((as17 & 0x00400) >> 8) |
+ ((as17 & 0x003ff) << 3));
+}
+
+static inline int reassemble_21(int as21)
+{
+ return (((as21 & 0x100000) >> 20) |
+ ((as21 & 0x0ffe00) >> 8) |
+ ((as21 & 0x000180) << 7) |
+ ((as21 & 0x00007c) << 14) |
+ ((as21 & 0x000003) << 12));
+}
+
+static inline int reassemble_22(int as22)
+{
+ return (((as22 & 0x200000) >> 21) |
+ ((as22 & 0x1f0000) << 5) |
+ ((as22 & 0x00f800) << 5) |
+ ((as22 & 0x000400) >> 8) |
+ ((as22 & 0x0003ff) << 3));
+}
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+#ifndef __LP64__
+static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n)
+{
+ return 0;
+}
+
+static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n)
+{
+ return 0;
+}
+
+static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
+{
+ unsigned long cnt = 0;
+
+ for (; n > 0; n--, rela++)
+ {
+ switch (ELF32_R_TYPE(rela->r_info)) {
+ case R_PARISC_PCREL17F:
+ case R_PARISC_PCREL22F:
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+#else
+static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n)
+{
+ unsigned long cnt = 0;
+
+ for (; n > 0; n--, rela++)
+ {
+ switch (ELF64_R_TYPE(rela->r_info)) {
+ case R_PARISC_LTOFF21L:
+ case R_PARISC_LTOFF14R:
+ case R_PARISC_PCREL22F:
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+
+static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n)
+{
+ unsigned long cnt = 0;
+
+ for (; n > 0; n--, rela++)
+ {
+ switch (ELF64_R_TYPE(rela->r_info)) {
+ case R_PARISC_FPTR64:
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+
+static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
+{
+ unsigned long cnt = 0;
+
+ for (; n > 0; n--, rela++)
+ {
+ switch (ELF64_R_TYPE(rela->r_info)) {
+ case R_PARISC_PCREL22F:
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+#endif
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+#define CONST
+int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
+ CONST Elf_Shdr *sechdrs,
+ CONST char *secstrings,
+ struct module *me)
+{
+ unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0;
+ unsigned int i;
+
+ for (i = 1; i < hdr->e_shnum; i++) {
+ const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset;
+ unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels);
+
+ if (strncmp(secstrings + sechdrs[i].sh_name,
+ ".PARISC.unwind", 14) == 0)
+ me->arch.unwind_section = i;
+
+ if (sechdrs[i].sh_type != SHT_RELA)
+ continue;
+
+ /* some of these are not relevant for 32-bit/64-bit
+ * we leave them here to make the code common. the
+ * compiler will do its thing and optimize out the
+ * stuff we don't need
+ */
+ gots += count_gots(rels, nrels);
+ fdescs += count_fdescs(rels, nrels);
+ if(strncmp(secstrings + sechdrs[i].sh_name,
+ ".rela.init", 10) == 0)
+ init_stubs += count_stubs(rels, nrels);
+ else
+ stubs += count_stubs(rels, nrels);
+ }
+
+ /* align things a bit */
+ me->core_size = ALIGN(me->core_size, 16);
+ me->arch.got_offset = me->core_size;
+ me->core_size += gots * sizeof(struct got_entry);
+
+ me->core_size = ALIGN(me->core_size, 16);
+ me->arch.fdesc_offset = me->core_size;
+ me->core_size += fdescs * sizeof(Elf_Fdesc);
+
+ me->core_size = ALIGN(me->core_size, 16);
+ me->arch.stub_offset = me->core_size;
+ me->core_size += stubs * sizeof(struct stub_entry);
+
+ me->init_size = ALIGN(me->init_size, 16);
+ me->arch.init_stub_offset = me->init_size;
+ me->init_size += init_stubs * sizeof(struct stub_entry);
+
+ me->arch.got_max = gots;
+ me->arch.fdesc_max = fdescs;
+ me->arch.stub_max = stubs;
+ me->arch.init_stub_max = init_stubs;
+
+ return 0;
+}
+
+#ifdef __LP64__
+static Elf64_Word get_got(struct module *me, unsigned long value, long addend)
+{
+ unsigned int i;
+ struct got_entry *got;
+
+ value += addend;
+
+ BUG_ON(value == 0);
+
+ got = me->module_core + me->arch.got_offset;
+ for (i = 0; got[i].addr; i++)
+ if (got[i].addr == value)
+ goto out;
+
+ BUG_ON(++me->arch.got_count > me->arch.got_max);
+
+ got[i].addr = value;
+ out:
+ DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry),
+ value);
+ return i * sizeof(struct got_entry);
+}
+#endif /* __LP64__ */
+
+#ifdef __LP64__
+static Elf_Addr get_fdesc(struct module *me, unsigned long value)
+{
+ Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
+
+ if (!value) {
+ printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
+ return 0;
+ }
+
+ /* Look for existing fdesc entry. */
+ while (fdesc->addr) {
+ if (fdesc->addr == value)
+ return (Elf_Addr)fdesc;
+ fdesc++;
+ }
+
+ BUG_ON(++me->arch.fdesc_count > me->arch.fdesc_max);
+
+ /* Create new one */
+ fdesc->addr = value;
+ fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
+ return (Elf_Addr)fdesc;
+}
+#endif /* __LP64__ */
+
+static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
+ int millicode, int init_section)
+{
+ unsigned long i;
+ struct stub_entry *stub;
+
+ if(init_section) {
+ i = me->arch.init_stub_count++;
+ BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
+ stub = me->module_init + me->arch.init_stub_offset +
+ i * sizeof(struct stub_entry);
+ } else {
+ i = me->arch.stub_count++;
+ BUG_ON(me->arch.stub_count > me->arch.stub_max);
+ stub = me->module_core + me->arch.stub_offset +
+ i * sizeof(struct stub_entry);
+ }
+
+#ifndef __LP64__
+/* for 32-bit the stub looks like this:
+ * ldil L'XXX,%r1
+ * be,n R'XXX(%sr4,%r1)
+ */
+ //value = *(unsigned long *)((value + addend) & ~3); /* why? */
+
+ stub->insns[0] = 0x20200000; /* ldil L'XXX,%r1 */
+ stub->insns[1] = 0xe0202002; /* be,n R'XXX(%sr4,%r1) */
+
+ stub->insns[0] |= reassemble_21(lrsel(value, addend));
+ stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4);
+
+#else
+/* for 64-bit we have two kinds of stubs:
+ * for normal function calls:
+ * ldd 0(%dp),%dp
+ * ldd 10(%dp), %r1
+ * bve (%r1)
+ * ldd 18(%dp), %dp
+ *
+ * for millicode:
+ * ldil 0, %r1
+ * ldo 0(%r1), %r1
+ * ldd 10(%r1), %r1
+ * bve,n (%r1)
+ */
+ if (!millicode)
+ {
+ stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */
+ stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */
+ stub->insns[2] = 0xe820d000; /* bve (%r1) */
+ stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */
+
+ stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff);
+ }
+ else
+ {
+ stub->insns[0] = 0x20200000; /* ldil 0,%r1 */
+ stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */
+ stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */
+ stub->insns[3] = 0xe820d002; /* bve,n (%r1) */
+
+ stub->insns[0] |= reassemble_21(lrsel(value, addend));
+ stub->insns[1] |= reassemble_14(rrsel(value, addend));
+ }
+#endif
+
+ return (Elf_Addr)stub;
+}
+
+int apply_relocate(Elf_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ /* parisc should not need this ... */
+ printk(KERN_ERR "module %s: RELOCATION unsupported\n",
+ me->name);
+ return -ENOEXEC;
+}
+
+#ifndef __LP64__
+int apply_relocate_add(Elf_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ int i;
+ Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ Elf32_Word *loc;
+ Elf32_Addr val;
+ Elf32_Sword addend;
+ Elf32_Addr dot;
+ //unsigned long dp = (unsigned long)$global$;
+ register unsigned long dp asm ("r27");
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+ if (!sym->st_value) {
+ printk(KERN_WARNING "%s: Unknown symbol %s\n",
+ me->name, strtab + sym->st_name);
+ return -ENOENT;
+ }
+ //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
+ dot = (Elf32_Addr)loc & ~0x03;
+
+ val = sym->st_value;
+ addend = rel[i].r_addend;
+
+#if 0
+#define r(t) ELF32_R_TYPE(rel[i].r_info)==t ? #t :
+ DEBUGP("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n",
+ strtab + sym->st_name,
+ (uint32_t)loc, val, addend,
+ r(R_PARISC_PLABEL32)
+ r(R_PARISC_DIR32)
+ r(R_PARISC_DIR21L)
+ r(R_PARISC_DIR14R)
+ r(R_PARISC_SEGREL32)
+ r(R_PARISC_DPREL21L)
+ r(R_PARISC_DPREL14R)
+ r(R_PARISC_PCREL17F)
+ r(R_PARISC_PCREL22F)
+ "UNKNOWN");
+#undef r
+#endif
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_PARISC_PLABEL32:
+ /* 32-bit function address */
+ /* no function descriptors... */
+ *loc = fsel(val, addend);
+ break;
+ case R_PARISC_DIR32:
+ /* direct 32-bit ref */
+ *loc = fsel(val, addend);
+ break;
+ case R_PARISC_DIR21L:
+ /* left 21 bits of effective address */
+ val = lrsel(val, addend);
+ *loc = mask(*loc, 21) | reassemble_21(val);
+ break;
+ case R_PARISC_DIR14R:
+ /* right 14 bits of effective address */
+ val = rrsel(val, addend);
+ *loc = mask(*loc, 14) | reassemble_14(val);
+ break;
+ case R_PARISC_SEGREL32:
+ /* 32-bit segment relative address */
+ /* See note about special handling of SEGREL32 at
+ * the beginning of this file.
+ */
+ *loc = fsel(val, addend);
+ break;
+ case R_PARISC_DPREL21L:
+ /* left 21 bit of relative address */
+ val = lrsel(val - dp, addend);
+ *loc = mask(*loc, 21) | reassemble_21(val);
+ break;
+ case R_PARISC_DPREL14R:
+ /* right 14 bit of relative address */
+ val = rrsel(val - dp, addend);
+ *loc = mask(*loc, 14) | reassemble_14(val);
+ break;
+ case R_PARISC_PCREL17F:
+ /* 17-bit PC relative address */
+ val = get_stub(me, val, addend, 0, is_init(me, loc));
+ val = (val - dot - 8)/4;
+ CHECK_RELOC(val, 17)
+ *loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
+ break;
+ case R_PARISC_PCREL22F:
+ /* 22-bit PC relative address; only defined for pa20 */
+ val = get_stub(me, val, addend, 0, is_init(me, loc));
+ DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n",
+ strtab + sym->st_name, (unsigned long)loc, addend,
+ val)
+ val = (val - dot - 8)/4;
+ CHECK_RELOC(val, 22);
+ *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
+ break;
+
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+
+ return 0;
+}
+
+#else
+int apply_relocate_add(Elf_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ int i;
+ Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf64_Sym *sym;
+ Elf64_Word *loc;
+ Elf64_Xword *loc64;
+ Elf64_Addr val;
+ Elf64_Sxword addend;
+ Elf64_Addr dot;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to */
+ sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
+ + ELF64_R_SYM(rel[i].r_info);
+ if (!sym->st_value) {
+ printk(KERN_WARNING "%s: Unknown symbol %s\n",
+ me->name, strtab + sym->st_name);
+ return -ENOENT;
+ }
+ //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
+ dot = (Elf64_Addr)loc & ~0x03;
+ loc64 = (Elf64_Xword *)loc;
+
+ val = sym->st_value;
+ addend = rel[i].r_addend;
+
+#if 0
+#define r(t) ELF64_R_TYPE(rel[i].r_info)==t ? #t :
+ printk("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n",
+ strtab + sym->st_name,
+ loc, val, addend,
+ r(R_PARISC_LTOFF14R)
+ r(R_PARISC_LTOFF21L)
+ r(R_PARISC_PCREL22F)
+ r(R_PARISC_DIR64)
+ r(R_PARISC_SEGREL32)
+ r(R_PARISC_FPTR64)
+ "UNKNOWN");
+#undef r
+#endif
+
+ switch (ELF64_R_TYPE(rel[i].r_info)) {
+ case R_PARISC_LTOFF21L:
+ /* LT-relative; left 21 bits */
+ val = get_got(me, val, addend);
+ DEBUGP("LTOFF21L Symbol %s loc %p val %lx\n",
+ strtab + sym->st_name,
+ loc, val);
+ val = lrsel(val, 0);
+ *loc = mask(*loc, 21) | reassemble_21(val);
+ break;
+ case R_PARISC_LTOFF14R:
+ /* L(ltoff(val+addend)) */
+ /* LT-relative; right 14 bits */
+ val = get_got(me, val, addend);
+ val = rrsel(val, 0);
+ DEBUGP("LTOFF14R Symbol %s loc %p val %lx\n",
+ strtab + sym->st_name,
+ loc, val);
+ *loc = mask(*loc, 14) | reassemble_14(val);
+ break;
+ case R_PARISC_PCREL22F:
+ /* PC-relative; 22 bits */
+ DEBUGP("PCREL22F Symbol %s loc %p val %lx\n",
+ strtab + sym->st_name,
+ loc, val);
+ /* can we reach it locally? */
+ if(!is_local(me, (void *)val)) {
+ if (strncmp(strtab + sym->st_name, "$$", 2)
+ == 0)
+ val = get_stub(me, val, addend, 1,
+ is_init(me, loc));
+ else
+ val = get_stub(me, val, addend, 0,
+ is_init(me, loc));
+ }
+ DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n",
+ strtab + sym->st_name, loc, sym->st_value,
+ addend, val);
+ /* FIXME: local symbols work as long as the
+ * core and init pieces aren't separated too
+ * far. If this is ever broken, you will trip
+ * the check below. The way to fix it would
+ * be to generate local stubs to go between init
+ * and core */
+ if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 ||
+ (Elf64_Sxword)(val - dot - 8) < -0x800000) {
+ printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n",
+ me->name, strtab + sym->st_name);
+ return -ENOEXEC;
+ }
+ val = (val - dot - 8)/4;
+ *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
+ break;
+ case R_PARISC_DIR64:
+ /* 64-bit effective address */
+ *loc64 = val + addend;
+ break;
+ case R_PARISC_SEGREL32:
+ /* 32-bit segment relative address */
+ /* See note about special handling of SEGREL32 at
+ * the beginning of this file.
+ */
+ *loc = fsel(val, addend);
+ break;
+ case R_PARISC_FPTR64:
+ /* 64-bit function address */
+ if(is_local(me, (void *)(val + addend))) {
+ *loc64 = get_fdesc(me, val+addend);
+ DEBUGP("FDESC for %s at %p points to %lx\n",
+ strtab + sym->st_name, *loc64,
+ ((Elf_Fdesc *)*loc64)->addr);
+ } else {
+ /* if the symbol is not local to this
+ * module then val+addend is a pointer
+ * to the function descriptor */
+ DEBUGP("Non local FPTR64 Symbol %s loc %p val %lx\n",
+ strtab + sym->st_name,
+ loc, val);
+ *loc64 = val + addend;
+ }
+ break;
+
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %Lu\n",
+ me->name, ELF64_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+#endif
+
+static void
+register_unwind_table(struct module *me,
+ const Elf_Shdr *sechdrs)
+{
+ unsigned char *table, *end;
+ unsigned long gp;
+
+ if (!me->arch.unwind_section)
+ return;
+
+ table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
+ end = table + sechdrs[me->arch.unwind_section].sh_size;
+ gp = (Elf_Addr)me->module_core + me->arch.got_offset;
+
+ DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
+ me->arch.unwind_section, table, end, gp);
+ me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end);
+}
+
+static void
+deregister_unwind_table(struct module *me)
+{
+ if (me->arch.unwind)
+ unwind_table_remove(me->arch.unwind);
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ int i;
+ unsigned long nsyms;
+ const char *strtab = NULL;
+ Elf_Sym *newptr, *oldptr;
+ Elf_Shdr *symhdr = NULL;
+#ifdef DEBUG
+ Elf_Fdesc *entry;
+ u32 *addr;
+
+ entry = (Elf_Fdesc *)me->init;
+ printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry,
+ entry->gp, entry->addr);
+ addr = (u32 *)entry->addr;
+ printk("INSNS: %x %x %x %x\n",
+ addr[0], addr[1], addr[2], addr[3]);
+ printk("stubs used %ld, stubs max %ld\n"
+ "init_stubs used %ld, init stubs max %ld\n"
+ "got entries used %ld, gots max %ld\n"
+ "fdescs used %ld, fdescs max %ld\n",
+ me->arch.stub_count, me->arch.stub_max,
+ me->arch.init_stub_count, me->arch.init_stub_max,
+ me->arch.got_count, me->arch.got_max,
+ me->arch.fdesc_count, me->arch.fdesc_max);
+#endif
+
+ register_unwind_table(me, sechdrs);
+
+ /* haven't filled in me->symtab yet, so have to find it
+ * ourselves */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if(sechdrs[i].sh_type == SHT_SYMTAB
+ && (sechdrs[i].sh_type & SHF_ALLOC)) {
+ int strindex = sechdrs[i].sh_link;
+ /* FIXME: AWFUL HACK
+ * The cast is to drop the const from
+ * the sechdrs pointer */
+ symhdr = (Elf_Shdr *)&sechdrs[i];
+ strtab = (char *)sechdrs[strindex].sh_addr;
+ break;
+ }
+ }
+
+ DEBUGP("module %s: strtab %p, symhdr %p\n",
+ me->name, strtab, symhdr);
+
+ if(me->arch.got_count > MAX_GOTS) {
+ printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d\n", me->name, me->arch.got_count, MAX_GOTS);
+ return -EINVAL;
+ }
+
+ /* no symbol table */
+ if(symhdr == NULL)
+ return 0;
+
+ oldptr = (void *)symhdr->sh_addr;
+ newptr = oldptr + 1; /* we start counting at 1 */
+ nsyms = symhdr->sh_size / sizeof(Elf_Sym);
+ DEBUGP("OLD num_symtab %lu\n", nsyms);
+
+ for (i = 1; i < nsyms; i++) {
+ oldptr++; /* note, count starts at 1 so preincrement */
+ if(strncmp(strtab + oldptr->st_name,
+ ".L", 2) == 0)
+ continue;
+
+ if(newptr != oldptr)
+ *newptr++ = *oldptr;
+ else
+ newptr++;
+
+ }
+ nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
+ DEBUGP("NEW num_symtab %lu\n", nsyms);
+ symhdr->sh_size = nsyms * sizeof(Elf_Sym);
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+ deregister_unwind_table(mod);
+}
diff --git a/arch/parisc/kernel/pa7300lc.c b/arch/parisc/kernel/pa7300lc.c
new file mode 100644
index 000000000000..8a89780223aa
--- /dev/null
+++ b/arch/parisc/kernel/pa7300lc.c
@@ -0,0 +1,49 @@
+/*
+ * linux/arch/parisc/kernel/pa7300lc.c
+ * - PA7300LC-specific functions
+ *
+ * Copyright (C) 2000 Philipp Rumpf */
+
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/machdep.h>
+
+/* CPU register indices */
+
+#define MIOC_STATUS 0xf040
+#define MIOC_CONTROL 0xf080
+#define MDERRADD 0xf0e0
+#define DMAERR 0xf0e8
+#define DIOERR 0xf0ec
+#define HIDMAMEM 0xf0f4
+
+/* this returns the HPA of the CPU it was called on */
+static u32 cpu_hpa(void)
+{
+ return 0xfffb0000;
+}
+
+static void pa7300lc_lpmc(int code, struct pt_regs *regs)
+{
+ u32 hpa;
+ printk(KERN_WARNING "LPMC on CPU %d\n", smp_processor_id());
+
+ show_regs(regs);
+
+ hpa = cpu_hpa();
+ printk(KERN_WARNING
+ "MIOC_CONTROL %08x\n" "MIOC_STATUS %08x\n"
+ "MDERRADD %08x\n" "DMAERR %08x\n"
+ "DIOERR %08x\n" "HIDMAMEM %08x\n",
+ gsc_readl(hpa+MIOC_CONTROL), gsc_readl(hpa+MIOC_STATUS),
+ gsc_readl(hpa+MDERRADD), gsc_readl(hpa+DMAERR),
+ gsc_readl(hpa+DIOERR), gsc_readl(hpa+HIDMAMEM));
+}
+
+void pa7300lc_init(void)
+{
+ cpu_lpmc = pa7300lc_lpmc;
+}
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
new file mode 100644
index 000000000000..77e03bc0f935
--- /dev/null
+++ b/arch/parisc/kernel/pacache.S
@@ -0,0 +1,1086 @@
+/*
+ * PARISC TLB and cache flushing support
+ * Copyright (C) 2000-2001 Hewlett-Packard (John Marvin)
+ * Copyright (C) 2001 Matthew Wilcox (willy at parisc-linux.org)
+ * Copyright (C) 2002 Richard Hirst (rhirst with parisc-linux.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * NOTE: fdc,fic, and pdc instructions that use base register modification
+ * should only use index and base registers that are not shadowed,
+ * so that the fast path emulation in the non access miss handler
+ * can be used.
+ */
+
+#ifdef __LP64__
+#define ADDIB addib,*
+#define CMPB cmpb,*
+#define ANDCM andcm,*
+
+ .level 2.0w
+#else
+#define ADDIB addib,
+#define CMPB cmpb,
+#define ANDCM andcm
+
+ .level 2.0
+#endif
+
+#include <asm/assembly.h>
+#include <asm/psw.h>
+#include <asm/pgtable.h>
+#include <asm/cache.h>
+
+ .text
+ .align 128
+
+ .export flush_tlb_all_local,code
+
+flush_tlb_all_local:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ /*
+ * The pitlbe and pdtlbe instructions should only be used to
+ * flush the entire tlb. Also, there needs to be no intervening
+ * tlb operations, e.g. tlb misses, so the operation needs
+ * to happen in real mode with all interruptions disabled.
+ */
+
+ /*
+ * Once again, we do the rfi dance ... some day we need examine
+ * all of our uses of this type of code and see what can be
+ * consolidated.
+ */
+
+ rsm PSW_SM_I, %r19 /* relied upon translation! PA 2.0 Arch. F-5 */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ rsm PSW_SM_Q, %r0 /* Turn off Q bit to load iia queue */
+ ldil L%REAL_MODE_PSW, %r1
+ ldo R%REAL_MODE_PSW(%r1), %r1
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ ldil L%PA(1f), %r1
+ ldo R%PA(1f)(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
+ rfi
+ nop
+
+1: ldil L%PA(cache_info), %r1
+ ldo R%PA(cache_info)(%r1), %r1
+
+ /* Flush Instruction Tlb */
+
+ LDREG ITLB_SID_BASE(%r1), %r20
+ LDREG ITLB_SID_STRIDE(%r1), %r21
+ LDREG ITLB_SID_COUNT(%r1), %r22
+ LDREG ITLB_OFF_BASE(%r1), %arg0
+ LDREG ITLB_OFF_STRIDE(%r1), %arg1
+ LDREG ITLB_OFF_COUNT(%r1), %arg2
+ LDREG ITLB_LOOP(%r1), %arg3
+
+ ADDIB= -1, %arg3, fitoneloop /* Preadjust and test */
+ movb,<,n %arg3, %r31, fitdone /* If loop < 0, skip */
+ copy %arg0, %r28 /* Init base addr */
+
+fitmanyloop: /* Loop if LOOP >= 2 */
+ mtsp %r20, %sr1
+ add %r21, %r20, %r20 /* increment space */
+ copy %arg2, %r29 /* Init middle loop count */
+
+fitmanymiddle: /* Loop if LOOP >= 2 */
+ ADDIB> -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
+ pitlbe 0(%sr1, %r28)
+ pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */
+ ADDIB> -1, %r29, fitmanymiddle /* Middle loop decr */
+ copy %arg3, %r31 /* Re-init inner loop count */
+
+ movb,tr %arg0, %r28, fitmanyloop /* Re-init base addr */
+ ADDIB<=,n -1, %r22, fitdone /* Outer loop count decr */
+
+fitoneloop: /* Loop if LOOP = 1 */
+ mtsp %r20, %sr1
+ copy %arg0, %r28 /* init base addr */
+ copy %arg2, %r29 /* init middle loop count */
+
+fitonemiddle: /* Loop if LOOP = 1 */
+ ADDIB> -1, %r29, fitonemiddle /* Middle loop count decr */
+ pitlbe,m %arg1(%sr1, %r28) /* pitlbe for one loop */
+
+ ADDIB> -1, %r22, fitoneloop /* Outer loop count decr */
+ add %r21, %r20, %r20 /* increment space */
+
+fitdone:
+
+ /* Flush Data Tlb */
+
+ LDREG DTLB_SID_BASE(%r1), %r20
+ LDREG DTLB_SID_STRIDE(%r1), %r21
+ LDREG DTLB_SID_COUNT(%r1), %r22
+ LDREG DTLB_OFF_BASE(%r1), %arg0
+ LDREG DTLB_OFF_STRIDE(%r1), %arg1
+ LDREG DTLB_OFF_COUNT(%r1), %arg2
+ LDREG DTLB_LOOP(%r1), %arg3
+
+ ADDIB= -1, %arg3, fdtoneloop /* Preadjust and test */
+ movb,<,n %arg3, %r31, fdtdone /* If loop < 0, skip */
+ copy %arg0, %r28 /* Init base addr */
+
+fdtmanyloop: /* Loop if LOOP >= 2 */
+ mtsp %r20, %sr1
+ add %r21, %r20, %r20 /* increment space */
+ copy %arg2, %r29 /* Init middle loop count */
+
+fdtmanymiddle: /* Loop if LOOP >= 2 */
+ ADDIB> -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
+ pdtlbe 0(%sr1, %r28)
+ pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */
+ ADDIB> -1, %r29, fdtmanymiddle /* Middle loop decr */
+ copy %arg3, %r31 /* Re-init inner loop count */
+
+ movb,tr %arg0, %r28, fdtmanyloop /* Re-init base addr */
+ ADDIB<=,n -1, %r22,fdtdone /* Outer loop count decr */
+
+fdtoneloop: /* Loop if LOOP = 1 */
+ mtsp %r20, %sr1
+ copy %arg0, %r28 /* init base addr */
+ copy %arg2, %r29 /* init middle loop count */
+
+fdtonemiddle: /* Loop if LOOP = 1 */
+ ADDIB> -1, %r29, fdtonemiddle /* Middle loop count decr */
+ pdtlbe,m %arg1(%sr1, %r28) /* pdtlbe for one loop */
+
+ ADDIB> -1, %r22, fdtoneloop /* Outer loop count decr */
+ add %r21, %r20, %r20 /* increment space */
+
+fdtdone:
+
+ /* Switch back to virtual mode */
+
+ rsm PSW_SM_Q, %r0 /* clear Q bit to load iia queue */
+ ldil L%KERNEL_PSW, %r1
+ ldo R%KERNEL_PSW(%r1), %r1
+ or %r1, %r19, %r1 /* Set I bit if set on entry */
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ ldil L%(2f), %r1
+ ldo R%(2f)(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
+ rfi
+ nop
+
+2: bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_instruction_cache_local,code
+ .import cache_info,data
+
+flush_instruction_cache_local:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ mtsp %r0, %sr1
+ ldil L%cache_info, %r1
+ ldo R%cache_info(%r1), %r1
+
+ /* Flush Instruction Cache */
+
+ LDREG ICACHE_BASE(%r1), %arg0
+ LDREG ICACHE_STRIDE(%r1), %arg1
+ LDREG ICACHE_COUNT(%r1), %arg2
+ LDREG ICACHE_LOOP(%r1), %arg3
+ rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/
+ ADDIB= -1, %arg3, fioneloop /* Preadjust and test */
+ movb,<,n %arg3, %r31, fisync /* If loop < 0, do sync */
+
+fimanyloop: /* Loop if LOOP >= 2 */
+ ADDIB> -1, %r31, fimanyloop /* Adjusted inner loop decr */
+ fice 0(%sr1, %arg0)
+ fice,m %arg1(%sr1, %arg0) /* Last fice and addr adjust */
+ movb,tr %arg3, %r31, fimanyloop /* Re-init inner loop count */
+ ADDIB<=,n -1, %arg2, fisync /* Outer loop decr */
+
+fioneloop: /* Loop if LOOP = 1 */
+ ADDIB> -1, %arg2, fioneloop /* Outer loop count decr */
+ fice,m %arg1(%sr1, %arg0) /* Fice for one loop */
+
+fisync:
+ sync
+ mtsm %r22
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_data_cache_local, code
+ .import cache_info, data
+
+flush_data_cache_local:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ mtsp %r0, %sr1
+ ldil L%cache_info, %r1
+ ldo R%cache_info(%r1), %r1
+
+ /* Flush Data Cache */
+
+ LDREG DCACHE_BASE(%r1), %arg0
+ LDREG DCACHE_STRIDE(%r1), %arg1
+ LDREG DCACHE_COUNT(%r1), %arg2
+ LDREG DCACHE_LOOP(%r1), %arg3
+ rsm PSW_SM_I, %r22
+ ADDIB= -1, %arg3, fdoneloop /* Preadjust and test */
+ movb,<,n %arg3, %r31, fdsync /* If loop < 0, do sync */
+
+fdmanyloop: /* Loop if LOOP >= 2 */
+ ADDIB> -1, %r31, fdmanyloop /* Adjusted inner loop decr */
+ fdce 0(%sr1, %arg0)
+ fdce,m %arg1(%sr1, %arg0) /* Last fdce and addr adjust */
+ movb,tr %arg3, %r31, fdmanyloop /* Re-init inner loop count */
+ ADDIB<=,n -1, %arg2, fdsync /* Outer loop decr */
+
+fdoneloop: /* Loop if LOOP = 1 */
+ ADDIB> -1, %arg2, fdoneloop /* Outer loop count decr */
+ fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */
+
+fdsync:
+ syncdma
+ sync
+ mtsm %r22
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export copy_user_page_asm,code
+ .align 16
+
+copy_user_page_asm:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+#ifdef __LP64__
+ /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
+ * Unroll the loop by hand and arrange insn appropriately.
+ * GCC probably can do this just as well.
+ */
+
+ ldd 0(%r25), %r19
+ ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
+ ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */
+ ldw 128(%r25), %r0 /* prefetch 2 */
+
+1: ldd 8(%r25), %r20
+ ldw 192(%r25), %r0 /* prefetch 3 */
+ ldw 256(%r25), %r0 /* prefetch 4 */
+
+ ldd 16(%r25), %r21
+ ldd 24(%r25), %r22
+ std %r19, 0(%r26)
+ std %r20, 8(%r26)
+
+ ldd 32(%r25), %r19
+ ldd 40(%r25), %r20
+ std %r21, 16(%r26)
+ std %r22, 24(%r26)
+
+ ldd 48(%r25), %r21
+ ldd 56(%r25), %r22
+ std %r19, 32(%r26)
+ std %r20, 40(%r26)
+
+ ldd 64(%r25), %r19
+ ldd 72(%r25), %r20
+ std %r21, 48(%r26)
+ std %r22, 56(%r26)
+
+ ldd 80(%r25), %r21
+ ldd 88(%r25), %r22
+ std %r19, 64(%r26)
+ std %r20, 72(%r26)
+
+ ldd 96(%r25), %r19
+ ldd 104(%r25), %r20
+ std %r21, 80(%r26)
+ std %r22, 88(%r26)
+
+ ldd 112(%r25), %r21
+ ldd 120(%r25), %r22
+ std %r19, 96(%r26)
+ std %r20, 104(%r26)
+
+ ldo 128(%r25), %r25
+ std %r21, 112(%r26)
+ std %r22, 120(%r26)
+ ldo 128(%r26), %r26
+
+ ADDIB> -1, %r1, 1b /* bundle 10 */
+ ldd 0(%r25), %r19 /* start next loads */
+
+#else
+
+ /*
+ * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
+ * bundles (very restricted rules for bundling).
+ * Note that until (if) we start saving
+ * the full 64 bit register values on interrupt, we can't
+ * use ldd/std on a 32 bit kernel.
+ */
+ ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
+
+1:
+ ldw 0(%r25), %r19
+ ldw 4(%r25), %r20
+ ldw 8(%r25), %r21
+ ldw 12(%r25), %r22
+ stw %r19, 0(%r26)
+ stw %r20, 4(%r26)
+ stw %r21, 8(%r26)
+ stw %r22, 12(%r26)
+ ldw 16(%r25), %r19
+ ldw 20(%r25), %r20
+ ldw 24(%r25), %r21
+ ldw 28(%r25), %r22
+ stw %r19, 16(%r26)
+ stw %r20, 20(%r26)
+ stw %r21, 24(%r26)
+ stw %r22, 28(%r26)
+ ldw 32(%r25), %r19
+ ldw 36(%r25), %r20
+ ldw 40(%r25), %r21
+ ldw 44(%r25), %r22
+ stw %r19, 32(%r26)
+ stw %r20, 36(%r26)
+ stw %r21, 40(%r26)
+ stw %r22, 44(%r26)
+ ldw 48(%r25), %r19
+ ldw 52(%r25), %r20
+ ldw 56(%r25), %r21
+ ldw 60(%r25), %r22
+ stw %r19, 48(%r26)
+ stw %r20, 52(%r26)
+ stw %r21, 56(%r26)
+ stw %r22, 60(%r26)
+ ldo 64(%r26), %r26
+ ADDIB> -1, %r1, 1b
+ ldo 64(%r25), %r25
+#endif
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+/*
+ * NOTE: Code in clear_user_page has a hard coded dependency on the
+ * maximum alias boundary being 4 Mb. We've been assured by the
+ * parisc chip designers that there will not ever be a parisc
+ * chip with a larger alias boundary (Never say never :-) ).
+ *
+ * Subtle: the dtlb miss handlers support the temp alias region by
+ * "knowing" that if a dtlb miss happens within the temp alias
+ * region it must have occurred while in clear_user_page. Since
+ * this routine makes use of processor local translations, we
+ * don't want to insert them into the kernel page table. Instead,
+ * we load up some general registers (they need to be registers
+ * which aren't shadowed) with the physical page numbers (preshifted
+ * for tlb insertion) needed to insert the translations. When we
+ * miss on the translation, the dtlb miss handler inserts the
+ * translation into the tlb using these values:
+ *
+ * %r26 physical page (shifted for tlb insert) of "to" translation
+ * %r23 physical page (shifted for tlb insert) of "from" translation
+ */
+
+#if 0
+
+ /*
+ * We can't do this since copy_user_page is used to bring in
+ * file data that might have instructions. Since the data would
+ * then need to be flushed out so the i-fetch can see it, it
+ * makes more sense to just copy through the kernel translation
+ * and flush it.
+ *
+ * I'm still keeping this around because it may be possible to
+ * use it if more information is passed into copy_user_page().
+ * Have to do some measurements to see if it is worthwhile to
+ * lobby for such a change.
+ */
+
+ .export copy_user_page_asm,code
+
+copy_user_page_asm:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%(__PAGE_OFFSET), %r1
+ sub %r26, %r1, %r26
+ sub %r25, %r1, %r23 /* move physical addr into non shadowed reg */
+
+ ldil L%(TMPALIAS_MAP_START), %r28
+#ifdef __LP64__
+ extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */
+ extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */
+ depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */
+ depdi 0, 63,12, %r28 /* Clear any offset bits */
+ copy %r28, %r29
+ depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */
+#else
+ extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
+ extrw,u %r23, 24,25, %r23 /* convert phys addr to tlb insert format */
+ depw %r24, 31,22, %r28 /* Form aliased virtual address 'to' */
+ depwi 0, 31,12, %r28 /* Clear any offset bits */
+ copy %r28, %r29
+ depwi 1, 9,1, %r29 /* Form aliased virtual address 'from' */
+#endif
+
+ /* Purge any old translations */
+
+ pdtlb 0(%r28)
+ pdtlb 0(%r29)
+
+ ldi 64, %r1
+
+ /*
+ * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
+ * bundles (very restricted rules for bundling). It probably
+ * does OK on PCXU and better, but we could do better with
+ * ldd/std instructions. Note that until (if) we start saving
+ * the full 64 bit register values on interrupt, we can't
+ * use ldd/std on a 32 bit kernel.
+ */
+
+
+1:
+ ldw 0(%r29), %r19
+ ldw 4(%r29), %r20
+ ldw 8(%r29), %r21
+ ldw 12(%r29), %r22
+ stw %r19, 0(%r28)
+ stw %r20, 4(%r28)
+ stw %r21, 8(%r28)
+ stw %r22, 12(%r28)
+ ldw 16(%r29), %r19
+ ldw 20(%r29), %r20
+ ldw 24(%r29), %r21
+ ldw 28(%r29), %r22
+ stw %r19, 16(%r28)
+ stw %r20, 20(%r28)
+ stw %r21, 24(%r28)
+ stw %r22, 28(%r28)
+ ldw 32(%r29), %r19
+ ldw 36(%r29), %r20
+ ldw 40(%r29), %r21
+ ldw 44(%r29), %r22
+ stw %r19, 32(%r28)
+ stw %r20, 36(%r28)
+ stw %r21, 40(%r28)
+ stw %r22, 44(%r28)
+ ldw 48(%r29), %r19
+ ldw 52(%r29), %r20
+ ldw 56(%r29), %r21
+ ldw 60(%r29), %r22
+ stw %r19, 48(%r28)
+ stw %r20, 52(%r28)
+ stw %r21, 56(%r28)
+ stw %r22, 60(%r28)
+ ldo 64(%r28), %r28
+ ADDIB> -1, %r1,1b
+ ldo 64(%r29), %r29
+
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+#endif
+
+ .export __clear_user_page_asm,code
+
+__clear_user_page_asm:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ tophys_r1 %r26
+
+ ldil L%(TMPALIAS_MAP_START), %r28
+#ifdef __LP64__
+#if (TMPALIAS_MAP_START >= 0x80000000)
+ depdi 0, 31,32, %r28 /* clear any sign extension */
+#endif
+ extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
+ depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
+ depdi 0, 63,12, %r28 /* Clear any offset bits */
+#else
+ extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
+ depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
+ depwi 0, 31,12, %r28 /* Clear any offset bits */
+#endif
+
+ /* Purge any old translation */
+
+ pdtlb 0(%r28)
+
+#ifdef __LP64__
+ ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
+
+ /* PREFETCH (Write) has not (yet) been proven to help here */
+/* #define PREFETCHW_OP ldd 256(%0), %r0 */
+
+1: std %r0, 0(%r28)
+ std %r0, 8(%r28)
+ std %r0, 16(%r28)
+ std %r0, 24(%r28)
+ std %r0, 32(%r28)
+ std %r0, 40(%r28)
+ std %r0, 48(%r28)
+ std %r0, 56(%r28)
+ std %r0, 64(%r28)
+ std %r0, 72(%r28)
+ std %r0, 80(%r28)
+ std %r0, 88(%r28)
+ std %r0, 96(%r28)
+ std %r0, 104(%r28)
+ std %r0, 112(%r28)
+ std %r0, 120(%r28)
+ ADDIB> -1, %r1, 1b
+ ldo 128(%r28), %r28
+
+#else /* ! __LP64 */
+
+ ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
+
+1:
+ stw %r0, 0(%r28)
+ stw %r0, 4(%r28)
+ stw %r0, 8(%r28)
+ stw %r0, 12(%r28)
+ stw %r0, 16(%r28)
+ stw %r0, 20(%r28)
+ stw %r0, 24(%r28)
+ stw %r0, 28(%r28)
+ stw %r0, 32(%r28)
+ stw %r0, 36(%r28)
+ stw %r0, 40(%r28)
+ stw %r0, 44(%r28)
+ stw %r0, 48(%r28)
+ stw %r0, 52(%r28)
+ stw %r0, 56(%r28)
+ stw %r0, 60(%r28)
+ ADDIB> -1, %r1, 1b
+ ldo 64(%r28), %r28
+#endif /* __LP64 */
+
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_kernel_dcache_page
+
+flush_kernel_dcache_page:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+
+#ifdef __LP64__
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
+#else
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
+#endif
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+
+1: fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ CMPB<< %r26, %r25,1b
+ fdc,m %r23(%r26)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_user_dcache_page
+
+flush_user_dcache_page:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+
+#ifdef __LP64__
+ depdi,z 1,63-PAGE_SHIFT,1, %r25
+#else
+ depwi,z 1,31-PAGE_SHIFT,1, %r25
+#endif
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+
+1: fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ CMPB<< %r26, %r25,1b
+ fdc,m %r23(%sr3, %r26)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_user_icache_page
+
+flush_user_icache_page:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+
+#ifdef __LP64__
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
+#else
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
+#endif
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+
+1: fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ CMPB<< %r26, %r25,1b
+ fic,m %r23(%sr3, %r26)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+
+ .export purge_kernel_dcache_page
+
+purge_kernel_dcache_page:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+
+#ifdef __LP64__
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
+#else
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
+#endif
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+1: pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ CMPB<< %r26, %r25, 1b
+ pdc,m %r23(%r26)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+#if 0
+ /* Currently not used, but it still is a possible alternate
+ * solution.
+ */
+
+ .export flush_alias_page
+
+flush_alias_page:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ tophys_r1 %r26
+
+ ldil L%(TMPALIAS_MAP_START), %r28
+#ifdef __LP64__
+ extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
+ depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
+ depdi 0, 63,12, %r28 /* Clear any offset bits */
+#else
+ extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
+ depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
+ depwi 0, 31,12, %r28 /* Clear any offset bits */
+#endif
+
+ /* Purge any old translation */
+
+ pdtlb 0(%r28)
+
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+
+#ifdef __LP64__
+ depdi,z 1, 63-PAGE_SHIFT,1, %r29
+#else
+ depwi,z 1, 31-PAGE_SHIFT,1, %r29
+#endif
+ add %r28, %r29, %r29
+ sub %r29, %r23, %r29
+
+1: fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ CMPB<< %r28, %r29, 1b
+ fdc,m %r23(%r28)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+#endif
+
+ .export flush_user_dcache_range_asm
+
+flush_user_dcache_range_asm:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
+
+1: CMPB<<,n %r26, %r25, 1b
+ fdc,m %r23(%sr3, %r26)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_kernel_dcache_range_asm
+
+flush_kernel_dcache_range_asm:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
+
+1: CMPB<<,n %r26, %r25,1b
+ fdc,m %r23(%r26)
+
+ sync
+ syncdma
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_user_icache_range_asm
+
+flush_user_icache_range_asm:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%icache_stride, %r1
+ ldw R%icache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
+
+1: CMPB<<,n %r26, %r25,1b
+ fic,m %r23(%sr3, %r26)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_kernel_icache_page
+
+flush_kernel_icache_page:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%icache_stride, %r1
+ ldw R%icache_stride(%r1), %r23
+
+#ifdef __LP64__
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
+#else
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
+#endif
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+
+1: fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ CMPB<< %r26, %r25, 1b
+ fic,m %r23(%r26)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .export flush_kernel_icache_range_asm
+
+flush_kernel_icache_range_asm:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%icache_stride, %r1
+ ldw R%icache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
+
+1: CMPB<<,n %r26, %r25, 1b
+ fic,m %r23(%r26)
+
+ sync
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .align 128
+
+ .export disable_sr_hashing_asm,code
+
+disable_sr_hashing_asm:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ /* Switch to real mode */
+
+ ssm 0, %r0 /* relied upon translation! */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ rsm (PSW_SM_Q|PSW_SM_I), %r0 /* disable Q&I to load the iia queue */
+ ldil L%REAL_MODE_PSW, %r1
+ ldo R%REAL_MODE_PSW(%r1), %r1
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ ldil L%PA(1f), %r1
+ ldo R%PA(1f)(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
+ rfi
+ nop
+
+1: cmpib,=,n SRHASH_PCXST, %r26,srdis_pcxs
+ cmpib,=,n SRHASH_PCXL, %r26,srdis_pcxl
+ cmpib,=,n SRHASH_PA20, %r26,srdis_pa20
+ b,n srdis_done
+
+srdis_pcxs:
+
+ /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
+
+ .word 0x141c1a00 /* mfdiag %dr0, %r28 */
+ .word 0x141c1a00 /* must issue twice */
+ depwi 0,18,1, %r28 /* Clear DHE (dcache hash enable) */
+ depwi 0,20,1, %r28 /* Clear IHE (icache hash enable) */
+ .word 0x141c1600 /* mtdiag %r28, %dr0 */
+ .word 0x141c1600 /* must issue twice */
+ b,n srdis_done
+
+srdis_pcxl:
+
+ /* Disable Space Register Hashing for PCXL */
+
+ .word 0x141c0600 /* mfdiag %dr0, %r28 */
+ depwi 0,28,2, %r28 /* Clear DHASH_EN & IHASH_EN */
+ .word 0x141c0240 /* mtdiag %r28, %dr0 */
+ b,n srdis_done
+
+srdis_pa20:
+
+ /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */
+
+ .word 0x144008bc /* mfdiag %dr2, %r28 */
+ depdi 0, 54,1, %r28 /* clear DIAG_SPHASH_ENAB (bit 54) */
+ .word 0x145c1840 /* mtdiag %r28, %dr2 */
+
+srdis_done:
+
+ /* Switch back to virtual mode */
+
+ rsm PSW_SM_Q, %r0 /* clear Q bit to load iia queue */
+ ldil L%KERNEL_PSW, %r1
+ ldo R%KERNEL_PSW(%r1), %r1
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ ldil L%(2f), %r1
+ ldo R%(2f)(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
+ rfi
+ nop
+
+2: bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+
+ .end
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
new file mode 100644
index 000000000000..f40a777dd388
--- /dev/null
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -0,0 +1,187 @@
+/*
+ * Architecture-specific kernel symbols
+ *
+ * Copyright (C) 2000-2001 Richard Hirst <rhirst with parisc-linux.org>
+ * Copyright (C) 2001 Dave Kennedy
+ * Copyright (C) 2001 Paul Bame <bame at parisc-linux.org>
+ * Copyright (C) 2001-2003 Grant Grundler <grundler with parisc-linux.org>
+ * Copyright (C) 2002-2003 Matthew Wilcox <willy at parisc-linux.org>
+ * Copyright (C) 2002 Randolph Chung <tausq at parisc-linux.org>
+ * Copyright (C) 2002-2003 Helge Deller <deller with parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/syscalls.h>
+
+#include <linux/string.h>
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strpbrk);
+
+#include <linux/pm.h>
+EXPORT_SYMBOL(pm_power_off);
+
+#include <asm/atomic.h>
+EXPORT_SYMBOL(__xchg8);
+EXPORT_SYMBOL(__xchg32);
+EXPORT_SYMBOL(__cmpxchg_u32);
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(__atomic_hash);
+#endif
+#ifdef __LP64__
+EXPORT_SYMBOL(__xchg64);
+EXPORT_SYMBOL(__cmpxchg_u64);
+#endif
+
+#include <asm/uaccess.h>
+EXPORT_SYMBOL(lstrncpy_from_user);
+EXPORT_SYMBOL(lclear_user);
+EXPORT_SYMBOL(lstrnlen_user);
+
+/* Global fixups */
+extern void fixup_get_user_skip_1(void);
+extern void fixup_get_user_skip_2(void);
+extern void fixup_put_user_skip_1(void);
+extern void fixup_put_user_skip_2(void);
+EXPORT_SYMBOL(fixup_get_user_skip_1);
+EXPORT_SYMBOL(fixup_get_user_skip_2);
+EXPORT_SYMBOL(fixup_put_user_skip_1);
+EXPORT_SYMBOL(fixup_put_user_skip_2);
+
+#ifndef __LP64__
+/* Needed so insmod can set dp value */
+extern int $global$;
+EXPORT_SYMBOL($global$);
+#endif
+
+#include <asm/io.h>
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(memcpy_toio);
+EXPORT_SYMBOL(memcpy_fromio);
+EXPORT_SYMBOL(memset_io);
+
+#include <asm/unistd.h>
+EXPORT_SYMBOL(sys_open);
+EXPORT_SYMBOL(sys_lseek);
+EXPORT_SYMBOL(sys_read);
+EXPORT_SYMBOL(sys_write);
+
+#include <asm/semaphore.h>
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down);
+
+extern void $$divI(void);
+extern void $$divU(void);
+extern void $$remI(void);
+extern void $$remU(void);
+extern void $$mulI(void);
+extern void $$divU_3(void);
+extern void $$divU_5(void);
+extern void $$divU_6(void);
+extern void $$divU_9(void);
+extern void $$divU_10(void);
+extern void $$divU_12(void);
+extern void $$divU_7(void);
+extern void $$divU_14(void);
+extern void $$divU_15(void);
+extern void $$divI_3(void);
+extern void $$divI_5(void);
+extern void $$divI_6(void);
+extern void $$divI_7(void);
+extern void $$divI_9(void);
+extern void $$divI_10(void);
+extern void $$divI_12(void);
+extern void $$divI_14(void);
+extern void $$divI_15(void);
+
+EXPORT_SYMBOL($$divI);
+EXPORT_SYMBOL($$divU);
+EXPORT_SYMBOL($$remI);
+EXPORT_SYMBOL($$remU);
+EXPORT_SYMBOL($$mulI);
+EXPORT_SYMBOL($$divU_3);
+EXPORT_SYMBOL($$divU_5);
+EXPORT_SYMBOL($$divU_6);
+EXPORT_SYMBOL($$divU_9);
+EXPORT_SYMBOL($$divU_10);
+EXPORT_SYMBOL($$divU_12);
+EXPORT_SYMBOL($$divU_7);
+EXPORT_SYMBOL($$divU_14);
+EXPORT_SYMBOL($$divU_15);
+EXPORT_SYMBOL($$divI_3);
+EXPORT_SYMBOL($$divI_5);
+EXPORT_SYMBOL($$divI_6);
+EXPORT_SYMBOL($$divI_7);
+EXPORT_SYMBOL($$divI_9);
+EXPORT_SYMBOL($$divI_10);
+EXPORT_SYMBOL($$divI_12);
+EXPORT_SYMBOL($$divI_14);
+EXPORT_SYMBOL($$divI_15);
+
+extern void __ashrdi3(void);
+extern void __ashldi3(void);
+extern void __lshrdi3(void);
+extern void __muldi3(void);
+
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__muldi3);
+
+asmlinkage void * __canonicalize_funcptr_for_compare(void *);
+EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);
+
+#ifdef __LP64__
+extern void __divdi3(void);
+extern void __udivdi3(void);
+extern void __umoddi3(void);
+extern void __moddi3(void);
+
+EXPORT_SYMBOL(__divdi3);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__moddi3);
+#endif
+
+#ifndef __LP64__
+extern void $$dyncall(void);
+EXPORT_SYMBOL($$dyncall);
+#endif
+
+#ifdef CONFIG_DISCONTIGMEM
+#include <asm/mmzone.h>
+EXPORT_SYMBOL(node_data);
+EXPORT_SYMBOL(pfnnid_map);
+#endif
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
new file mode 100644
index 000000000000..368cc095c99f
--- /dev/null
+++ b/arch/parisc/kernel/pci-dma.c
@@ -0,0 +1,578 @@
+/*
+** PARISC 1.1 Dynamic DMA mapping support.
+** This implementation is for PA-RISC platforms that do not support
+** I/O TLBs (aka DMA address translation hardware).
+** See Documentation/DMA-mapping.txt for interface definitions.
+**
+** (c) Copyright 1999,2000 Hewlett-Packard Company
+** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2000 Philipp Rumpf <prumpf@tux.org>
+** (c) Copyright 2000 John Marvin
+**
+** "leveraged" from 2.3.47: arch/ia64/kernel/pci-dma.c.
+** (I assume it's from David Mosberger-Tang but there was no Copyright)
+**
+** AFAIK, all PA7100LC and PA7300LC platforms can use this code.
+**
+** - ggg
+*/
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/cacheflush.h>
+#include <asm/dma.h> /* for DMA_CHUNK_SIZE */
+#include <asm/io.h>
+#include <asm/page.h> /* get_order */
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+
+
+static struct proc_dir_entry * proc_gsc_root = NULL;
+static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
+static unsigned long pcxl_used_bytes = 0;
+static unsigned long pcxl_used_pages = 0;
+
+extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */
+static spinlock_t pcxl_res_lock;
+static char *pcxl_res_map;
+static int pcxl_res_hint;
+static int pcxl_res_size;
+
+#ifdef DEBUG_PCXL_RESOURCE
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+
+/*
+** Dump a hex representation of the resource map.
+*/
+
+#ifdef DUMP_RESMAP
+static
+void dump_resmap(void)
+{
+ u_long *res_ptr = (unsigned long *)pcxl_res_map;
+ u_long i = 0;
+
+ printk("res_map: ");
+ for(; i < (pcxl_res_size / sizeof(unsigned long)); ++i, ++res_ptr)
+ printk("%08lx ", *res_ptr);
+
+ printk("\n");
+}
+#else
+static inline void dump_resmap(void) {;}
+#endif
+
+static int pa11_dma_supported( struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+static inline int map_pte_uncached(pte_t * pte,
+ unsigned long vaddr,
+ unsigned long size, unsigned long *paddr_ptr)
+{
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ vaddr &= ~PMD_MASK;
+ end = vaddr + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ if (!pte_none(*pte))
+ printk(KERN_ERR "map_pte_uncached: page already exists\n");
+ set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
+ purge_tlb_start();
+ pdtlb_kernel(orig_vaddr);
+ purge_tlb_end();
+ vaddr += PAGE_SIZE;
+ orig_vaddr += PAGE_SIZE;
+ (*paddr_ptr) += PAGE_SIZE;
+ pte++;
+ } while (vaddr < end);
+ return 0;
+}
+
+static inline int map_pmd_uncached(pmd_t * pmd, unsigned long vaddr,
+ unsigned long size, unsigned long *paddr_ptr)
+{
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ vaddr &= ~PGDIR_MASK;
+ end = vaddr + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ pte_t * pte = pte_alloc_kernel(&init_mm, pmd, vaddr);
+ if (!pte)
+ return -ENOMEM;
+ if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr))
+ return -ENOMEM;
+ vaddr = (vaddr + PMD_SIZE) & PMD_MASK;
+ orig_vaddr += PMD_SIZE;
+ pmd++;
+ } while (vaddr < end);
+ return 0;
+}
+
+static inline int map_uncached_pages(unsigned long vaddr, unsigned long size,
+ unsigned long paddr)
+{
+ pgd_t * dir;
+ unsigned long end = vaddr + size;
+
+ dir = pgd_offset_k(vaddr);
+ do {
+ pmd_t *pmd;
+
+ pmd = pmd_alloc(NULL, dir, vaddr);
+ if (!pmd)
+ return -ENOMEM;
+ if (map_pmd_uncached(pmd, vaddr, end - vaddr, &paddr))
+ return -ENOMEM;
+ vaddr = vaddr + PGDIR_SIZE;
+ dir++;
+ } while (vaddr && (vaddr < end));
+ return 0;
+}
+
+static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr,
+ unsigned long size)
+{
+ pte_t * pte;
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = pte_offset_map(pmd, vaddr);
+ vaddr &= ~PMD_MASK;
+ end = vaddr + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ pte_t page = *pte;
+ pte_clear(&init_mm, vaddr, pte);
+ purge_tlb_start();
+ pdtlb_kernel(orig_vaddr);
+ purge_tlb_end();
+ vaddr += PAGE_SIZE;
+ orig_vaddr += PAGE_SIZE;
+ pte++;
+ if (pte_none(page) || pte_present(page))
+ continue;
+ printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n");
+ } while (vaddr < end);
+}
+
+static inline void unmap_uncached_pmd(pgd_t * dir, unsigned long vaddr,
+ unsigned long size)
+{
+ pmd_t * pmd;
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ if (pgd_none(*dir))
+ return;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return;
+ }
+ pmd = pmd_offset(dir, vaddr);
+ vaddr &= ~PGDIR_MASK;
+ end = vaddr + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ unmap_uncached_pte(pmd, orig_vaddr, end - vaddr);
+ vaddr = (vaddr + PMD_SIZE) & PMD_MASK;
+ orig_vaddr += PMD_SIZE;
+ pmd++;
+ } while (vaddr < end);
+}
+
+static void unmap_uncached_pages(unsigned long vaddr, unsigned long size)
+{
+ pgd_t * dir;
+ unsigned long end = vaddr + size;
+
+ dir = pgd_offset_k(vaddr);
+ do {
+ unmap_uncached_pmd(dir, vaddr, end - vaddr);
+ vaddr = vaddr + PGDIR_SIZE;
+ dir++;
+ } while (vaddr && (vaddr < end));
+}
+
+#define PCXL_SEARCH_LOOP(idx, mask, size) \
+ for(; res_ptr < res_end; ++res_ptr) \
+ { \
+ if(0 == ((*res_ptr) & mask)) { \
+ *res_ptr |= mask; \
+ idx = (int)((u_long)res_ptr - (u_long)pcxl_res_map); \
+ pcxl_res_hint = idx + (size >> 3); \
+ goto resource_found; \
+ } \
+ }
+
+#define PCXL_FIND_FREE_MAPPING(idx, mask, size) { \
+ u##size *res_ptr = (u##size *)&(pcxl_res_map[pcxl_res_hint & ~((size >> 3) - 1)]); \
+ u##size *res_end = (u##size *)&pcxl_res_map[pcxl_res_size]; \
+ PCXL_SEARCH_LOOP(idx, mask, size); \
+ res_ptr = (u##size *)&pcxl_res_map[0]; \
+ PCXL_SEARCH_LOOP(idx, mask, size); \
+}
+
+unsigned long
+pcxl_alloc_range(size_t size)
+{
+ int res_idx;
+ u_long mask, flags;
+ unsigned int pages_needed = size >> PAGE_SHIFT;
+
+ mask = (u_long) -1L;
+ mask >>= BITS_PER_LONG - pages_needed;
+
+ DBG_RES("pcxl_alloc_range() size: %d pages_needed %d pages_mask 0x%08lx\n",
+ size, pages_needed, mask);
+
+ spin_lock_irqsave(&pcxl_res_lock, flags);
+
+ if(pages_needed <= 8) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 8);
+ } else if(pages_needed <= 16) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 16);
+ } else if(pages_needed <= 32) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 32);
+ } else {
+ panic("%s: pcxl_alloc_range() Too many pages to map.\n",
+ __FILE__);
+ }
+
+ dump_resmap();
+ panic("%s: pcxl_alloc_range() out of dma mapping resources\n",
+ __FILE__);
+
+resource_found:
+
+ DBG_RES("pcxl_alloc_range() res_idx %d mask 0x%08lx res_hint: %d\n",
+ res_idx, mask, pcxl_res_hint);
+
+ pcxl_used_pages += pages_needed;
+ pcxl_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1);
+
+ spin_unlock_irqrestore(&pcxl_res_lock, flags);
+
+ dump_resmap();
+
+ /*
+ ** return the corresponding vaddr in the pcxl dma map
+ */
+ return (pcxl_dma_start + (res_idx << (PAGE_SHIFT + 3)));
+}
+
+#define PCXL_FREE_MAPPINGS(idx, m, size) \
+ u##size *res_ptr = (u##size *)&(pcxl_res_map[(idx) + (((size >> 3) - 1) & (~((size >> 3) - 1)))]); \
+ /* BUG_ON((*res_ptr & m) != m); */ \
+ *res_ptr &= ~m;
+
+/*
+** clear bits in the pcxl resource map
+*/
+static void
+pcxl_free_range(unsigned long vaddr, size_t size)
+{
+ u_long mask, flags;
+ unsigned int res_idx = (vaddr - pcxl_dma_start) >> (PAGE_SHIFT + 3);
+ unsigned int pages_mapped = size >> PAGE_SHIFT;
+
+ mask = (u_long) -1L;
+ mask >>= BITS_PER_LONG - pages_mapped;
+
+ DBG_RES("pcxl_free_range() res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n",
+ res_idx, size, pages_mapped, mask);
+
+ spin_lock_irqsave(&pcxl_res_lock, flags);
+
+ if(pages_mapped <= 8) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 8);
+ } else if(pages_mapped <= 16) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 16);
+ } else if(pages_mapped <= 32) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 32);
+ } else {
+ panic("%s: pcxl_free_range() Too many pages to unmap.\n",
+ __FILE__);
+ }
+
+ pcxl_used_pages -= (pages_mapped ? pages_mapped : 1);
+ pcxl_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1);
+
+ spin_unlock_irqrestore(&pcxl_res_lock, flags);
+
+ dump_resmap();
+}
+
+static int __init
+pcxl_dma_init(void)
+{
+ if (pcxl_dma_start == 0)
+ return 0;
+
+ spin_lock_init(&pcxl_res_lock);
+ pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3);
+ pcxl_res_hint = 0;
+ pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
+ get_order(pcxl_res_size));
+ memset(pcxl_res_map, 0, pcxl_res_size);
+ proc_gsc_root = proc_mkdir("gsc", 0);
+ create_proc_info_entry("dino", 0, proc_gsc_root, pcxl_proc_info);
+ return 0;
+}
+
+__initcall(pcxl_dma_init);
+
+static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+{
+ unsigned long vaddr;
+ unsigned long paddr;
+ int order;
+
+ order = get_order(size);
+ size = 1 << (order + PAGE_SHIFT);
+ vaddr = pcxl_alloc_range(size);
+ paddr = __get_free_pages(flag, order);
+ flush_kernel_dcache_range(paddr, size);
+ paddr = __pa(paddr);
+ map_uncached_pages(vaddr, size, paddr);
+ *dma_handle = (dma_addr_t) paddr;
+
+#if 0
+/* This probably isn't needed to support EISA cards.
+** ISA cards will certainly only support 24-bit DMA addressing.
+** Not clear if we can, want, or need to support ISA.
+*/
+ if (!dev || *dev->coherent_dma_mask < 0xffffffff)
+ gfp |= GFP_DMA;
+#endif
+ return (void *)vaddr;
+}
+
+static void pa11_dma_free_consistent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ int order;
+
+ order = get_order(size);
+ size = 1 << (order + PAGE_SHIFT);
+ unmap_uncached_pages((unsigned long)vaddr, size);
+ pcxl_free_range((unsigned long)vaddr, size);
+ free_pages((unsigned long)__va(dma_handle), order);
+}
+
+static dma_addr_t pa11_dma_map_single(struct device *dev, void *addr, size_t size, enum dma_data_direction direction)
+{
+ if (direction == DMA_NONE) {
+ printk(KERN_ERR "pa11_dma_map_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
+ BUG();
+ }
+
+ flush_kernel_dcache_range((unsigned long) addr, size);
+ return virt_to_phys(addr);
+}
+
+static void pa11_dma_unmap_single(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
+{
+ if (direction == DMA_NONE) {
+ printk(KERN_ERR "pa11_dma_unmap_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
+ BUG();
+ }
+
+ if (direction == DMA_TO_DEVICE)
+ return;
+
+ /*
+ * For PCI_DMA_FROMDEVICE this flush is not necessary for the
+ * simple map/unmap case. However, it IS necessary if if
+ * pci_dma_sync_single_* has been called and the buffer reused.
+ */
+
+ flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size);
+ return;
+}
+
+static int pa11_dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
+{
+ int i;
+
+ if (direction == DMA_NONE)
+ BUG();
+
+ for (i = 0; i < nents; i++, sglist++ ) {
+ unsigned long vaddr = sg_virt_addr(sglist);
+ sg_dma_address(sglist) = (dma_addr_t) virt_to_phys(vaddr);
+ sg_dma_len(sglist) = sglist->length;
+ flush_kernel_dcache_range(vaddr, sglist->length);
+ }
+ return nents;
+}
+
+static void pa11_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
+{
+ int i;
+
+ if (direction == DMA_NONE)
+ BUG();
+
+ if (direction == DMA_TO_DEVICE)
+ return;
+
+ /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
+
+ for (i = 0; i < nents; i++, sglist++ )
+ flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
+ return;
+}
+
+static void pa11_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ if (direction == DMA_NONE)
+ BUG();
+
+ flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size);
+}
+
+static void pa11_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ if (direction == DMA_NONE)
+ BUG();
+
+ flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size);
+}
+
+static void pa11_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
+{
+ int i;
+
+ /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
+
+ for (i = 0; i < nents; i++, sglist++ )
+ flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
+}
+
+static void pa11_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
+{
+ int i;
+
+ /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
+
+ for (i = 0; i < nents; i++, sglist++ )
+ flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
+}
+
+struct hppa_dma_ops pcxl_dma_ops = {
+ .dma_supported = pa11_dma_supported,
+ .alloc_consistent = pa11_dma_alloc_consistent,
+ .alloc_noncoherent = pa11_dma_alloc_consistent,
+ .free_consistent = pa11_dma_free_consistent,
+ .map_single = pa11_dma_map_single,
+ .unmap_single = pa11_dma_unmap_single,
+ .map_sg = pa11_dma_map_sg,
+ .unmap_sg = pa11_dma_unmap_sg,
+ .dma_sync_single_for_cpu = pa11_dma_sync_single_for_cpu,
+ .dma_sync_single_for_device = pa11_dma_sync_single_for_device,
+ .dma_sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu,
+ .dma_sync_sg_for_device = pa11_dma_sync_sg_for_device,
+};
+
+static void *fail_alloc_consistent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, int flag)
+{
+ return NULL;
+}
+
+static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, int flag)
+{
+ void *addr = NULL;
+
+ /* rely on kmalloc to be cacheline aligned */
+ addr = kmalloc(size, flag);
+ if(addr)
+ *dma_handle = (dma_addr_t)virt_to_phys(addr);
+
+ return addr;
+}
+
+static void pa11_dma_free_noncoherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t iova)
+{
+ kfree(vaddr);
+ return;
+}
+
+struct hppa_dma_ops pcx_dma_ops = {
+ .dma_supported = pa11_dma_supported,
+ .alloc_consistent = fail_alloc_consistent,
+ .alloc_noncoherent = pa11_dma_alloc_noncoherent,
+ .free_consistent = pa11_dma_free_noncoherent,
+ .map_single = pa11_dma_map_single,
+ .unmap_single = pa11_dma_unmap_single,
+ .map_sg = pa11_dma_map_sg,
+ .unmap_sg = pa11_dma_unmap_sg,
+ .dma_sync_single_for_cpu = pa11_dma_sync_single_for_cpu,
+ .dma_sync_single_for_device = pa11_dma_sync_single_for_device,
+ .dma_sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu,
+ .dma_sync_sg_for_device = pa11_dma_sync_sg_for_device,
+};
+
+
+static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
+{
+ u_long i = 0;
+ unsigned long *res_ptr = (u_long *)pcxl_res_map;
+ unsigned long total_pages = pcxl_res_size << 3; /* 8 bits per byte */
+
+ sprintf(buf, "\nDMA Mapping Area size : %d bytes (%d pages)\n",
+ PCXL_DMA_MAP_SIZE,
+ (pcxl_res_size << 3) ); /* 1 bit per page */
+
+ sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
+ buf, pcxl_res_size, pcxl_res_size << 3); /* 8 bits per byte */
+
+ strcat(buf, " total: free: used: % used:\n");
+ sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size,
+ pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes,
+ (pcxl_used_bytes * 100) / pcxl_res_size);
+
+ sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
+ total_pages - pcxl_used_pages, pcxl_used_pages,
+ (pcxl_used_pages * 100 / total_pages));
+
+ strcat(buf, "\nResource bitmap:");
+
+ for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
+ if ((i & 7) == 0)
+ strcat(buf,"\n ");
+ sprintf(buf, "%s %08lx", buf, *res_ptr);
+ }
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
new file mode 100644
index 000000000000..3cb08a4a513a
--- /dev/null
+++ b/arch/parisc/kernel/pci.c
@@ -0,0 +1,346 @@
+/* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997, 1998 Ralf Baechle
+ * Copyright (C) 1999 SuSE GmbH
+ * Copyright (C) 1999-2001 Hewlett-Packard Company
+ * Copyright (C) 1999-2001 Grant Grundler
+ */
+#include <linux/config.h>
+#include <linux/eisa.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/cache.h> /* for L1_CACHE_BYTES */
+#include <asm/superio.h>
+
+#define DEBUG_RESOURCES 0
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
+# define DBGC(x...) printk(KERN_DEBUG x)
+#else
+# define DBGC(x...)
+#endif
+
+
+#if DEBUG_RESOURCES
+#define DBG_RES(x...) printk(KERN_DEBUG x)
+#else
+#define DBG_RES(x...)
+#endif
+
+/* To be used as: mdelay(pci_post_reset_delay);
+ *
+ * post_reset is the time the kernel should stall to prevent anyone from
+ * accessing the PCI bus once #RESET is de-asserted.
+ * PCI spec somewhere says 1 second but with multi-PCI bus systems,
+ * this makes the boot time much longer than necessary.
+ * 20ms seems to work for all the HP PCI implementations to date.
+ *
+ * XXX: turn into a #defined constant in <asm/pci.h> ?
+ */
+int pci_post_reset_delay = 50;
+
+struct pci_port_ops *pci_port;
+struct pci_bios_ops *pci_bios;
+
+int pci_hba_count = 0;
+
+/* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. */
+#define PCI_HBA_MAX 32
+struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX];
+
+
+/********************************************************************
+**
+** I/O port space support
+**
+*********************************************************************/
+
+/* EISA port numbers and PCI port numbers share the same interface. Some
+ * machines have both EISA and PCI adapters installed. Rather than turn
+ * pci_port into an array, we reserve bus 0 for EISA and call the EISA
+ * routines if the access is to a port on bus 0. We don't want to fix
+ * EISA and ISA drivers which assume port space is <= 0xffff.
+ */
+
+#ifdef CONFIG_EISA
+#define EISA_IN(size) if (EISA_bus && (b == 0)) return eisa_in##size(addr)
+#define EISA_OUT(size) if (EISA_bus && (b == 0)) return eisa_out##size(d, addr)
+#else
+#define EISA_IN(size)
+#define EISA_OUT(size)
+#endif
+
+#define PCI_PORT_IN(type, size) \
+u##size in##type (int addr) \
+{ \
+ int b = PCI_PORT_HBA(addr); \
+ EISA_IN(size); \
+ if (!parisc_pci_hba[b]) return (u##size) -1; \
+ return pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \
+} \
+EXPORT_SYMBOL(in##type);
+
+PCI_PORT_IN(b, 8)
+PCI_PORT_IN(w, 16)
+PCI_PORT_IN(l, 32)
+
+
+#define PCI_PORT_OUT(type, size) \
+void out##type (u##size d, int addr) \
+{ \
+ int b = PCI_PORT_HBA(addr); \
+ EISA_OUT(size); \
+ if (!parisc_pci_hba[b]) return; \
+ pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \
+} \
+EXPORT_SYMBOL(out##type);
+
+PCI_PORT_OUT(b, 8)
+PCI_PORT_OUT(w, 16)
+PCI_PORT_OUT(l, 32)
+
+
+
+/*
+ * BIOS32 replacement.
+ */
+static int __init pcibios_init(void)
+{
+ if (!pci_bios)
+ return -1;
+
+ if (pci_bios->init) {
+ pci_bios->init();
+ } else {
+ printk(KERN_WARNING "pci_bios != NULL but init() is!\n");
+ }
+ return 0;
+}
+
+
+/* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */
+void pcibios_fixup_bus(struct pci_bus *bus)
+{
+ if (pci_bios->fixup_bus) {
+ pci_bios->fixup_bus(bus);
+ } else {
+ printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n");
+ }
+}
+
+
+char *pcibios_setup(char *str)
+{
+ return str;
+}
+
+/*
+ * Called by pci_set_master() - a driver interface.
+ *
+ * Legacy PDC guarantees to set:
+ * Map Memory BAR's into PA IO space.
+ * Map Expansion ROM BAR into one common PA IO space per bus.
+ * Map IO BAR's into PCI IO space.
+ * Command (see below)
+ * Cache Line Size
+ * Latency Timer
+ * Interrupt Line
+ * PPB: secondary latency timer, io/mmio base/limit,
+ * bus numbers, bridge control
+ *
+ */
+void pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+
+ /* If someone already mucked with this, don't touch it. */
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat >= 16) return;
+
+ /*
+ ** HP generally has fewer devices on the bus than other architectures.
+ ** upper byte is PCI_LATENCY_TIMER.
+ */
+ pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
+ (0x80 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
+}
+
+
+void __init pcibios_init_bus(struct pci_bus *bus)
+{
+ struct pci_dev *dev = bus->self;
+ unsigned short bridge_ctl;
+
+ /* We deal only with pci controllers and pci-pci bridges. */
+ if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ return;
+
+ /* PCI-PCI bridge - set the cache line and default latency
+ (32) for primary and secondary buses. */
+ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32);
+
+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl);
+ bridge_ctl |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl);
+}
+
+
+/* KLUGE: Link the child and parent resources - generic PCI didn't */
+static void
+pcibios_link_hba_resources( struct resource *hba_res, struct resource *r)
+{
+ if (!r->parent) {
+ printk(KERN_EMERG "PCI: Tell willy he's wrong\n");
+ r->parent = hba_res;
+
+ /* reverse link is harder *sigh* */
+ if (r->parent->child) {
+ if (r->parent->sibling) {
+ struct resource *next = r->parent->sibling;
+ while (next->sibling)
+ next = next->sibling;
+ next->sibling = r;
+ } else {
+ r->parent->sibling = r;
+ }
+ } else
+ r->parent->child = r;
+ }
+}
+
+/* called by drivers/pci/setup-bus.c:pci_setup_bridge(). */
+void __devinit pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region, struct resource *res)
+{
+ struct pci_bus *bus = dev->bus;
+ struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data);
+
+ if (res->flags & IORESOURCE_IO) {
+ /*
+ ** I/O space may see busnumbers here. Something
+ ** in the form of 0xbbxxxx where bb is the bus num
+ ** and xxxx is the I/O port space address.
+ ** Remaining address translation are done in the
+ ** PCI Host adapter specific code - ie dino_out8.
+ */
+ region->start = PCI_PORT_ADDR(res->start);
+ region->end = PCI_PORT_ADDR(res->end);
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* Convert MMIO addr to PCI addr (undo global virtualization) */
+ region->start = PCI_BUS_ADDR(hba, res->start);
+ region->end = PCI_BUS_ADDR(hba, res->end);
+ }
+
+ DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n",
+ bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM",
+ region->start, region->end);
+
+ /* KLUGE ALERT
+ ** if this resource isn't linked to a "parent", then it seems
+ ** to be a child of the HBA - lets link it in.
+ */
+ pcibios_link_hba_resources(&hba->io_space, bus->resource[0]);
+ pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]);
+}
+
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
+/*
+ * pcibios align resources() is called every time generic PCI code
+ * wants to generate a new address. The process of looking for
+ * an available address, each candidate is first "aligned" and
+ * then checked if the resource is available until a match is found.
+ *
+ * Since we are just checking candidates, don't use any fields other
+ * than res->start.
+ */
+void pcibios_align_resource(void *data, struct resource *res,
+ unsigned long size, unsigned long alignment)
+{
+ unsigned long mask, align;
+
+ DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n",
+ pci_name(((struct pci_dev *) data)),
+ res->parent, res->start, res->end,
+ (int) res->flags, size, alignment);
+
+ /* If it's not IO, then it's gotta be MEM */
+ align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+
+ /* Align to largest of MIN or input size */
+ mask = max(alignment, align) - 1;
+ res->start += mask;
+ res->start &= ~mask;
+
+ /* The caller updates the end field, we don't. */
+}
+
+
+/*
+ * A driver is enabling the device. We make sure that all the appropriate
+ * bits are set to allow the device to operate as the driver is expecting.
+ * We enable the port IO and memory IO bits if the device has any BARs of
+ * that type, and we enable the PERR and SERR bits unconditionally.
+ * Drivers that do not need parity (eg graphics and possibly networking)
+ * can clear these bits if they want.
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ u16 cmd;
+ int idx;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+ for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
+ struct resource *r = &dev->resource[idx];
+
+ /* only setup requested resources */
+ if (!(mask & (1<<idx)))
+ continue;
+
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+
+ cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+
+#if 0
+ /* If bridge/bus controller has FBB enabled, child must too. */
+ if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
+ cmd |= PCI_COMMAND_FAST_BACK;
+#endif
+ DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", pci_name(dev), cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ return 0;
+}
+
+
+/* PA-RISC specific */
+void pcibios_register_hba(struct pci_hba_data *hba)
+{
+ if (pci_hba_count >= PCI_HBA_MAX) {
+ printk(KERN_ERR "PCI: Too many Host Bus Adapters\n");
+ return;
+ }
+
+ parisc_pci_hba[pci_hba_count] = hba;
+ hba->hba_num = pci_hba_count++;
+}
+
+subsys_initcall(pcibios_init);
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
new file mode 100644
index 000000000000..52004ae28d20
--- /dev/null
+++ b/arch/parisc/kernel/pdc_chassis.c
@@ -0,0 +1,245 @@
+/*
+ * interfaces to log Chassis Codes via PDC (firmware)
+ *
+ * Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
+ * Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#undef PDC_CHASSIS_DEBUG
+#ifdef PDC_CHASSIS_DEBUG
+#define DPRINTK(fmt, args...) printk(fmt, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/notifier.h>
+
+#include <asm/pdc_chassis.h>
+#include <asm/processor.h>
+#include <asm/pdc.h>
+#include <asm/pdcpat.h>
+
+
+#ifdef CONFIG_PDC_CHASSIS
+static int pdc_chassis_old = 0;
+static unsigned int pdc_chassis_enabled = 1;
+
+
+/**
+ * pdc_chassis_setup() - Enable/disable pdc_chassis code at boot time.
+ * @str configuration param: 0 to disable chassis log
+ * @return 1
+ */
+
+static int __init pdc_chassis_setup(char *str)
+{
+ /*panic_timeout = simple_strtoul(str, NULL, 0);*/
+ get_option(&str, &pdc_chassis_enabled);
+ return 1;
+}
+__setup("pdcchassis=", pdc_chassis_setup);
+
+
+/**
+ * pdc_chassis_checkold() - Checks for old PDC_CHASSIS compatibility
+ * @pdc_chassis_old: 1 if old pdc chassis style
+ *
+ * Currently, only E class and A180 are known to work with this.
+ * Inspired by Christoph Plattner
+ */
+
+static void __init pdc_chassis_checkold(void)
+{
+ switch(CPU_HVERSION) {
+ case 0x480: /* E25 */
+ case 0x481: /* E35 */
+ case 0x482: /* E45 */
+ case 0x483: /* E55 */
+ case 0x516: /* A180 */
+ pdc_chassis_old = 1;
+ break;
+
+ default:
+ break;
+ }
+ DPRINTK(KERN_DEBUG "%s: pdc_chassis_checkold(); pdc_chassis_old = %d\n", __FILE__, pdc_chassis_old);
+}
+
+
+/**
+ * pdc_chassis_panic_event() - Called by the panic handler.
+ *
+ * As soon as a panic occurs, we should inform the PDC.
+ */
+
+static int pdc_chassis_panic_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
+ return NOTIFY_DONE;
+}
+
+
+static struct notifier_block pdc_chassis_panic_block = {
+ .notifier_call = pdc_chassis_panic_event,
+ .priority = INT_MAX,
+};
+
+
+/**
+ * parisc_reboot_event() - Called by the reboot handler.
+ *
+ * As soon as a reboot occurs, we should inform the PDC.
+ */
+
+static int pdc_chassis_reboot_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
+ return NOTIFY_DONE;
+}
+
+
+static struct notifier_block pdc_chassis_reboot_block = {
+ .notifier_call = pdc_chassis_reboot_event,
+ .priority = INT_MAX,
+};
+#endif /* CONFIG_PDC_CHASSIS */
+
+
+/**
+ * parisc_pdc_chassis_init() - Called at boot time.
+ */
+
+void __init parisc_pdc_chassis_init(void)
+{
+#ifdef CONFIG_PDC_CHASSIS
+ int handle = 0;
+ if (pdc_chassis_enabled) {
+ DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__);
+
+ /* Let see if we have something to handle... */
+ /* Check for PDC_PAT or old LED Panel */
+ pdc_chassis_checkold();
+ if (is_pdc_pat()) {
+ printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n");
+ handle = 1;
+ }
+ else if (pdc_chassis_old) {
+ printk(KERN_INFO "Enabling old style chassis LED panel support.\n");
+ handle = 1;
+ }
+
+ if (handle) {
+ /* initialize panic notifier chain */
+ notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block);
+
+ /* initialize reboot notifier chain */
+ register_reboot_notifier(&pdc_chassis_reboot_block);
+ }
+ }
+#endif /* CONFIG_PDC_CHASSIS */
+}
+
+
+/**
+ * pdc_chassis_send_status() - Sends a predefined message to the chassis,
+ * and changes the front panel LEDs according to the new system state
+ * @retval: PDC call return value.
+ *
+ * Only machines with 64 bits PDC PAT and those reported in
+ * pdc_chassis_checkold() are supported atm.
+ *
+ * returns 0 if no error, -1 if no supported PDC is present or invalid message,
+ * else returns the appropriate PDC error code.
+ *
+ * For a list of predefined messages, see asm-parisc/pdc_chassis.h
+ */
+
+int pdc_chassis_send_status(int message)
+{
+ /* Maybe we should do that in an other way ? */
+ int retval = 0;
+#ifdef CONFIG_PDC_CHASSIS
+ if (pdc_chassis_enabled) {
+
+ DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message);
+
+#ifdef CONFIG_64BIT
+ if (is_pdc_pat()) {
+ switch(message) {
+ case PDC_CHASSIS_DIRECT_BSTART:
+ retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_BSTART, PDC_CHASSIS_LSTATE_RUN_NORMAL);
+ break;
+
+ case PDC_CHASSIS_DIRECT_BCOMPLETE:
+ retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_BCOMPLETE, PDC_CHASSIS_LSTATE_RUN_NORMAL);
+ break;
+
+ case PDC_CHASSIS_DIRECT_SHUTDOWN:
+ retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_SHUTDOWN, PDC_CHASSIS_LSTATE_NONOS);
+ break;
+
+ case PDC_CHASSIS_DIRECT_PANIC:
+ retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_PANIC, PDC_CHASSIS_LSTATE_RUN_CRASHREC);
+ break;
+
+ case PDC_CHASSIS_DIRECT_LPMC:
+ retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_LPMC, PDC_CHASSIS_LSTATE_RUN_SYSINT);
+ break;
+
+ case PDC_CHASSIS_DIRECT_HPMC:
+ retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_HPMC, PDC_CHASSIS_LSTATE_RUN_NCRIT);
+ break;
+
+ default:
+ retval = -1;
+ }
+ } else retval = -1;
+#else
+ if (pdc_chassis_old) {
+ switch (message) {
+ case PDC_CHASSIS_DIRECT_BSTART:
+ case PDC_CHASSIS_DIRECT_BCOMPLETE:
+ retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_RUN));
+ break;
+
+ case PDC_CHASSIS_DIRECT_SHUTDOWN:
+ retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_SHUT));
+ break;
+
+ case PDC_CHASSIS_DIRECT_HPMC:
+ case PDC_CHASSIS_DIRECT_PANIC:
+ retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_FLT));
+ break;
+
+ case PDC_CHASSIS_DIRECT_LPMC:
+ retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_WARN));
+ break;
+
+ default:
+ retval = -1;
+ }
+ } else retval = -1;
+#endif /* CONFIG_64BIT */
+ } /* if (pdc_chassis_enabled) */
+#endif /* CONFIG_PDC_CHASSIS */
+ return retval;
+}
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
new file mode 100644
index 000000000000..01f676d1673b
--- /dev/null
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -0,0 +1,189 @@
+/*
+ * PDC Console support - ie use firmware to dump text via boot console
+ *
+ * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
+ * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
+ * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
+ * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
+ * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
+ * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
+ * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
+ * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
+ * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
+ * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
+ * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * The PDC console is a simple console, which can be used for debugging
+ * boot related problems on HP PA-RISC machines.
+ *
+ * This code uses the ROM (=PDC) based functions to read and write characters
+ * from and to PDC's boot path.
+ * Since all character read from that path must be polled, this code never
+ * can or will be a fully functional linux console.
+ */
+
+/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems.
+ * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
+#undef EARLY_BOOTUP_DEBUG
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/major.h>
+#include <linux/tty.h>
+#include <asm/page.h>
+#include <asm/types.h>
+#include <asm/system.h>
+#include <asm/pdc.h> /* for iodc_call() proto and friends */
+
+
+static void pdc_console_write(struct console *co, const char *s, unsigned count)
+{
+ while(count--)
+ pdc_iodc_putc(*s++);
+}
+
+void pdc_outc(unsigned char c)
+{
+ pdc_iodc_outc(c);
+}
+
+void pdc_printf(const char *fmt, ...)
+{
+ va_list args;
+ char buf[1024];
+ int i, len;
+
+ va_start(args, fmt);
+ len = vscnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for (i = 0; i < len; i++)
+ pdc_iodc_outc(buf[i]);
+}
+
+int pdc_console_poll_key(struct console *co)
+{
+ return pdc_iodc_getc();
+}
+
+static int pdc_console_setup(struct console *co, char *options)
+{
+ return 0;
+}
+
+#if defined(CONFIG_PDC_CONSOLE)
+#define PDC_CONSOLE_DEVICE pdc_console_device
+static struct tty_driver * pdc_console_device (struct console *c, int *index)
+{
+ extern struct tty_driver console_driver;
+ *index = c->index ? c->index-1 : fg_console;
+ return &console_driver;
+}
+#else
+#define PDC_CONSOLE_DEVICE NULL
+#endif
+
+static struct console pdc_cons = {
+ .name = "ttyB",
+ .write = pdc_console_write,
+ .device = PDC_CONSOLE_DEVICE,
+ .setup = pdc_console_setup,
+ .flags = CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
+ .index = -1,
+};
+
+static int pdc_console_initialized;
+extern unsigned long con_start; /* kernel/printk.c */
+extern unsigned long log_end; /* kernel/printk.c */
+
+
+static void pdc_console_init_force(void)
+{
+ if (pdc_console_initialized)
+ return;
+ ++pdc_console_initialized;
+
+ /* If the console is duplex then copy the COUT parameters to CIN. */
+ if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
+ memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
+
+ /* register the pdc console */
+ register_console(&pdc_cons);
+}
+
+void __init pdc_console_init(void)
+{
+#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE)
+ pdc_console_init_force();
+#endif
+#ifdef EARLY_BOOTUP_DEBUG
+ printk(KERN_INFO "Initialized PDC Console for debugging.\n");
+#endif
+}
+
+
+/* Unregister the pdc console with the printk console layer */
+void pdc_console_die(void)
+{
+ if (!pdc_console_initialized)
+ return;
+ --pdc_console_initialized;
+
+ printk(KERN_INFO "Switching from PDC console\n");
+
+ /* Don't repeat what we've already printed */
+ con_start = log_end;
+
+ unregister_console(&pdc_cons);
+}
+
+
+/*
+ * Used for emergencies. Currently only used if an HPMC occurs. If an
+ * HPMC occurs, it is possible that the current console may not be
+ * properly initialed after the PDC IO reset. This routine unregisters all
+ * of the current consoles, reinitializes the pdc console and
+ * registers it.
+ */
+
+void pdc_console_restart(void)
+{
+ struct console *console;
+
+ if (pdc_console_initialized)
+ return;
+
+ while ((console = console_drivers) != NULL)
+ unregister_console(console_drivers);
+
+ /* Don't repeat what we've already printed */
+ con_start = log_end;
+
+ /* force registering the pdc console */
+ pdc_console_init_force();
+}
+
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
new file mode 100644
index 000000000000..b3ad0a505b87
--- /dev/null
+++ b/arch/parisc/kernel/perf.c
@@ -0,0 +1,841 @@
+/*
+ * Parisc performance counters
+ * Copyright (C) 2001 Randolph Chung <tausq@debian.org>
+ *
+ * This code is derived, with permission, from HP/UX sources.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Edited comment from original sources:
+ *
+ * This driver programs the PCX-U/PCX-W performance counters
+ * on the PA-RISC 2.0 chips. The driver keeps all images now
+ * internally to the kernel to hopefully eliminate the possiblity
+ * of a bad image halting the CPU. Also, there are different
+ * images for the PCX-W and later chips vs the PCX-U chips.
+ *
+ * Only 1 process is allowed to access the driver at any time,
+ * so the only protection that is needed is at open and close.
+ * A variable "perf_enabled" is used to hold the state of the
+ * driver. The spinlock "perf_lock" is used to protect the
+ * modification of the state during open/close operations so
+ * multiple processes don't get into the driver simultaneously.
+ *
+ * This driver accesses the processor directly vs going through
+ * the PDC INTRIGUE calls. This is done to eliminate bugs introduced
+ * in various PDC revisions. The code is much more maintainable
+ * and reliable this way vs having to debug on every version of PDC
+ * on every box.
+ */
+
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+
+#include <asm/uaccess.h>
+#include <asm/perf.h>
+#include <asm/parisc-device.h>
+#include <asm/processor.h>
+#include <asm/runway.h>
+#include <asm/io.h> /* for __raw_read() */
+
+#include "perf_images.h"
+
+#define MAX_RDR_WORDS 24
+#define PERF_VERSION 2 /* derived from hpux's PI v2 interface */
+
+/* definition of RDR regs */
+struct rdr_tbl_ent {
+ uint16_t width;
+ uint8_t num_words;
+ uint8_t write_control;
+};
+
+static int perf_processor_interface = UNKNOWN_INTF;
+static int perf_enabled = 0;
+static spinlock_t perf_lock;
+struct parisc_device *cpu_device = NULL;
+
+/* RDRs to write for PCX-W */
+static int perf_rdrs_W[] =
+ { 0, 1, 4, 5, 6, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
+
+/* RDRs to write for PCX-U */
+static int perf_rdrs_U[] =
+ { 0, 1, 4, 5, 6, 7, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
+
+/* RDR register descriptions for PCX-W */
+static struct rdr_tbl_ent perf_rdr_tbl_W[] = {
+ { 19, 1, 8 }, /* RDR 0 */
+ { 16, 1, 16 }, /* RDR 1 */
+ { 72, 2, 0 }, /* RDR 2 */
+ { 81, 2, 0 }, /* RDR 3 */
+ { 328, 6, 0 }, /* RDR 4 */
+ { 160, 3, 0 }, /* RDR 5 */
+ { 336, 6, 0 }, /* RDR 6 */
+ { 164, 3, 0 }, /* RDR 7 */
+ { 0, 0, 0 }, /* RDR 8 */
+ { 35, 1, 0 }, /* RDR 9 */
+ { 6, 1, 0 }, /* RDR 10 */
+ { 18, 1, 0 }, /* RDR 11 */
+ { 13, 1, 0 }, /* RDR 12 */
+ { 8, 1, 0 }, /* RDR 13 */
+ { 8, 1, 0 }, /* RDR 14 */
+ { 8, 1, 0 }, /* RDR 15 */
+ { 1530, 24, 0 }, /* RDR 16 */
+ { 16, 1, 0 }, /* RDR 17 */
+ { 4, 1, 0 }, /* RDR 18 */
+ { 0, 0, 0 }, /* RDR 19 */
+ { 152, 3, 24 }, /* RDR 20 */
+ { 152, 3, 24 }, /* RDR 21 */
+ { 233, 4, 48 }, /* RDR 22 */
+ { 233, 4, 48 }, /* RDR 23 */
+ { 71, 2, 0 }, /* RDR 24 */
+ { 71, 2, 0 }, /* RDR 25 */
+ { 11, 1, 0 }, /* RDR 26 */
+ { 18, 1, 0 }, /* RDR 27 */
+ { 128, 2, 0 }, /* RDR 28 */
+ { 0, 0, 0 }, /* RDR 29 */
+ { 16, 1, 0 }, /* RDR 30 */
+ { 16, 1, 0 }, /* RDR 31 */
+};
+
+/* RDR register descriptions for PCX-U */
+static struct rdr_tbl_ent perf_rdr_tbl_U[] = {
+ { 19, 1, 8 }, /* RDR 0 */
+ { 32, 1, 16 }, /* RDR 1 */
+ { 20, 1, 0 }, /* RDR 2 */
+ { 0, 0, 0 }, /* RDR 3 */
+ { 344, 6, 0 }, /* RDR 4 */
+ { 176, 3, 0 }, /* RDR 5 */
+ { 336, 6, 0 }, /* RDR 6 */
+ { 0, 0, 0 }, /* RDR 7 */
+ { 0, 0, 0 }, /* RDR 8 */
+ { 0, 0, 0 }, /* RDR 9 */
+ { 28, 1, 0 }, /* RDR 10 */
+ { 33, 1, 0 }, /* RDR 11 */
+ { 0, 0, 0 }, /* RDR 12 */
+ { 230, 4, 0 }, /* RDR 13 */
+ { 32, 1, 0 }, /* RDR 14 */
+ { 128, 2, 0 }, /* RDR 15 */
+ { 1494, 24, 0 }, /* RDR 16 */
+ { 18, 1, 0 }, /* RDR 17 */
+ { 4, 1, 0 }, /* RDR 18 */
+ { 0, 0, 0 }, /* RDR 19 */
+ { 158, 3, 24 }, /* RDR 20 */
+ { 158, 3, 24 }, /* RDR 21 */
+ { 194, 4, 48 }, /* RDR 22 */
+ { 194, 4, 48 }, /* RDR 23 */
+ { 71, 2, 0 }, /* RDR 24 */
+ { 71, 2, 0 }, /* RDR 25 */
+ { 28, 1, 0 }, /* RDR 26 */
+ { 33, 1, 0 }, /* RDR 27 */
+ { 88, 2, 0 }, /* RDR 28 */
+ { 32, 1, 0 }, /* RDR 29 */
+ { 24, 1, 0 }, /* RDR 30 */
+ { 16, 1, 0 }, /* RDR 31 */
+};
+
+/*
+ * A non-zero write_control in the above tables is a byte offset into
+ * this array.
+ */
+static uint64_t perf_bitmasks[] = {
+ 0x0000000000000000ul, /* first dbl word must be zero */
+ 0xfdffe00000000000ul, /* RDR0 bitmask */
+ 0x003f000000000000ul, /* RDR1 bitmask */
+ 0x00fffffffffffffful, /* RDR20-RDR21 bitmask (152 bits) */
+ 0xfffffffffffffffful,
+ 0xfffffffc00000000ul,
+ 0xfffffffffffffffful, /* RDR22-RDR23 bitmask (233 bits) */
+ 0xfffffffffffffffful,
+ 0xfffffffffffffffcul,
+ 0xff00000000000000ul
+};
+
+/*
+ * Write control bitmasks for Pa-8700 processor given
+ * somethings have changed slightly.
+ */
+static uint64_t perf_bitmasks_piranha[] = {
+ 0x0000000000000000ul, /* first dbl word must be zero */
+ 0xfdffe00000000000ul, /* RDR0 bitmask */
+ 0x003f000000000000ul, /* RDR1 bitmask */
+ 0x00fffffffffffffful, /* RDR20-RDR21 bitmask (158 bits) */
+ 0xfffffffffffffffful,
+ 0xfffffffc00000000ul,
+ 0xfffffffffffffffful, /* RDR22-RDR23 bitmask (210 bits) */
+ 0xfffffffffffffffful,
+ 0xfffffffffffffffful,
+ 0xfffc000000000000ul
+};
+
+static uint64_t *bitmask_array; /* array of bitmasks to use */
+
+/******************************************************************************
+ * Function Prototypes
+ *****************************************************************************/
+static int perf_config(uint32_t *image_ptr);
+static int perf_release(struct inode *inode, struct file *file);
+static int perf_open(struct inode *inode, struct file *file);
+static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos);
+static ssize_t perf_write(struct file *file, const char __user *buf, size_t count,
+ loff_t *ppos);
+static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg);
+static void perf_start_counters(void);
+static int perf_stop_counters(uint32_t *raddr);
+static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num);
+static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer);
+static int perf_rdr_clear(uint32_t rdr_num);
+static int perf_write_image(uint64_t *memaddr);
+static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer);
+
+/* External Assembly Routines */
+extern uint64_t perf_rdr_shift_in_W (uint32_t rdr_num, uint16_t width);
+extern uint64_t perf_rdr_shift_in_U (uint32_t rdr_num, uint16_t width);
+extern void perf_rdr_shift_out_W (uint32_t rdr_num, uint64_t buffer);
+extern void perf_rdr_shift_out_U (uint32_t rdr_num, uint64_t buffer);
+extern void perf_intrigue_enable_perf_counters (void);
+extern void perf_intrigue_disable_perf_counters (void);
+
+/******************************************************************************
+ * Function Definitions
+ *****************************************************************************/
+
+
+/*
+ * configure:
+ *
+ * Configure the cpu with a given data image. First turn off the counters,
+ * then download the image, then turn the counters back on.
+ */
+static int perf_config(uint32_t *image_ptr)
+{
+ long error;
+ uint32_t raddr[4];
+
+ /* Stop the counters*/
+ error = perf_stop_counters(raddr);
+ if (error != 0) {
+ printk("perf_config: perf_stop_counters = %ld\n", error);
+ return -EINVAL;
+ }
+
+printk("Preparing to write image\n");
+ /* Write the image to the chip */
+ error = perf_write_image((uint64_t *)image_ptr);
+ if (error != 0) {
+ printk("perf_config: DOWNLOAD = %ld\n", error);
+ return -EINVAL;
+ }
+
+printk("Preparing to start counters\n");
+
+ /* Start the counters */
+ perf_start_counters();
+
+ return sizeof(uint32_t);
+}
+
+/*
+ * Open the device and initialize all of its memory. The device is only
+ * opened once, but can be "queried" by multiple processes that know its
+ * file descriptor.
+ */
+static int perf_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&perf_lock);
+ if (perf_enabled) {
+ spin_unlock(&perf_lock);
+ return -EBUSY;
+ }
+ perf_enabled = 1;
+ spin_unlock(&perf_lock);
+
+ return 0;
+}
+
+/*
+ * Close the device.
+ */
+static int perf_release(struct inode *inode, struct file *file)
+{
+ spin_lock(&perf_lock);
+ perf_enabled = 0;
+ spin_unlock(&perf_lock);
+
+ return 0;
+}
+
+/*
+ * Read does nothing for this driver
+ */
+static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos)
+{
+ return 0;
+}
+
+/*
+ * write:
+ *
+ * This routine downloads the image to the chip. It must be
+ * called on the processor that the download should happen
+ * on.
+ */
+static ssize_t perf_write(struct file *file, const char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ int err;
+ size_t image_size;
+ uint32_t image_type;
+ uint32_t interface_type;
+ uint32_t test;
+
+ if (perf_processor_interface == ONYX_INTF)
+ image_size = PCXU_IMAGE_SIZE;
+ else if (perf_processor_interface == CUDA_INTF)
+ image_size = PCXW_IMAGE_SIZE;
+ else
+ return -EFAULT;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (count != sizeof(uint32_t))
+ return -EIO;
+
+ if ((err = copy_from_user(&image_type, buf, sizeof(uint32_t))) != 0)
+ return err;
+
+ /* Get the interface type and test type */
+ interface_type = (image_type >> 16) & 0xffff;
+ test = (image_type & 0xffff);
+
+ /* Make sure everything makes sense */
+
+ /* First check the machine type is correct for
+ the requested image */
+ if (((perf_processor_interface == CUDA_INTF) &&
+ (interface_type != CUDA_INTF)) ||
+ ((perf_processor_interface == ONYX_INTF) &&
+ (interface_type != ONYX_INTF)))
+ return -EINVAL;
+
+ /* Next check to make sure the requested image
+ is valid */
+ if (((interface_type == CUDA_INTF) &&
+ (test >= MAX_CUDA_IMAGES)) ||
+ ((interface_type == ONYX_INTF) &&
+ (test >= MAX_ONYX_IMAGES)))
+ return -EINVAL;
+
+ /* Copy the image into the processor */
+ if (interface_type == CUDA_INTF)
+ return perf_config(cuda_images[test]);
+ else
+ return perf_config(onyx_images[test]);
+
+ return count;
+}
+
+/*
+ * Patch the images that need to know the IVA addresses.
+ */
+static void perf_patch_images(void)
+{
+#if 0 /* FIXME!! */
+/*
+ * NOTE: this routine is VERY specific to the current TLB image.
+ * If the image is changed, this routine might also need to be changed.
+ */
+ extern void $i_itlb_miss_2_0();
+ extern void $i_dtlb_miss_2_0();
+ extern void PA2_0_iva();
+
+ /*
+ * We can only use the lower 32-bits, the upper 32-bits should be 0
+ * anyway given this is in the kernel
+ */
+ uint32_t itlb_addr = (uint32_t)&($i_itlb_miss_2_0);
+ uint32_t dtlb_addr = (uint32_t)&($i_dtlb_miss_2_0);
+ uint32_t IVAaddress = (uint32_t)&PA2_0_iva;
+
+ if (perf_processor_interface == ONYX_INTF) {
+ /* clear last 2 bytes */
+ onyx_images[TLBMISS][15] &= 0xffffff00;
+ /* set 2 bytes */
+ onyx_images[TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
+ onyx_images[TLBMISS][16] = (dtlb_addr << 8)&0xffffff00;
+ onyx_images[TLBMISS][17] = itlb_addr;
+
+ /* clear last 2 bytes */
+ onyx_images[TLBHANDMISS][15] &= 0xffffff00;
+ /* set 2 bytes */
+ onyx_images[TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
+ onyx_images[TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00;
+ onyx_images[TLBHANDMISS][17] = itlb_addr;
+
+ /* clear last 2 bytes */
+ onyx_images[BIG_CPI][15] &= 0xffffff00;
+ /* set 2 bytes */
+ onyx_images[BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24));
+ onyx_images[BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00;
+ onyx_images[BIG_CPI][17] = itlb_addr;
+
+ onyx_images[PANIC][15] &= 0xffffff00; /* clear last 2 bytes */
+ onyx_images[PANIC][15] |= (0x000000ff&((IVAaddress) >> 24)); /* set 2 bytes */
+ onyx_images[PANIC][16] = (IVAaddress << 8)&0xffffff00;
+
+
+ } else if (perf_processor_interface == CUDA_INTF) {
+ /* Cuda interface */
+ cuda_images[TLBMISS][16] =
+ (cuda_images[TLBMISS][16]&0xffff0000) |
+ ((dtlb_addr >> 8)&0x0000ffff);
+ cuda_images[TLBMISS][17] =
+ ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
+ cuda_images[TLBMISS][18] = (itlb_addr << 16)&0xffff0000;
+
+ cuda_images[TLBHANDMISS][16] =
+ (cuda_images[TLBHANDMISS][16]&0xffff0000) |
+ ((dtlb_addr >> 8)&0x0000ffff);
+ cuda_images[TLBHANDMISS][17] =
+ ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
+ cuda_images[TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000;
+
+ cuda_images[BIG_CPI][16] =
+ (cuda_images[BIG_CPI][16]&0xffff0000) |
+ ((dtlb_addr >> 8)&0x0000ffff);
+ cuda_images[BIG_CPI][17] =
+ ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
+ cuda_images[BIG_CPI][18] = (itlb_addr << 16)&0xffff0000;
+ } else {
+ /* Unknown type */
+ }
+#endif
+}
+
+
+/*
+ * ioctl routine
+ * All routines effect the processor that they are executed on. Thus you
+ * must be running on the processor that you wish to change.
+ */
+
+static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ long error_start;
+ uint32_t raddr[4];
+
+ switch (cmd) {
+
+ case PA_PERF_ON:
+ /* Start the counters */
+ perf_start_counters();
+ return 0;
+
+ case PA_PERF_OFF:
+ error_start = perf_stop_counters(raddr);
+ if (error_start != 0) {
+ printk(KERN_ERR "perf_off: perf_stop_counters = %ld\n", error_start);
+ return -EFAULT;
+ }
+
+ /* copy out the Counters */
+ if (copy_to_user((void __user *)arg, raddr,
+ sizeof (raddr)) != 0) {
+ return -EFAULT;
+ }
+ return 0;
+
+ case PA_PERF_VERSION:
+ /* Return the version # */
+ return put_user(PERF_VERSION, (int *)arg);
+
+ default:
+ break;
+ }
+ return -ENOTTY;
+}
+
+static struct file_operations perf_fops = {
+ .llseek = no_llseek,
+ .read = perf_read,
+ .write = perf_write,
+ .ioctl = perf_ioctl,
+ .open = perf_open,
+ .release = perf_release
+};
+
+static struct miscdevice perf_dev = {
+ MISC_DYNAMIC_MINOR,
+ PA_PERF_DEV,
+ &perf_fops
+};
+
+/*
+ * Initialize the module
+ */
+static int __init perf_init(void)
+{
+ int ret;
+
+ /* Determine correct processor interface to use */
+ bitmask_array = perf_bitmasks;
+
+ if (boot_cpu_data.cpu_type == pcxu ||
+ boot_cpu_data.cpu_type == pcxu_) {
+ perf_processor_interface = ONYX_INTF;
+ } else if (boot_cpu_data.cpu_type == pcxw ||
+ boot_cpu_data.cpu_type == pcxw_ ||
+ boot_cpu_data.cpu_type == pcxw2 ||
+ boot_cpu_data.cpu_type == mako) {
+ perf_processor_interface = CUDA_INTF;
+ if (boot_cpu_data.cpu_type == pcxw2 ||
+ boot_cpu_data.cpu_type == mako)
+ bitmask_array = perf_bitmasks_piranha;
+ } else {
+ perf_processor_interface = UNKNOWN_INTF;
+ printk("Performance monitoring counters not supported on this processor\n");
+ return -ENODEV;
+ }
+
+ ret = misc_register(&perf_dev);
+ if (ret) {
+ printk(KERN_ERR "Performance monitoring counters: "
+ "cannot register misc device.\n");
+ return ret;
+ }
+
+ /* Patch the images to match the system */
+ perf_patch_images();
+
+ spin_lock_init(&perf_lock);
+
+ /* TODO: this only lets us access the first cpu.. what to do for SMP? */
+ cpu_device = cpu_data[0].dev;
+ printk("Performance monitoring counters enabled for %s\n",
+ cpu_data[0].dev->name);
+
+ return 0;
+}
+
+/*
+ * perf_start_counters(void)
+ *
+ * Start the counters.
+ */
+static void perf_start_counters(void)
+{
+ /* Enable performance monitor counters */
+ perf_intrigue_enable_perf_counters();
+}
+
+/*
+ * perf_stop_counters
+ *
+ * Stop the performance counters and save counts
+ * in a per_processor array.
+ */
+static int perf_stop_counters(uint32_t *raddr)
+{
+ uint64_t userbuf[MAX_RDR_WORDS];
+
+ /* Disable performance counters */
+ perf_intrigue_disable_perf_counters();
+
+ if (perf_processor_interface == ONYX_INTF) {
+ uint64_t tmp64;
+ /*
+ * Read the counters
+ */
+ if (!perf_rdr_read_ubuf(16, userbuf))
+ return -13;
+
+ /* Counter0 is bits 1398 thru 1429 */
+ tmp64 = (userbuf[21] << 22) & 0x00000000ffc00000;
+ tmp64 |= (userbuf[22] >> 42) & 0x00000000003fffff;
+ /* OR sticky0 (bit 1430) to counter0 bit 32 */
+ tmp64 |= (userbuf[22] >> 10) & 0x0000000080000000;
+ raddr[0] = (uint32_t)tmp64;
+
+ /* Counter1 is bits 1431 thru 1462 */
+ tmp64 = (userbuf[22] >> 9) & 0x00000000ffffffff;
+ /* OR sticky1 (bit 1463) to counter1 bit 32 */
+ tmp64 |= (userbuf[22] << 23) & 0x0000000080000000;
+ raddr[1] = (uint32_t)tmp64;
+
+ /* Counter2 is bits 1464 thru 1495 */
+ tmp64 = (userbuf[22] << 24) & 0x00000000ff000000;
+ tmp64 |= (userbuf[23] >> 40) & 0x0000000000ffffff;
+ /* OR sticky2 (bit 1496) to counter2 bit 32 */
+ tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000;
+ raddr[2] = (uint32_t)tmp64;
+
+ /* Counter3 is bits 1497 thru 1528 */
+ tmp64 = (userbuf[23] >> 7) & 0x00000000ffffffff;
+ /* OR sticky3 (bit 1529) to counter3 bit 32 */
+ tmp64 |= (userbuf[23] << 25) & 0x0000000080000000;
+ raddr[3] = (uint32_t)tmp64;
+
+ /*
+ * Zero out the counters
+ */
+
+ /*
+ * The counters and sticky-bits comprise the last 132 bits
+ * (1398 - 1529) of RDR16 on a U chip. We'll zero these
+ * out the easy way: zero out last 10 bits of dword 21,
+ * all of dword 22 and 58 bits (plus 6 don't care bits) of
+ * dword 23.
+ */
+ userbuf[21] &= 0xfffffffffffffc00ul; /* 0 to last 10 bits */
+ userbuf[22] = 0;
+ userbuf[23] = 0;
+
+ /*
+ * Write back the zero'ed bytes + the image given
+ * the read was destructive.
+ */
+ perf_rdr_write(16, userbuf);
+ } else {
+
+ /*
+ * Read RDR-15 which contains the counters and sticky bits
+ */
+ if (!perf_rdr_read_ubuf(15, userbuf)) {
+ return -13;
+ }
+
+ /*
+ * Clear out the counters
+ */
+ perf_rdr_clear(15);
+
+ /*
+ * Copy the counters
+ */
+ raddr[0] = (uint32_t)((userbuf[0] >> 32) & 0x00000000ffffffffUL);
+ raddr[1] = (uint32_t)(userbuf[0] & 0x00000000ffffffffUL);
+ raddr[2] = (uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffffUL);
+ raddr[3] = (uint32_t)(userbuf[1] & 0x00000000ffffffffUL);
+ }
+
+ return 0;
+}
+
+/*
+ * perf_rdr_get_entry
+ *
+ * Retrieve a pointer to the description of what this
+ * RDR contains.
+ */
+static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num)
+{
+ if (perf_processor_interface == ONYX_INTF) {
+ return &perf_rdr_tbl_U[rdr_num];
+ } else {
+ return &perf_rdr_tbl_W[rdr_num];
+ }
+}
+
+/*
+ * perf_rdr_read_ubuf
+ *
+ * Read the RDR value into the buffer specified.
+ */
+static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer)
+{
+ uint64_t data, data_mask = 0;
+ uint32_t width, xbits, i;
+ struct rdr_tbl_ent *tentry;
+
+ tentry = perf_rdr_get_entry(rdr_num);
+ if ((width = tentry->width) == 0)
+ return 0;
+
+ /* Clear out buffer */
+ i = tentry->num_words;
+ while (i--) {
+ buffer[i] = 0;
+ }
+
+ /* Check for bits an even number of 64 */
+ if ((xbits = width & 0x03f) != 0) {
+ data_mask = 1;
+ data_mask <<= (64 - xbits);
+ data_mask--;
+ }
+
+ /* Grab all of the data */
+ i = tentry->num_words;
+ while (i--) {
+
+ if (perf_processor_interface == ONYX_INTF) {
+ data = perf_rdr_shift_in_U(rdr_num, width);
+ } else {
+ data = perf_rdr_shift_in_W(rdr_num, width);
+ }
+ if (xbits) {
+ buffer[i] |= (data << (64 - xbits));
+ if (i) {
+ buffer[i-1] |= ((data >> xbits) & data_mask);
+ }
+ } else {
+ buffer[i] = data;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * perf_rdr_clear
+ *
+ * Zero out the given RDR register
+ */
+static int perf_rdr_clear(uint32_t rdr_num)
+{
+ struct rdr_tbl_ent *tentry;
+ int32_t i;
+
+ tentry = perf_rdr_get_entry(rdr_num);
+
+ if (tentry->width == 0) {
+ return -1;
+ }
+
+ i = tentry->num_words;
+ while (i--) {
+ if (perf_processor_interface == ONYX_INTF) {
+ perf_rdr_shift_out_U(rdr_num, 0UL);
+ } else {
+ perf_rdr_shift_out_W(rdr_num, 0UL);
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * perf_write_image
+ *
+ * Write the given image out to the processor
+ */
+static int perf_write_image(uint64_t *memaddr)
+{
+ uint64_t buffer[MAX_RDR_WORDS];
+ uint64_t *bptr;
+ uint32_t dwords;
+ uint32_t *intrigue_rdr;
+ uint64_t *intrigue_bitmask, tmp64, proc_hpa;
+ struct rdr_tbl_ent *tentry;
+ int i;
+
+ /* Clear out counters */
+ if (perf_processor_interface == ONYX_INTF) {
+
+ perf_rdr_clear(16);
+
+ /* Toggle performance monitor */
+ perf_intrigue_enable_perf_counters();
+ perf_intrigue_disable_perf_counters();
+
+ intrigue_rdr = perf_rdrs_U;
+ } else {
+ perf_rdr_clear(15);
+ intrigue_rdr = perf_rdrs_W;
+ }
+
+ /* Write all RDRs */
+ while (*intrigue_rdr != -1) {
+ tentry = perf_rdr_get_entry(*intrigue_rdr);
+ perf_rdr_read_ubuf(*intrigue_rdr, buffer);
+ bptr = &buffer[0];
+ dwords = tentry->num_words;
+ if (tentry->write_control) {
+ intrigue_bitmask = &bitmask_array[tentry->write_control >> 3];
+ while (dwords--) {
+ tmp64 = *intrigue_bitmask & *memaddr++;
+ tmp64 |= (~(*intrigue_bitmask++)) & *bptr;
+ *bptr++ = tmp64;
+ }
+ } else {
+ while (dwords--) {
+ *bptr++ = *memaddr++;
+ }
+ }
+
+ perf_rdr_write(*intrigue_rdr, buffer);
+ intrigue_rdr++;
+ }
+
+ /*
+ * Now copy out the Runway stuff which is not in RDRs
+ */
+
+ if (cpu_device == NULL)
+ {
+ printk(KERN_ERR "write_image: cpu_device not yet initialized!\n");
+ return -1;
+ }
+
+ proc_hpa = cpu_device->hpa;
+
+ /* Merge intrigue bits into Runway STATUS 0 */
+ tmp64 = __raw_readq(proc_hpa + RUNWAY_STATUS) & 0xffecfffffffffffful;
+ __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), proc_hpa + RUNWAY_STATUS);
+
+ /* Write RUNWAY DEBUG registers */
+ for (i = 0; i < 8; i++) {
+ __raw_writeq(*memaddr++, proc_hpa + RUNWAY_DEBUG + i);
+ }
+
+ return 0;
+}
+
+/*
+ * perf_rdr_write
+ *
+ * Write the given RDR register with the contents
+ * of the given buffer.
+ */
+static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer)
+{
+ struct rdr_tbl_ent *tentry;
+ int32_t i;
+
+printk("perf_rdr_write\n");
+ tentry = perf_rdr_get_entry(rdr_num);
+ if (tentry->width == 0) { return; }
+
+ i = tentry->num_words;
+ while (i--) {
+ if (perf_processor_interface == ONYX_INTF) {
+ perf_rdr_shift_out_U(rdr_num, buffer[i]);
+ } else {
+ perf_rdr_shift_out_W(rdr_num, buffer[i]);
+ }
+ }
+printk("perf_rdr_write done\n");
+}
+
+module_init(perf_init);
diff --git a/arch/parisc/kernel/perf_asm.S b/arch/parisc/kernel/perf_asm.S
new file mode 100644
index 000000000000..adb3c6444910
--- /dev/null
+++ b/arch/parisc/kernel/perf_asm.S
@@ -0,0 +1,1691 @@
+
+/* low-level asm for "intrigue" (PA8500-8700 CPU perf counters)
+ *
+ * Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org>
+ * Copyright (C) 2001 Hewlett-Packard (Grant Grundler)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <asm/assembly.h>
+
+#ifdef CONFIG_64BIT
+ .level 2.0w
+#endif /* CONFIG_64BIT */
+
+#define MTDIAG_1(gr) .word 0x14201840 + gr*0x10000
+#define MTDIAG_2(gr) .word 0x14401840 + gr*0x10000
+#define MFDIAG_1(gr) .word 0x142008A0 + gr
+#define MFDIAG_2(gr) .word 0x144008A0 + gr
+#define STDIAG(dr) .word 0x14000AA0 + dr*0x200000
+#define SFDIAG(dr) .word 0x14000BA0 + dr*0x200000
+#define DR2_SLOW_RET 53
+
+
+;
+; Enable the performance counters
+;
+; The coprocessor only needs to be enabled when
+; starting/stopping the coprocessor with the pmenb/pmdis.
+;
+ .text
+ .align 32
+
+ .export perf_intrigue_enable_perf_counters,code
+perf_intrigue_enable_perf_counters:
+ .proc
+ .callinfo frame=0,NO_CALLS
+ .entry
+
+ ldi 0x20,%r25 ; load up perfmon bit
+ mfctl ccr,%r26 ; get coprocessor register
+ or %r25,%r26,%r26 ; set bit
+ mtctl %r26,ccr ; turn on performance coprocessor
+ pmenb ; enable performance monitor
+ ssm 0,0 ; dummy op to ensure completion
+ sync ; follow ERS
+ andcm %r26,%r25,%r26 ; clear bit now
+ mtctl %r26,ccr ; turn off performance coprocessor
+ nop ; NOPs as specified in ERS
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ bve (%r2)
+ nop
+ .exit
+ .procend
+
+ .export perf_intrigue_disable_perf_counters,code
+perf_intrigue_disable_perf_counters:
+ .proc
+ .callinfo frame=0,NO_CALLS
+ .entry
+ ldi 0x20,%r25 ; load up perfmon bit
+ mfctl ccr,%r26 ; get coprocessor register
+ or %r25,%r26,%r26 ; set bit
+ mtctl %r26,ccr ; turn on performance coprocessor
+ pmdis ; disable performance monitor
+ ssm 0,0 ; dummy op to ensure completion
+ andcm %r26,%r25,%r26 ; clear bit now
+ bve (%r2)
+ mtctl %r26,ccr ; turn off performance coprocessor
+ .exit
+ .procend
+
+;***********************************************************************
+;*
+;* Name: perf_rdr_shift_in_W
+;*
+;* Description:
+;* This routine shifts data in from the RDR in arg0 and returns
+;* the result in ret0. If the RDR is <= 64 bits in length, it
+;* is shifted shifted backup immediately. This is to compensate
+;* for RDR10 which has bits that preclude PDC stack operations
+;* when they are in the wrong state.
+;*
+;* Arguments:
+;* arg0 : rdr to be read
+;* arg1 : bit length of rdr
+;*
+;* Returns:
+;* ret0 = next 64 bits of rdr data from staging register
+;*
+;* Register usage:
+;* arg0 : rdr to be read
+;* arg1 : bit length of rdr
+;* %r24 - original DR2 value
+;* %r1 - scratch
+;* %r29 - scratch
+;*
+;* Returns:
+;* ret0 = RDR data (right justified)
+;*
+;***********************************************************************
+
+ .export perf_rdr_shift_in_W,code
+perf_rdr_shift_in_W:
+ .proc
+ .callinfo frame=0,NO_CALLS
+ .entry
+;
+; read(shift in) the RDR.
+;
+
+; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any
+; shifting is done, from or to, remote diagnose registers.
+;
+
+ depdi,z 1,DR2_SLOW_RET,1,%r29
+ MFDIAG_2 (24)
+ or %r24,%r29,%r29
+ MTDIAG_2 (29) ; set DR2_SLOW_RET
+
+ nop
+ nop
+ nop
+ nop
+
+;
+; Cacheline start (32-byte cacheline)
+;
+ nop
+ nop
+ nop
+ extrd,u arg1,63,6,%r1 ; setup shift amount by bits to move
+
+ mtsar %r1
+ shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number
+ blr %r1,%r0 ; branch to 8-instruction sequence
+ nop
+
+;
+; Cacheline start (32-byte cacheline)
+;
+
+ ;
+ ; RDR 0 sequence
+ ;
+ SFDIAG (0)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1) ; mtdiag %dr1, %r1
+ STDIAG (0)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 1 sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (1)
+ ssm 0,0
+ MFDIAG_1 (28)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+ nop
+
+ ;
+ ; RDR 2 read sequence
+ ;
+ SFDIAG (2)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (2)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 3 read sequence
+ ;
+ b,n perf_rdr_shift_in_W_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ ;
+ ; RDR 4 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (4)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 5 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (5)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 6 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (6)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 7 read sequence
+ ;
+ b,n perf_rdr_shift_in_W_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ ;
+ ; RDR 8 read sequence
+ ;
+ b,n perf_rdr_shift_in_W_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ ;
+ ; RDR 9 read sequence
+ ;
+ b,n perf_rdr_shift_in_W_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ ;
+ ; RDR 10 read sequence
+ ;
+ SFDIAG (10)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (10)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 11 read sequence
+ ;
+ SFDIAG (11)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (11)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 12 read sequence
+ ;
+ b,n perf_rdr_shift_in_W_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ ;
+ ; RDR 13 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (13)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 14 read sequence
+ ;
+ SFDIAG (14)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (14)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 15 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (15)
+ ssm 0,0
+ MFDIAG_1 (28)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+ nop
+
+ ;
+ ; RDR 16 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (16)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 17 read sequence
+ ;
+ SFDIAG (17)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (17)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 18 read sequence
+ ;
+ SFDIAG (18)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (18)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 19 read sequence
+ ;
+ b,n perf_rdr_shift_in_W_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ ;
+ ; RDR 20 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (20)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 21 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (21)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 22 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (22)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 23 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (23)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 24 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (24)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 25 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (25)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 26 read sequence
+ ;
+ SFDIAG (26)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (26)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 27 read sequence
+ ;
+ SFDIAG (27)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (27)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 28 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (28)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 29 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (29)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 30 read sequence
+ ;
+ SFDIAG (30)
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (30)
+ ssm 0,0
+ b,n perf_rdr_shift_in_W_leave
+
+ ;
+ ; RDR 31 read sequence
+ ;
+ sync
+ ssm 0,0
+ SFDIAG (31)
+ ssm 0,0
+ MFDIAG_1 (28)
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; Fallthrough
+ ;
+
+perf_rdr_shift_in_W_leave:
+ bve (%r2)
+ .exit
+ MTDIAG_2 (24) ; restore DR2
+ .procend
+
+
+;***********************************************************************
+;*
+;* Name: perf_rdr_shift_out_W
+;*
+;* Description:
+;* This routine moves data to the RDR's. The double-word that
+;* arg1 points to is loaded and moved into the staging register.
+;* Then the STDIAG instruction for the RDR # in arg0 is called
+;* to move the data to the RDR.
+;*
+;* Arguments:
+;* arg0 = rdr number
+;* arg1 = 64-bit value to write
+;* %r24 - DR2 | DR2_SLOW_RET
+;* %r23 - original DR2 value
+;*
+;* Returns:
+;* None
+;*
+;* Register usage:
+;*
+;***********************************************************************
+
+ .export perf_rdr_shift_out_W,code
+perf_rdr_shift_out_W:
+ .proc
+ .callinfo frame=0,NO_CALLS
+ .entry
+;
+; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any
+; shifting is done, from or to, the remote diagnose registers.
+;
+
+ depdi,z 1,DR2_SLOW_RET,1,%r24
+ MFDIAG_2 (23)
+ or %r24,%r23,%r24
+ MTDIAG_2 (24) ; set DR2_SLOW_RET
+ MTDIAG_1 (25) ; data to the staging register
+ shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number
+ blr %r1,%r0 ; branch to 8-instruction sequence
+ nop
+
+ ;
+ ; RDR 0 write sequence
+ ;
+ sync ; RDR 0 write sequence
+ ssm 0,0
+ STDIAG (0)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 1 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (1)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 2 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (2)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 3 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (3)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 4 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (4)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 5 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (5)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 6 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (6)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 7 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (7)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 8 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (8)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 9 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (9)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 10 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (10)
+ STDIAG (26)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 11 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (11)
+ STDIAG (27)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 12 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (12)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 13 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (13)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 14 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (14)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 15 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (15)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 16 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (16)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 17 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (17)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 18 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (18)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 19 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (19)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 20 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (20)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 21 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (21)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 22 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (22)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 23 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (23)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 24 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (24)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 25 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (25)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 26 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (10)
+ STDIAG (26)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 27 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (11)
+ STDIAG (27)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 28 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (28)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 29 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (29)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 30 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (30)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+ ;
+ ; RDR 31 write sequence
+ ;
+ sync
+ ssm 0,0
+ STDIAG (31)
+ ssm 0,0
+ b,n perf_rdr_shift_out_W_leave
+ nop
+ ssm 0,0
+ nop
+
+perf_rdr_shift_out_W_leave:
+ bve (%r2)
+ .exit
+ MTDIAG_2 (23) ; restore DR2
+ .procend
+
+
+;***********************************************************************
+;*
+;* Name: rdr_shift_in_U
+;*
+;* Description:
+;* This routine shifts data in from the RDR in arg0 and returns
+;* the result in ret0. If the RDR is <= 64 bits in length, it
+;* is shifted shifted backup immediately. This is to compensate
+;* for RDR10 which has bits that preclude PDC stack operations
+;* when they are in the wrong state.
+;*
+;* Arguments:
+;* arg0 : rdr to be read
+;* arg1 : bit length of rdr
+;*
+;* Returns:
+;* ret0 = next 64 bits of rdr data from staging register
+;*
+;* Register usage:
+;* arg0 : rdr to be read
+;* arg1 : bit length of rdr
+;* %r24 - original DR2 value
+;* %r23 - DR2 | DR2_SLOW_RET
+;* %r1 - scratch
+;*
+;***********************************************************************
+
+ .export perf_rdr_shift_in_U,code
+perf_rdr_shift_in_U:
+ .proc
+ .callinfo frame=0,NO_CALLS
+ .entry
+
+; read(shift in) the RDR.
+;
+; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any
+; shifting is done, from or to, remote diagnose registers.
+
+ depdi,z 1,DR2_SLOW_RET,1,%r29
+ MFDIAG_2 (24)
+ or %r24,%r29,%r29
+ MTDIAG_2 (29) ; set DR2_SLOW_RET
+
+ nop
+ nop
+ nop
+ nop
+
+;
+; Start of next 32-byte cacheline
+;
+ nop
+ nop
+ nop
+ extrd,u arg1,63,6,%r1
+
+ mtsar %r1
+ shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number
+ blr %r1,%r0 ; branch to 8-instruction sequence
+ nop
+
+;
+; Start of next 32-byte cacheline
+;
+ SFDIAG (0) ; RDR 0 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (0)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (1) ; RDR 1 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (1)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ sync ; RDR 2 read sequence
+ ssm 0,0
+ SFDIAG (4)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 3 read sequence
+ ssm 0,0
+ SFDIAG (3)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 4 read sequence
+ ssm 0,0
+ SFDIAG (4)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 5 read sequence
+ ssm 0,0
+ SFDIAG (5)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 6 read sequence
+ ssm 0,0
+ SFDIAG (6)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 7 read sequence
+ ssm 0,0
+ SFDIAG (7)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ b,n perf_rdr_shift_in_U_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ SFDIAG (9) ; RDR 9 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (9)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (10) ; RDR 10 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (10)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (11) ; RDR 11 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (11)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (12) ; RDR 12 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (12)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (13) ; RDR 13 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (13)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (14) ; RDR 14 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (14)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (15) ; RDR 15 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (15)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ sync ; RDR 16 read sequence
+ ssm 0,0
+ SFDIAG (16)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ SFDIAG (17) ; RDR 17 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (17)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (18) ; RDR 18 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (18)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ b,n perf_rdr_shift_in_U_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ sync ; RDR 20 read sequence
+ ssm 0,0
+ SFDIAG (20)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 21 read sequence
+ ssm 0,0
+ SFDIAG (21)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 22 read sequence
+ ssm 0,0
+ SFDIAG (22)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 23 read sequence
+ ssm 0,0
+ SFDIAG (23)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 24 read sequence
+ ssm 0,0
+ SFDIAG (24)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ sync ; RDR 25 read sequence
+ ssm 0,0
+ SFDIAG (25)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ SFDIAG (26) ; RDR 26 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (26)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (27) ; RDR 27 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (27)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ sync ; RDR 28 read sequence
+ ssm 0,0
+ SFDIAG (28)
+ ssm 0,0
+ MFDIAG_1 (28)
+ b,n perf_rdr_shift_in_U_leave
+ ssm 0,0
+ nop
+
+ b,n perf_rdr_shift_in_U_leave
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ SFDIAG (30) ; RDR 30 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (30)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+
+ SFDIAG (31) ; RDR 31 read sequence
+ ssm 0,0
+ MFDIAG_1 (28)
+ shrpd ret0,%r0,%sar,%r1
+ MTDIAG_1 (1)
+ STDIAG (31)
+ ssm 0,0
+ b,n perf_rdr_shift_in_U_leave
+ nop
+
+perf_rdr_shift_in_U_leave:
+ bve (%r2)
+ .exit
+ MTDIAG_2 (24) ; restore DR2
+ .procend
+
+;***********************************************************************
+;*
+;* Name: rdr_shift_out_U
+;*
+;* Description:
+;* This routine moves data to the RDR's. The double-word that
+;* arg1 points to is loaded and moved into the staging register.
+;* Then the STDIAG instruction for the RDR # in arg0 is called
+;* to move the data to the RDR.
+;*
+;* Arguments:
+;* arg0 = rdr target
+;* arg1 = buffer pointer
+;*
+;* Returns:
+;* None
+;*
+;* Register usage:
+;* arg0 = rdr target
+;* arg1 = buffer pointer
+;* %r24 - DR2 | DR2_SLOW_RET
+;* %r23 - original DR2 value
+;*
+;***********************************************************************
+
+ .export perf_rdr_shift_out_U,code
+perf_rdr_shift_out_U:
+ .proc
+ .callinfo frame=0,NO_CALLS
+ .entry
+
+;
+; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any
+; shifting is done, from or to, the remote diagnose registers.
+;
+
+ depdi,z 1,DR2_SLOW_RET,1,%r24
+ MFDIAG_2 (23)
+ or %r24,%r23,%r24
+ MTDIAG_2 (24) ; set DR2_SLOW_RET
+
+ MTDIAG_1 (25) ; data to the staging register
+ shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number
+ blr %r1,%r0 ; branch to 8-instruction sequence
+ nop
+
+;
+; 32-byte cachline aligned
+;
+
+ sync ; RDR 0 write sequence
+ ssm 0,0
+ STDIAG (0)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 1 write sequence
+ ssm 0,0
+ STDIAG (1)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 2 write sequence
+ ssm 0,0
+ STDIAG (2)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 3 write sequence
+ ssm 0,0
+ STDIAG (3)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 4 write sequence
+ ssm 0,0
+ STDIAG (4)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 5 write sequence
+ ssm 0,0
+ STDIAG (5)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 6 write sequence
+ ssm 0,0
+ STDIAG (6)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 7 write sequence
+ ssm 0,0
+ STDIAG (7)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 8 write sequence
+ ssm 0,0
+ STDIAG (8)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 9 write sequence
+ ssm 0,0
+ STDIAG (9)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 10 write sequence
+ ssm 0,0
+ STDIAG (10)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 11 write sequence
+ ssm 0,0
+ STDIAG (11)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 12 write sequence
+ ssm 0,0
+ STDIAG (12)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 13 write sequence
+ ssm 0,0
+ STDIAG (13)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 14 write sequence
+ ssm 0,0
+ STDIAG (14)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 15 write sequence
+ ssm 0,0
+ STDIAG (15)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 16 write sequence
+ ssm 0,0
+ STDIAG (16)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 17 write sequence
+ ssm 0,0
+ STDIAG (17)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 18 write sequence
+ ssm 0,0
+ STDIAG (18)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 19 write sequence
+ ssm 0,0
+ STDIAG (19)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 20 write sequence
+ ssm 0,0
+ STDIAG (20)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 21 write sequence
+ ssm 0,0
+ STDIAG (21)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 22 write sequence
+ ssm 0,0
+ STDIAG (22)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 23 write sequence
+ ssm 0,0
+ STDIAG (23)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 24 write sequence
+ ssm 0,0
+ STDIAG (24)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 25 write sequence
+ ssm 0,0
+ STDIAG (25)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 26 write sequence
+ ssm 0,0
+ STDIAG (26)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 27 write sequence
+ ssm 0,0
+ STDIAG (27)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 28 write sequence
+ ssm 0,0
+ STDIAG (28)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 29 write sequence
+ ssm 0,0
+ STDIAG (29)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 30 write sequence
+ ssm 0,0
+ STDIAG (30)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+ sync ; RDR 31 write sequence
+ ssm 0,0
+ STDIAG (31)
+ ssm 0,0
+ b,n perf_rdr_shift_out_U_leave
+ nop
+ ssm 0,0
+ nop
+
+perf_rdr_shift_out_U_leave:
+ bve (%r2)
+ .exit
+ MTDIAG_2 (23) ; restore DR2
+ .procend
+
diff --git a/arch/parisc/kernel/perf_images.h b/arch/parisc/kernel/perf_images.h
new file mode 100644
index 000000000000..d9562fe3f75c
--- /dev/null
+++ b/arch/parisc/kernel/perf_images.h
@@ -0,0 +1,3138 @@
+/*
+ * Imagine for use with the Onyx (PCX-U) CPU interface
+ *
+ * Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org>
+ * Copyright (C) 2001 Hewlett-Packard (Grant Grundler)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef PERF_IMAGES_H
+#define PERF_IMAGES_H
+
+/* Magic numbers taken without modification from HPUX stuff */
+
+#define PCXU_IMAGE_SIZE 584
+
+static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] = {
+/*
+ * CPI:
+ *
+ * Counts the following:
+ *
+ * ctr0 : total cycles
+ * ctr1 : total cycles where nothing retired
+ * ctr2 : total instructions retired, including nullified
+ * ctr3 : total instructions retired, less nullified instructions
+ */
+ {
+ 0x4c00c000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
+ 0x0101ffff, 0xfffff104, 0xe000c07f, 0xfffffffc,
+ 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
+ 0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00,
+ 0x000fffff, 0x00000000, 0x00000000, 0x00ffffff,
+ 0xfffff000, 0x0000000f, 0xffffffff, 0xff000000,
+ 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
+ 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
+ 0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000,
+ 0xf0000030, 0x00003c00, 0x067f080c, 0x02019fc0,
+ 0x02804067, 0xf0009030, 0x19fc002c, 0x40067f08,
+ 0x0c12019f, 0xc0028440, 0x67f00091, 0x3019fc00,
+ 0x2fc007ff, 0xf800f001, 0xfffe003c, 0x007fff80,
+ 0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00,
+ 0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800,
+ 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003,
+ 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f,
+ 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c,
+ 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0,
+ 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff},
+
+/* Bus utilization image (bus_util)
+ *
+ * ctr0 : counts address valid cycles
+ * ctr1 : counts data valid cycles
+ * ctr2 : counts overflow from counter 0
+ * ctr3 : counts overflow from counter 1
+ */
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
+ 0x0000000c, 0x00003c00, 0x07930000, 0x0041e4c0,
+ 0x01002079, 0x3000800c, 0x1e4c0030, 0x00279300,
+ 0x010049e4, 0xc0014022, 0x79300090, 0x0c9e4c00,
+ 0x34004793, 0x00020051, 0xe4c00180, 0x24793000,
+ 0xa00d1e4c, 0x00380067, 0x93000300, 0x59e4c001,
+ 0xc0267930, 0x00b00d9e, 0x4c003fff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00100000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff },
+
+/*
+ * TLB counts (same as tlbStats image):
+ *
+ * Counts the following:
+ *
+ * ctr0: DTLB misses
+ * ctr1: ITLB misses
+ * ctr2: total cycles in the miss handlers
+ * ctr3: total cycles
+ */
+
+ {
+ 0x0c00c000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe7e7e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
+ 0x0101ffff, 0xfffff104, 0xe000c06a, 0xafffc85c,
+ 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
+ 0x01b9e000, 0x0001b8c0, 0x00000000, 0x0fffff00,
+ 0x000fffff, 0x00000000, 0x00000000, 0x00400000,
+ 0x00001000, 0x00000004, 0x00000000, 0x01000000,
+ 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
+ 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
+ 0xfff55ff5, 0xffffffff, 0xffffffff, 0xf0000000,
+ 0xf0000000, 0x00003c00, 0x01ff0001, 0x08007fc2,
+ 0x02c1001f, 0xf0807100, 0x1bfc200c, 0x4806ff00,
+ 0x03f001ff, 0xfe003c00, 0x7fff800f, 0x001fffe0,
+ 0x03c007ff, 0xf800f001, 0xfffe003c, 0x007fff80,
+ 0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00,
+ 0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800,
+ 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003,
+ 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f,
+ 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c,
+ 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0,
+ 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff },
+
+/* tlbHandMiss
+ *
+ * ctr0: counts TLB misses
+ * ctr1: counts dmisses inside tlb miss handlers
+ * ctr2: counts cycles in the tlb miss handlers
+ * ctr3: counts overflows of ctr2
+ */
+{
+0x1c00c000,00000000,0x00060000,00000000,
+0xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380,
+0x0101ffff,0xfffff104,0xe000c06a,0xafffc85c,
+0x01380010,0x1fffffff,0xff000000,00000000,
+0x01b9e000,0x0001b8c0,00000000,0x0fffff00,
+0x000fffff,00000000,00000000,0x00400000,
+0x00001000,0x00000004,00000000,0x01000000,
+0x0000ffff,0xfffffff0,00000000,0x0fffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xfff55ff5,0xffffffff,0xffffffff,0xf0000000,
+0xf0000000,0x00003c00,0x01fd0000,0x08007f42,
+0x0281001f,0xd080a100,0x19f42008,0x44067d08,
+0x0612019f,0x400084c0,0x67d00060,0x0047f400,
+0x042011fd,0x080b0404,0x7f4202c4,0x0167d080,
+0x311059f4,0x201c4816,0x7d000313,0x059f4001,
+0xfc007fff,0x800f001f,0xffe003c0,0x07fff800,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x6fff0000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* branch_taken image (ptkn image)
+ *
+ * ctr0: overflow for ctr1
+ * ctr1: predicted taken branches, actually taken
+ * ctr2: all predicted taken branches (nullfied or not)
+ * ctr3: overflow for ctr2
+ */
+
+ {
+ 0xcc01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
+ 0xf0000000, 0x00003c00, 0x04f90000, 0x02013e40,
+ 0x0081004f, 0x90004060, 0x13e40018, 0x0024f900,
+ 0x0802093e, 0x40028102, 0x4f9000c0, 0x6093e400,
+ 0x380014f9, 0x00010205, 0x3e4000c1, 0x014f9000,
+ 0x506053e4, 0x001c0034, 0xf9000902, 0x0d3e4002,
+ 0xc1034f90, 0x00d060d3, 0xe4003fff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff },
+
+/* branch_nottaken (pntkn image)
+ *
+ * ctr0: overflow for ctr1
+ * ctr1: counts branches predicted not-taken, but actually taken
+ * ctr2: counts all predictable branches predicted not-taken
+ * ctr3: overflow for ctr2
+ */
+{
+0xcc01e000,00000000,0x00060000,00000000,
+0xc0c0c0e0,0xffb1fffb,0xfff7ffff,0xffffffff,
+0xffffffff,0xfffffffb,0x1fffbfff,0x7fffffff,
+0xfcc7ffff,0xffdffffa,0x5f000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+
+/* imiss image
+ *
+ * ctr0 : counts imiss aligned on 0
+ * ctr1 : counts imiss aligned on 4
+ * ctr2 : counts imiss aligned on 8
+ * ctr3 : counts imiss aligned on C
+ */
+ {
+ 0x0c00c000, 0x00000000, 0x00010000, 0x00000000,
+ 0xe7ebedee, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
+ 0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000,
+ 0xf0000000, 0x00003c00, 0x007f0000, 0x01001fc0,
+ 0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00,
+ 0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00,
+ 0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000,
+ 0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003,
+ 0x438007f0, 0x00e0f001, 0xfc003fff, 0xfffff800,
+ 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003,
+ 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f,
+ 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f,
+ 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff,
+ 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff},
+
+/* dmiss image
+ *
+ * ctr0 : counts cycles
+ * ctr1 : counts cycles where something retired
+ * ctr2 : counts dmisses
+ * ctr3 : (same as ctr2)
+ */
+ {
+ 0x3c00c000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
+ 0xf0000000, 0x00003c04, 0x007f0009, 0x02001fc0,
+ 0x0280c007, 0xf000b040, 0x01fc0030, 0x14007f00,
+ 0x0d06001f, 0xc00381c0, 0x07f000f0, 0x8001fc00,
+ 0x2024007f, 0x00090a00, 0x1fc00282, 0xc007f000,
+ 0xb0c001fc, 0x00303400, 0x7f000d0e, 0x001fc003,
+ 0x83c007f0, 0x00f00001, 0xfc0023ff, 0xfffff800,
+ 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003,
+ 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f,
+ 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f,
+ 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff,
+ 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff },
+
+/* dcmiss
+ *
+ * ctr0: counts store instructions retired
+ * ctr1: counts load instructions retired
+ * ctr2: counts dmisses
+ * ctr3: counts READ_SHARED_OR_PRIV and READ_PRIVATE transactions on Runway
+ */
+{
+0x2c90c000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf00000e8,0x00003c02,0x00bf0001,0x02002fc0,
+0x0080a00b,0xf0003040,0x02fc0010,0x1200bf00,
+0x0506002f,0xc00181a0,0x0bf00070,0x8002fc00,
+0x202200bf,0x00090a00,0x2fc00282,0xa00bf000,
+0xb0c002fc,0x00303200,0xbf000d0e,0x002fc003,
+0x83a00bf0,0x00ffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0x6fff0000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0x55555555,0xd5555555,
+0x55555555,0x75555555,0x5e1ffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xf8000000,00000000,
+00000000,00000000,0xf4000000,00000000,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+00000000,00000000,0x00ffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* big_cpi
+ *
+ * ctr0: counts total cycles
+ * ctr1: counts overflows of ctr0 (for greater than 32-bit values)
+ * ctr2: counts overflows of ctr3 (for greater than 32-bit values)
+ * ctr3: counts unnullified instructions retired
+ */
+{
+0x0c00c000,00000000,0x00060000,00000000,
+0xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380,
+0x0101ffff,0xfffff104,0xe000c06a,0xafffc85c,
+0x01380010,0x1fffffff,0xff000000,00000000,
+0x01b9e000,0x0001b8c0,00000000,0x0fffff00,
+0x000fffff,00000000,00000000,0x00400000,
+0x00001000,0x00000004,00000000,0x01000000,
+0x0000ffff,0xfffffff0,00000000,0x0fffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xfff55ff5,0xffffffff,0xffffffff,0xf0000000,
+0xf0000010,0x00003c00,0x01760008,0x00025d80,
+0x02800417,0x6000c001,0x25d80038,0x04017600,
+0x0901025d,0x8002c044,0x176000d0,0x1125d800,
+0x3c2001f6,0x08080400,0x7d820203,0x001f6080,
+0x804027d8,0x20282009,0xf6080a0c,0x027d8202,
+0x81041f60,0x80c08107,0xd8203030,0x41f6080c,
+0x04127d82,0x0382049f,0x6080e0c1,0x27d82038,
+0x4006f608,0x081011bd,0x82030400,0xef6080a1,
+0x013bd820,0x384806f6,0x00081211,0xbd800304,
+0x80ef6000,0xa1213bd8,0x003bc007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x6fff0000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* big_ls
+ *
+ * ctr0:counts the total number of cycles for which local_stall_A1 is asserted.
+ * ctr1: is the overflow for counter 0.
+ * ctr2: counts IFLUSH_AV
+ * ctr3: is the overflow for counter 2.
+ */
+{
+0x0c000000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x0fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00029408,0x02f50002,0x0800bd40,
+0x0202802f,0x5000a000,0x4bd40004,0x0812f500,
+0x030804bd,0x40024281,0x2f5000b0,0x010bd400,
+0x100842f5,0x00060810,0xbd400302,0x842f5000,
+0xe0014bd4,0x00140852,0xf5000708,0x14bd4003,
+0x42852f50,0x00ff001f,0xffe003c0,0x07fff800,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x0df70000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* br_abort
+ *
+ * ctr0: counts BRAD_STALLH
+ * ctr1: counts ONE_QUAD
+ * ctr2: counts BR0_ABRT
+ * ctr3: counts BR1_ABRT
+ */
+{
+0x0c002000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x1fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x1a250000,00000000,0x10000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* isnt
+ *
+ * ctr0: counts the total number of cycles for which iside_notrans is asserted
+ * ctr1: counts the number of times iside_notrans is asserted for 1-4 cycles
+ * ctr2: counts the number of times iside_notrans is asserted for 5-7 cycles
+ * ctr3: counts the number of times iside_notrans is asserted for > 7 cycles
+ */
+{
+0x0c018000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xcfffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00021c20,0x03ff0808,0x1800ffc4,
+0x0204003f,0xf0004280,0x0ffc6020,0x8003ff00,
+0x043800ff,0xc8020c00,0x3ff00044,0x800ffca0,
+0x210003ff,0x00045800,0xffcc0214,0x003ff000,
+0x26800ffc,0xe0218003,0xff000278,0x00ffd002,
+0x1c003ff0,0x0028800f,0xfd002200,0x03ff0001,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0xcdff0000,00000000,0xc0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* quadrant
+ *
+ * ctr0: Total number of instructions in quadrant 0
+ * ctr1: Total number of instructions in quadrant 1
+ * ctr2: Total number of instructions in quadrant 2
+ * ctr3: Total number of instructions in quadrant 3
+ * Works only with 32-bit
+ */
+
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
+ 0x0101ffff, 0xfffff004, 0xe000407f, 0xfffffffc,
+ 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
+ 0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00,
+ 0x000fffff, 0x00000000, 0x00000000, 0x00ffffff,
+ 0xffcff000, 0x0000040f, 0xfffffffc, 0xff000000,
+ 0x0080ffff, 0xffffcff0, 0x0000000c, 0x0fffffff,
+ 0xfcff0000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xfff55ff5, 0x5fffffff, 0xffffffff, 0xf0000000,
+ 0xf00000f0, 0x00003c00, 0x007f0000, 0x01001fc0,
+ 0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00,
+ 0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00,
+ 0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000,
+ 0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003,
+ 0x438007f0, 0x00e0f001, 0xfc003fff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff},
+
+/* rw_pdfet (READ_PRIV transactions)
+ *
+ * ctr0: counts address valid cycles
+ * ctr1: counts *all* data valid cycles
+ * ctr2: is the overflow from counter 0
+ * ctr3: is the overflow from counter 1
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xf8000000,00000000,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff},
+
+/* rw_wdfet (WRITEBACKS)
+ *
+ * ctr0: counts address valid cycles
+ * ctr1: counts *all* data valid cycles
+ * ctr2: is the overflow from counter 0
+ * ctr3: is the overflow from counter 1
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0x98000000,00000000,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff},
+
+/* shlib_cpi
+ *
+ * ctr0: Total number of instructions in quad 0
+ * ctr1: Total number of CPU clock cycles in quad 0
+ * ctr2: total instructions without nullified
+ * ctr3: total number of CPU clock cycles
+ */
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
+ 0x0101ffff, 0xfffff004, 0xe000407f, 0xfffffffc,
+ 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
+ 0x00000fff, 0xff00000f, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0x00000000, 0x00000000, 0x00ffffff,
+ 0xffcff000, 0x0000000f, 0xfffffffc, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xfff77ff5, 0x7fffffff, 0xffffffff, 0xf0000000,
+ 0xf00000a0, 0x00003c00, 0x01ff0005, 0x08007fc0,
+ 0x03c1001f, 0xf08030c0, 0x07fc203c, 0x4001ff08,
+ 0x0118007f, 0xc003c500, 0x1ff08031, 0xc007fc00,
+ 0x3fffffff, 0xf800ffff, 0xfffe003f, 0xffffff80,
+ 0x0fffffff, 0xe003ffff, 0xfff800ff, 0xfffffe00,
+ 0x3fffffff, 0x800fffff, 0xffe003ff, 0xfffff800,
+ 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003,
+ 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f,
+ 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f,
+ 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff,
+ 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff},
+
+
+/* addr_inv_abort_alu
+ *
+ * ctr0: counts ABORT_ALU0L
+ * ctr1: counts ABORT_ALU1L
+ * ctr2: counts ADDR0_INVALID
+ * ctr3: counts ADDR1_INVALID
+ */
+
+{
+0x0c00c000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000d,0x01001fc0,
+0x03008007,0xf000f030,0x01fc0038,0x10007f00,
+0x0905001f,0xc0020180,0x07f000b0,0x7001fc00,
+0x2820007f,0x00050900,0x1fc00102,0x8007f000,
+0x70b001fc,0x00183000,0x7f00010d,0x001fc000,
+0x038007f0,0x0030f001,0xfc000bff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x65380000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+
+
+/* brad_stall
+ *
+ * ctr0: counts the total number of cycles for which brad_stall is asserted
+ * ctr1: counts the number of times brad_stall is asserted for 1-4 cycles
+ * ctr2: counts the number of times brad_stall is asserted for 5-7 cycles
+ * ctr3: counts the number of times brad_stall is asserted for > 7 cycles
+ */
+{
+0x0c002000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x1fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00021c20,0x03ff0808,0x1800ffc4,
+0x0204003f,0xf0004280,0x0ffc6020,0x8003ff00,
+0x043800ff,0xc8020c00,0x3ff00044,0x800ffca0,
+0x210003ff,0x00045800,0xffcc0214,0x003ff000,
+0x26800ffc,0xe0218003,0xff000278,0x00ffd002,
+0x1c003ff0,0x0028800f,0xfd002200,0x03ff0001,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x1bff0000,00000000,0x10000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* cntl_in_pipel
+ *
+ * ctr0: counts the total number of cycles for which cntl_in_pipel is asserted
+ * ctr1: counts the number of times cntl_in_pipel is asserted for 1-4 cycles
+ * ctr2: counts the number of times cntl_in_pipel is asserted for 5-7 cycles
+ * ctr3: counts the number of times cntl_in_pipel is asserted for > 7 cycles
+ */
+{
+0x0c006000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x3fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00021c00,0x03ff0808,0x1000ffc4,
+0x0206003f,0xf0004200,0x0ffc6020,0xa003ff00,
+0x043000ff,0xc8020e00,0x3ff00044,0x000ffca0,
+0x212003ff,0x00045000,0xffcc0216,0x003ff000,
+0x26000ffc,0xe021a003,0xff000270,0x00ffd002,
+0x1e003ff0,0x0028000f,0xfd002220,0x03ff0001,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x3fff0000,00000000,0x30000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+
+/* dsnt_xfh
+ *
+ * ctr0: counts dside_notrans
+ * ctr1: counts xfhang
+ * ctr2: is the overflow for ctr0
+ * ctr3: is the overflow for ctr1
+ */
+{
+0x0c018000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xcfffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00030000,0x01f30000,0x00087cc0,
+0x0040041f,0x30002001,0x87cc000c,0x1001f300,
+0x0404087c,0xc0014104,0x1f300060,0x4187cc00,
+0x1c2001f3,0x00080808,0x7cc00242,0x041f3000,
+0xa08187cc,0x002c3001,0xf3000c0c,0x087cc003,
+0x43041f30,0x00e0c187,0xcc003fc0,0x07fff800,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0xcb3f0000,00000000,0xc0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* fet_sig1
+ *
+ * ctr0: counts ICORE_AV
+ * ctr1: counts ITRANS_STALL
+ * ctr2: counts SEL_PCQH
+ * ctr3: counts OUT_OF_CONTEXT
+ */
+{
+0x0c000000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x0fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x07c10000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* fet_sig2
+ *
+ * ctr0: counts ICORE_AV
+ * ctr1: counts IRTN_AV
+ * ctr2: counts ADDRESS_INC
+ * ctr3: counts ADDRESS_DEC
+ */
+{
+0x0c000000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x0fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x06930000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* g7_1
+ *
+ * ctr0: counts HIT_RETRY0
+ * ctr1: counts HIT_RETRY1
+ * ctr2: counts GO_TAG_E
+ * ctr3: counts GO_TAG_O
+ */
+{
+0x0c00e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x7fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x71c10000,00000000,0x70000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* g7_2
+ *
+ * ctr0: counts HIT_DM0
+ * ctr1: counts HIT_DM1
+ * ctr2: counts GO_STORE_E
+ * ctr3: counts GO_STORE_O
+ */
+{
+0x0c00e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x7fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x72930000,00000000,0x70000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* g7_3
+ *
+ * ctr0: counts HIT_DV0
+ * ctr1: counts HIT_DV1
+ * ctr2: counts STBYPT_E (load bypasses from store queue)
+ * ctr3: counts STBYPT_O
+ */
+{
+0x0c00e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x7fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f0002,0x01001fc0,
+0x00c08007,0xf0000030,0x01fc0004,0x10007f00,
+0x0605001f,0xc001c180,0x07f00040,0x7001fc00,
+0x1420007f,0x000a0900,0x1fc002c2,0x8007f000,
+0x80b001fc,0x00243000,0x7f000e0d,0x001fc003,
+0xc38007f0,0x00c0f001,0xfc0037ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x77250000,00000000,0x70000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* g7_4
+ *
+ * ctr0: counts HIT_DIRTY0
+ * ctr1: counts HIT_DIRTY1
+ * ctr2: counts CA_BYP_E (quick launch)
+ * ctr3: counts CA_BYP_O
+ */
+{
+0x0c00e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x7fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x7bb70000,00000000,0x70000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+
+/* mpb_labort
+ *
+ * ctr0: counts L_ABORT_ALU0L
+ * ctr1: counts L_ABORT_ALU1L
+ * ctr2: counts MPB0H
+ * ctr3: counts MPB1H
+ */
+{
+0x0c00c000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x605c0000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* panic
+ *
+ * ctr0: is the overflow for counter 1
+ * ctr1: counts traps and RFI's
+ * ctr2: counts panic traps
+ * ctr3: is the overflow for counter 2
+ */
+{
+0x0c002000,00000000,0x00060000,00000000,
+0xe7efe0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffffc,
+0x41380030,0x1aabfff2,0x17000000,00000000,
+0x01b80000,0x3effffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,00000000,0x00400000,
+0x00001fff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x1fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+0xb0000000,0x00012c04,0x05790804,0x14013e44,
+0x0008004f,0x90000040,0x15e46000,0xc0047920,
+0x004a003e,0x40011080,0x0f900024,0x4003e460,
+0x00c80479,0x00023301,0x1e400100,0x4157d080,
+0x514053f4,0x40048014,0xfd000104,0x055f4600,
+0x4c0147d2,0x0014a043,0xf4001508,0x10fd0003,
+0x44043f46,0x004c8147,0xd0003330,0x51f40014,
+0x04257908,0x0c14093e,0x44020802,0x4f900080,
+0x4095e460,0x20c02479,0x20084a08,0x3e400310,
+0x820f9000,0xa44083e4,0x6020c824,0x79000a33,
+0x091e4003,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x10400000,00000000,0x10000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* rare_inst
+ *
+ * ctr0: counts sync and syncdma instructions
+ * ctr1: counts pxtlbx,x instructions
+ * ctr2: counts ixtlbt instructions
+ * ctr3: counts cycles
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0x004e000c,0x000843fc,0x85c09380,
+0x0121ebfd,0xff217124,0xe0004000,0x943fc85f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xe00000e0,0x00003c00,0x007f0001,0x01001fc0,
+0x00408007,0xf0003030,0x01fc000c,0x10007f00,
+0x0505001f,0xc0014180,0x07f00070,0x7001fc00,
+0x1c20007f,0x00090900,0x1fc00242,0x8007f000,
+0xb0b001fc,0x002c3000,0x7f000d0d,0x001fc003,
+0x438007f0,0x00f0f001,0xfc003fff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* rw_dfet (for D-cache misses and writebacks)
+ *
+ * ctr0: counts address valid cycles
+ * ctr1: counts *all* data valid cycles
+ * ctr2: is the overflow from counter 0
+ * ctr3: is the overflow from counter 1
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xf0000000,00000000,
+00000000,00000000,0x98000000,00000000,
+0xffffffff,0xffffffff,0x0fffffff,0xffffffff,
+00000000,00000000,0x00ffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* rw_ifet (I-cache misses -- actually dumb READ transactions)
+ *
+ * ctr0: counts address valid cycles
+ * ctr1: counts *all* data valid cycles
+ * ctr2: is the overflow from counter 0
+ * ctr3: is the overflow from counter 1
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xd0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+0xffffffff,0xffffffff,00000000,00000000,
+0xffffffff,0xffffffff },
+
+
+/* rw_sdfet (READ_SHARED_OR_PRIVATE transactions)
+ *
+ * ctr0: counts address valid cycles
+ * ctr1: counts *all* data valid cycles
+ * ctr2: is the overflow from counter 0
+ * ctr3: is the overflow from counter 1
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xf4000000,00000000,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff },
+
+
+/* spec_ifet
+ *
+ * ICORE_AV fires for every request which the Instruction Fetch Unit sends
+ * to the Runway Interface Block. Hence, this counts all I-misses, speculative
+ * or not, but does *not* include I-cache prefetches, which are generated by
+ * RIB.
+ * IRTN_AV fires twice for every I-cache miss returning from RIB to the IFU.
+ * It will not fire if a second I-cache miss is issued from the IFU to RIB
+ * before the first returns. Therefore, if the IRTN_AV count is much less
+ * than 2x the ICORE_AV count, many speculative I-cache misses are occurring
+ * which are "discovered" to be incorrect fairly quickly.
+ * The ratio of I-cache miss transactions on Runway to the ICORE_AV count is
+ * a measure of the effectiveness of instruction prefetching. This ratio
+ * should be between 1 and 2. If it is close to 1, most prefetches are
+ * eventually called for by the IFU; if it is close to 2, almost no prefetches
+ * are useful and they are wasted bus traffic.
+ *
+ * ctr0: counts ICORE_AV
+ * ctr1: counts IRTN_AV
+ * ctr2: counts all non-coherent READ transactions on Runway. (TTYPE D0)
+ * This should be just I-cache miss and I-prefetch transactions.
+ * ctr3: counts total processor cycles
+ */
+{
+0x0c000000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x0fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x00000008,0x00030c00,0x01bf0001,0x00806fc0,
+0x00c1001b,0xf0005048,0x06fc001c,0x2001bf00,
+0x0908806f,0xc002c300,0x1bf000d0,0xc806fc00,
+0x3fffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0x06bf0000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00110000,00000000,0xd0ffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+0xffffffff,0xffffffff,00000000,00000000,
+0xffffffff,0xffffffff },
+
+/* st_cond0
+ *
+ * ctr0: is the overflow for ctr1
+ * ctr1: counts major ops 0C and 0E (fp ops, not fmac or fmpyadd)
+ * ctr2: counts B,L (including long and push) and GATE (including nullified),
+ * predicted not-taken
+ * ctr3: is the overflow for ctr2
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc13380,
+0x0101ffff,0xffa1f057,0xe000407f,0xdfffc87f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_cond1
+ *
+ * ctr0: is the overflow for ctr1
+ * ctr1: counts major ops 1x (most of the load/stores)
+ * ctr2: counts CMPB (dw) predicted not-taken
+ * ctr3: is the overflow for ctr2
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc01b80,
+0x0101ffff,0xffb7f03d,0xe000407f,0xffffc8ff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_cond2
+ *
+ * ctr0: is the overflow for ctr1
+ * ctr1: counts major op 03
+ * ctr2: counts CMPIB (dw) predicted not taken.
+ * ctr3: is the overflow for ctr2
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc09780,
+0x0101ffff,0xff21f077,0xe000407f,0xffffc87f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_cond3
+ *
+ * ctr0: is the overflow for ctr1
+ * ctr1: counts major ops 06 & 26
+ * ctr2: counts BB, BVB, MOVB, MOVIB (incl. nullified) predicted not-taken
+ * ctr3: is the overflow for ctr2
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc03780,
+0x0101ffff,0xff29f016,0xe000407f,0xffffe97f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_cond4
+ *
+ * ctr0: is the overflow for ctr1
+ * ctr1: counts major op 2E
+ * ctr2: counts CMPB, CMPIB, ADDB, ADDIB (incl. nullified) predicted not-taken
+ * ctr3: is the overflow for ctr2
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc17780,
+0x0101ffff,0xff21f014,0xe000407f,0xffffe9ff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_unpred0
+ *
+ * ctr0: is the overflow for ctr1
+ * ctr1: counts BE and BE,L
+ * ctr2: counts BE and BE,L including nullified
+ * ctr3: is the overflow for ctr2
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0c0c0e0,0xffffffff,0xffffffff,0xffdf5bbf,
+0xffffffff,0xff25f7d6,0xefffffff,0xffffc97f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_unpred1
+ *
+ * ctr0: is the overflow for ctr1
+ * ctr1: counts BLR, BV, BVE, BVE,L
+ * ctr2: counts BLR, BV, BVE, BVE,L including nullified
+ * ctr3: is the overflow for ctr2
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0c0c0e0,0xffffffff,0xffffffff,0xffc15f80,
+0x0501ff7f,0xff21f057,0xe001407f,0xdfffc87f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* unpred
+ *
+ * ctr0: counts non-nullified unpredictable branches
+ * ctr1: is the overflow for ctr0
+ * ctr2: counts all unpredictable branches (nullified or not)
+ * ctr3: is the overflow for ctr2
+ */
+{
+0xcc01e000,00000000,0x00060000,00000000,
+0x20202020,0xff31ffff,0xfff7fffe,0x97ffcc7f,
+0xfffffdff,0xffa5fff3,0x1fffffff,0x7fffe97f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf00000a0,0x00003c00,0x02f50000,0x0004bd40,
+0x0040802f,0x50002020,0x4bd4000c,0x0042f500,
+0x040014bd,0x40014084,0x2f500060,0x214bd400,
+0x1c2002f5,0x00080804,0xbd400242,0x802f5000,
+0xa0a04bd4,0x002c2042,0xf5000c08,0x14bd4003,
+0x42842f50,0x00e0a14b,0xd4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+
+/* go_store
+ *
+ * ctr0: Overflow for counter 2
+ * ctr1: Overflow for counter 3
+ * ctr2: count of GO_STORE_E signal
+ * ctr3: count of GO_STORE_O signal
+ */
+
+ {
+ 0x0c00e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffa5ffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x7fffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
+ 0x00000000, 0x0000c000, 0x067c0000, 0x01019f00,
+ 0x00408067, 0xc0002030, 0x19f0000c, 0x000e7c00,
+ 0x0401039f, 0x00014080, 0xe7c00060, 0x3039f000,
+ 0x1c00167c, 0x00080105, 0x9f000240, 0x8167c000,
+ 0xa03059f0, 0x002c001e, 0x7c000c01, 0x079f0003,
+ 0x4081e7c0, 0x00e03079, 0xf0003fc0, 0x07fff800,
+ 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003,
+ 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f,
+ 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c,
+ 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0,
+ 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x70130000, 0x00000000, 0x70000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff
+ },
+
+
+/* shlib_call
+ *
+ * ctr0: SharedLib call Depth1
+ * ctr1: SharedLib call Depth2
+ * ctr2: SharedLib call Depth3
+ * ctr3: SharedLib call Depth>3
+ */
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0xc76fa005, 0x07dd7e9c, 0x87115b80,
+ 0x01100200, 0x07200004, 0xe000407f, 0xfffffffc,
+ 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
+ 0xf0000000, 0x00003c20, 0x01ff0808, 0x04007fc0,
+ 0x0003001f, 0xf0000180, 0x07fc4010, 0x5001ff00,
+ 0x001c007f, 0xc2000a00, 0x1ff18022, 0x4007fc20,
+ 0x00b001ff, 0x10003800, 0x7fc8004d, 0x001ff100,
+ 0x03c007fc, 0x60012001, 0xff280144, 0x007fc600,
+ 0x13001ff2, 0x00058007, 0xfcc00550, 0x01ff2000,
+ 0x5c007fca, 0x001a001f, 0xf3801640, 0x07fca001,
+ 0xb001ff30, 0x0078007f, 0xd0005d00, 0x1ff30007,
+ 0xc007fce0, 0x022001ff, 0x48018400, 0x7fce0023,
+ 0x001ff400, 0x098007fd, 0x20065001, 0xff40009c,
+ 0x007fd200, 0x3fffffff, 0x800fffff, 0xffe00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+ 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+ 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff
+ }
+};
+#define PCXW_IMAGE_SIZE 576
+
+static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] = {
+/*
+ * CPI: FROM CPI.IDF (Image 0)
+ *
+ * Counts the following:
+ *
+ * ctr0 : total cycles
+ * ctr1 : total cycles where nothing retired
+ * ctr2 : total instructions retired, including nullified
+ * ctr3 : total instructions retired, less nullified instructions
+ */
+ {
+ 0x4c00c000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
+ 0xffffc000, 0x07ffff00, 0x07ffffff, 0x6007ffff,
+ 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000,
+ 0x60f00000, 0x0fffff00, 0x000fffff, 0x00000fff,
+ 0xff00000f, 0xffff0000, 0x00000000, 0x00ffffff,
+ 0xfffff000, 0x0000000f, 0xffffffff, 0xff000000,
+ 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00270000, 0x00000055,
+ 0x0200000e, 0x4d300000, 0x00000000, 0x0ff00002,
+ 0x70000000, 0x00000020, 0x0000e400, 0x00000ff0,
+ 0x00000000, 0x00000000, 0x00000055, 0xffffff00,
+ 0x00000000, 0x0000ff00, 0x00000000, 0x0f000000,
+ 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
+ 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
+ 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000,
+ 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
+ 0x00000000, 0x00000000, 0x00055fff, 0xfff00000,
+ 0x00000000, 0x0ff00000, 0x00000030, 0x00000000,
+ 0x00157fff, 0xffc00000, 0x034c0000, 0x00000000,
+ 0x03fc0000, 0x00000000, 0x6fff0000, 0x00000000,
+ 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* Bus utilization image FROM BUS_UTIL.IDF (Image 1)
+ *
+ * ctr0 : counts address valid cycles
+ * ctr1 : counts data valid cycles
+ * ctr2 : counts overflow from counter 0
+ * ctr3 : counts overflow from counter 1
+ */
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00001b00, 0xaa000000,
+ 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000,
+ 0x01b00000, 0x00000000, 0x00001037, 0x00000000,
+ 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000,
+ 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
+ 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
+ 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff,
+ 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
+ 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5,
+ 0x40000000, 0x00000000, 0x731c0000, 0x000156ab,
+ 0xfc000000, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00100000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/*
+ * TLB counts: FROM TLBSTATS.IDF (Image 2)
+ *
+ * Counts the following:
+ *
+ * ctr0: DTLB misses
+ * ctr1: ITLB misses
+ * ctr2: total cycles in the miss handlers
+ * ctr3: total cycles
+ */
+
+ {
+ 0x0c00c000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
+ 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff,
+ 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000,
+ 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff,
+ 0xff00000f, 0xffff0000, 0x00000000, 0x00400000,
+ 0x00001000, 0x00000004, 0x00000000, 0x01000000,
+ 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00800000, 0x00153f7f,
+ 0x55000000, 0xaf800000, 0xc0000000, 0x0403f240,
+ 0x00000000, 0x00001010, 0x00004700, 0x00000ff0,
+ 0x00000000, 0x00000000, 0x00000055, 0xffffff00,
+ 0x00000000, 0x0000ff00, 0x00000000, 0x0f000000,
+ 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
+ 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
+ 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000,
+ 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
+ 0x00000000, 0x00000000, 0x00055fff, 0xfff00000,
+ 0x00000000, 0x0ff00000, 0x00000000, 0x00000000,
+ 0x00157fff, 0xffc00000, 0x00000000, 0x3fc00000,
+ 0x00040000, 0x00000000, 0x6fff0000, 0x00000000,
+ 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* tlbhandler FROM tlbHandMiss.idf (Image 3)
+ *
+ * ctr0: TLB misses
+ * ctr1: dmisses inside the TLB miss handler
+ * ctr2: cycles in the TLB miss handler
+ * ctr3: overflow of ctr2
+ */
+ {
+ 0x1c00c000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
+ 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff,
+ 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000,
+ 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff,
+ 0xff00000f, 0xffff0000, 0x00000000, 0x00400000,
+ 0x00001000, 0x00000004, 0x00000000, 0x01000000,
+ 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x006c0000, 0x01000054,
+ 0x02000002, 0xc3200000, 0xc00aa000, 0x0c03f240,
+ 0x00000000, 0x00001010, 0x000044f4, 0x00000c00,
+ 0xaa0000f0, 0x0f0000b0, 0x00005005, 0x0f5f0000,
+ 0x0001f000, 0x0000ff00, 0x00000000, 0x0f000000,
+ 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
+ 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
+ 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000,
+ 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
+ 0x00000000, 0x00000000, 0x00055fff, 0xfff00000,
+ 0x00000000, 0x0ff00a00, 0x000f0000, 0x24004000,
+ 0x15400001, 0x40c00003, 0x3da00000, 0x0002a800,
+ 0x00ff0000, 0x00000000, 0x6fff0000, 0x00000000,
+ 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* branch_taken image FROM PTKN.IDF (Image 4)
+ *
+ * ctr0: mispredicted branches
+ * ctr1: predicted taken branches, actually taken
+ * ctr2: predicted taken branches (includes nullfied)
+ * ctr3: all branches
+ */
+
+ {
+ 0xcc01e000, 0x00000000, 0x00000000, 0x00000000,
+ 0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xfffffeff, 0xfffeffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
+ 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
+ 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
+ 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
+ 0x000dbfff, 0xffffff00, 0x00000000, 0x0f0fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
+ 0x00000000, 0x00000002, 0x67840000, 0x00000000,
+ 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* branch_nottaken FROM PNTKN.IDF (Image 5)
+ *
+ * ctr0: mispredicted branches
+ * ctr1: branches predicted not-taken, but actually taken
+ * ctr2: branches predicted not-taken (includes nullified)
+ * ctr3: all branches
+ */
+ {
+ 0xcc01e000, 0x00000000, 0x00000000, 0x00000000,
+ 0xe0c0c0e0, 0xffffffff, 0xffffffff, 0xffefffff,
+ 0xffffbfff, 0xfffffeff, 0xfffeffff, 0xfffffeff,
+ 0xfffffffe, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
+ 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
+ 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
+ 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
+ 0x000dbfff, 0xffffff00, 0x00000000, 0x0f0fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
+ 0x00000000, 0x00000002, 0x67840000, 0x00000000,
+ 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* IMISS image (Image 6)
+ *
+ * ctr0 : icache misses for retired instructions
+ * ctr1 : total cycles
+ * ctr2 : dcache misses for retired instructions
+ * ctr3 : number of retired instructions
+ */
+ {
+ 0x2801e000, 0x00000000, 0x00010000, 0x00000000,
+ 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff,
+ 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0,
+ 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800,
+ 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0,
+ 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555,
+ 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf,
+ 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000,
+ 0x03c14000, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* DMISS image (Image 7)
+ *
+ * ctr0 : icache misses for retired instructions
+ * ctr1 : total cycles
+ * ctr2 : dcache misses for retired instructions
+ * ctr3 : number of retired instructions
+ */
+ {
+ 0x2801e000, 0x00000000, 0x00010000, 0x00000000,
+ 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff,
+ 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0,
+ 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800,
+ 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0,
+ 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555,
+ 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf,
+ 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000,
+ 0x03c14000, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* dmiss_access image FROM DMISS_RATIO.IDF (Image 8)
+ *
+ * ctr0 : all loads and stores that retire (even lines)
+ * ctr1 : all loads and stores that retire (odd lines)
+ * ctr2 : dcache misses of retired loads/stores
+ * ctr3 : all READ_PRIV and READ_SHAR_OR_PRIV on Runway
+ * (Speculative and Non-Speculative)
+ */
+ {
+ 0x2d81e000, 0x00000000, 0x00000000, 0x00000000,
+ 0x10101010, 0x00ffffff, 0xa003ffff, 0xfe800fff,
+ 0xfffa003f, 0xffffe8ff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xd2280a00, 0x00000000,
+ 0x0000000b, 0x46000000, 0x00000005, 0x555ff900,
+ 0x80200000, 0x00000000, 0x0000907e, 0x00000000,
+ 0x00005555, 0xff80bf8b, 0xab030303, 0x03030000,
+ 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffff5555, 0x55500000, 0x15153fe0, 0x27628880,
+ 0x00000000, 0x00000002, 0x67840000, 0x00000001,
+ 0x5557fc00, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00110000, 0x00000000,
+ 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xf8ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+
+/* big_cpi image (Image 9)
+ *
+ * ctr0 : Total number of CPU clock cycles.
+ * ctr1 : Unused
+ * ctr2 : Unused
+ * ctr3 : Total number of Non-Nullified instructions retired.
+ */
+ {
+ 0x0c00c000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
+ 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff,
+ 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000,
+ 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff,
+ 0xff00000f, 0xffff0000, 0x00000000, 0x00400000,
+ 0x00001000, 0x00000004, 0x00000000, 0x01000000,
+ 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00550005, 0x00220000,
+ 0x0000000c, 0x71f00000, 0x00f00aa0, 0x0aaff000,
+ 0x00005002, 0x20000000, 0x0000c413, 0x00000c0f,
+ 0x00aa0000, 0xff00b600, 0x000500a0, 0x00000300,
+ 0x000cc3f0, 0x0000c0f0, 0x0aa0000f, 0xff000000,
+ 0x011000a0, 0x05503000, 0x00d03700, 0x00000f00,
+ 0xaa005500, 0x00000000, 0x000055ff, 0xffff0000,
+ 0x00000000, 0x00ff0000, 0x00000000, 0xf000aa00,
+ 0x11000a00, 0x55000000, 0x0d037000, 0x00c0f00a,
+ 0xa0055000, 0x0db00005, 0x5002a000, 0x00300000,
+ 0xf40f0000, 0x0c0f00aa, 0x0000ff10, 0x27400000,
+ 0x00008000, 0x00c00003, 0x037c0000, 0x003c02a8,
+ 0x02abfc00, 0x00000000, 0x6fff0000, 0x00000000,
+ 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* big_ls image (Image 10)
+ *
+ * ctr0 : Total number of CPU clock cycles during which local_stall_A1 is asserted
+ * ctr1 : Overflow of Counter 0
+ * ctr2 : Total number of IFLUSH_AV
+ * ctr3 : Overflow of Counter 2
+ */
+ {
+ 0x0c000000, 0x00000000, 0x00060000, 0x00000000,
+ 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x28880001, 0x54000000,
+ 0x00000004, 0xb6200000, 0x000aaaa0, 0x05555288,
+ 0x80000010, 0x00000000, 0x0000486e, 0x00000000,
+ 0xaaaa0055, 0x55002888, 0x00545401, 0x03030000,
+ 0x0007b000, 0x0000ff00, 0x00000000, 0x05000000,
+ 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
+ 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
+ 0x00000000, 0x00ff0000, 0x00000000, 0x00000000,
+ 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
+ 0x00000000, 0xa0000000, 0x00055fff, 0xfff00000,
+ 0x00aa0000, 0x05502a2a, 0x00151500, 0x0a220015,
+ 0x40400000, 0x00000001, 0xe2980000, 0x0002aaa8,
+ 0x01555400, 0x00000000, 0x0df70000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* br_abort image (Image 12)
+ *
+ * ctr0 : Total number of BRAD_STALLH
+ * ctr1 : Total number of ONE_QUAD
+ * ctr2 : Total number of BR0_ABRT
+ * ctr3 : Total number of BR1_ABRT
+ */
+
+ {
+ 0x0c002000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xff0fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0x1077ffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x551b0000, 0x00000000,
+ 0x0000000c, 0xd4f00000, 0x00000000, 0x0ffff001,
+ 0xb0000000, 0x00000000, 0x0000fd4c, 0x00000000,
+ 0x000000ff, 0xff00ff1b, 0x00000000, 0x00000000,
+ 0x0000d000, 0x0000ff00, 0x00000000, 0x0e0fffff,
+ 0xffffffff, 0xfffff000, 0x00000000, 0x000ff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x00ff0000, 0x00000000, 0x00ffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0x00ff0000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0xfff00000,
+ 0x00400000, 0x00000000, 0x00ffff00, 0x2a86c000,
+ 0x00000000, 0x00000000, 0xf50c0000, 0x00000000,
+ 0x03fffc00, 0x00000000, 0x1a250000, 0x00000000,
+ 0x10000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+
+/* isnt image (Image 13)
+ *
+ * ctr0 : Total number of cycles for which iside_notrans is asserted.
+ * ctr1 : Total number of times iside_notrans is asserted for 1-4 cycles.
+ * ctr2 : Total number of times iside_notrans is asserted for 5-7 cycles.
+ * ctr3 : Total number of times iside_notrans is asserted for > 7 cycles.
+ */
+
+ {
+ 0x0c018000, 0x00000000, 0x00060000, 0x00000000,
+ 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xc0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x22000000, 0x000001bc,
+ 0x10000006, 0x00900000, 0x50000000, 0x00055a20,
+ 0x00000000, 0x00016060, 0x0000c021, 0x00000540,
+ 0x00000000, 0x55002200, 0x00000000, 0x56bc4000,
+ 0x00048000, 0x0000ff00, 0x00000000, 0x17000000,
+ 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
+ 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
+ 0x00000000, 0x00ff0000, 0x00000000, 0x00000000,
+ 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
+ 0x00000000, 0x80000000, 0x00015bf3, 0xf5500000,
+ 0x02210000, 0x00100000, 0x00005500, 0x08800000,
+ 0x00001545, 0x85000001, 0x80240000, 0x11000000,
+ 0x00015400, 0x00000000, 0xcdff0000, 0x00000000,
+ 0xc0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* quadrant image (image 14)
+ *
+ * ctr0 : Total number of instructions in quadrant 0.
+ * ctr1 : Total number of instructions in quadrant 1.
+ * ctr2 : Total number of instructions in quadrant 2.
+ * ctr3 : Total number of instructions in quadrant 3.
+ *
+ * Only works for 32-bit applications.
+ */
+
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
+ 0xffffc000, 0x07ffff00, 0x07ffffff, 0x0007ffff,
+ 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000,
+ 0xf0000000, 0x0fffff00, 0x000fffff, 0x00000fff,
+ 0xff00000f, 0xffff0000, 0x00000000, 0x00ffffff,
+ 0xffcff000, 0x0000040f, 0xfffffffc, 0xff000000,
+ 0x0080ffff, 0xffffcff0, 0x0000000c, 0x0fffffff,
+ 0xfcff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x551b0000, 0x00000000,
+ 0x00000003, 0x17000000, 0x00000000, 0x0ffff001,
+ 0xb0000000, 0x00000000, 0x00000173, 0x00000000,
+ 0x000000ff, 0xff00ff1b, 0x00000000, 0x00000000,
+ 0x000f1ff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
+ 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
+ 0x0ffff0cf, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
+ 0xff7f0000, 0x00000000, 0x00fffff0, 0x2a86c000,
+ 0x00000000, 0x00000003, 0x05f00000, 0x00000000,
+ 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* rw_pdfet image (Image 15)
+ *
+ * ctr0 : Total of all READ_PRIV address valid cycles.
+ * ctr1 : Total of all READ_PRIV data valid cycles.
+ * ctr2 : Overflow of Counter 0.
+ * ctr3 : Overflow of Counter 1.
+ */
+
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00001b00, 0xaa000000,
+ 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000,
+ 0x01b00000, 0x00000000, 0x00001037, 0x00000000,
+ 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000,
+ 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
+ 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
+ 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff,
+ 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
+ 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5,
+ 0x40000000, 0x00000000, 0x731c0000, 0x000156ab,
+ 0xfc000000, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00100000, 0x00000000,
+ 0xf8000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00ffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ },
+
+
+/* rw_wdfet image (Image 16)
+ *
+ * ctr0 : Counts total number of writeback transactions.
+ * ctr1 : Total number of data valid Runway cycles.
+ * ctr2 : Overflow of Counter 0.
+ * ctr3 : Overflow of Counter 1.
+ */
+
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00001b00, 0xaa000000,
+ 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000,
+ 0x01b00000, 0x00000000, 0x00001037, 0x00000000,
+ 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000,
+ 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
+ 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
+ 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff,
+ 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
+ 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5,
+ 0x40000000, 0x00000000, 0x731c0000, 0x000156ab,
+ 0xfc000000, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00100000, 0x00000000,
+ 0x98000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00ffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ },
+
+/* shlib_cpi image (Image 17)
+ *
+ * ctr0 : Total number of instructions in quadrant 0.
+ * ctr1 : Total number of CPU clock cycles in quadrant 0.
+ * ctr2 : Total number of Non-Nullified instructions retired.
+ * ctr3 : Total number of CPU clock cycles.
+ *
+ * Only works for 32-bit shared libraries.
+ */
+
+ {
+ 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+ 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
+ 0xffffc000, 0x07ffff00, 0x07ffffff, 0x0007ffff,
+ 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000,
+ 0xf0150000, 0x0fffff00, 0x000fffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0x00ffffff,
+ 0xffcff000, 0x0000000f, 0xfffffffc, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x27000000, 0x00000055,
+ 0x02000005, 0x7f500000, 0xc0000000, 0x000ff270,
+ 0x00000000, 0x00000000, 0x00007700, 0x00000ff0,
+ 0x00000000, 0x0000ffff, 0xffffffff, 0xffffff00,
+ 0x00000000, 0x0000ff00, 0x00000000, 0x0f0fffff,
+ 0xffffffff, 0xfffff000, 0x00000000, 0x000ff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x00ff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0x00ff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xfff00000,
+ 0x00000000, 0x0ff00000, 0x000000a0, 0x3fffffff,
+ 0xffffffff, 0xffc00000, 0x03d40000, 0x20000000,
+ 0x0003fc00, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* flop image (Image 18)
+ *
+ * ctr0 : Total number of floating point instructions (opcode = 0xc).
+ * ctr1 : Total number of floating point instructions (opcode = 0xe, 0x6, 0x2e, 0x26).
+ * ctr2 : Unused
+ * ctr3 : Unused
+ */
+
+ {
+ 0x0001e000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00001010, 0x33ffffff, 0x006fffff, 0xfc5fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
+ 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
+ 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
+ 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
+ 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
+ 0x00000000, 0x00000002, 0x67840000, 0x00000000,
+ 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* cachemiss image FROM I_D_MISSES.IDF (Image 19)
+ *
+ * ctr0 : icache misses for retired instructions
+ * ctr1 : total cycles
+ * ctr2 : dcache misses for retired instructions
+ * ctr3 : number of retired instructions
+ */
+ {
+ 0x2801e000, 0x00000000, 0x00010000, 0x00000000,
+ 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff,
+ 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0,
+ 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800,
+ 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0,
+ 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555,
+ 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf,
+ 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000,
+ 0x03c14000, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* branch FROM br_report3.idf
+ *
+ * ctr0 : Total number of mispredicted branches.
+ * ctr1 : Some Non-Nullified unpredictable branches.
+ * ctr2 : Total number of branches (Nullified + Non-Nullified)
+ * (Unpredicted+ Predicted Taken +Predicted Not Taken).
+ * Total of All Branches.
+ * ctr3 : Remaining Non-Nullified unpredictable branches.
+ */
+ {
+ 0x4001e000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xffffffff, 0xff9fffff, 0xfe0fffff,
+ 0xffffbaff, 0xfdffc0ff, 0xfffdffff, 0xfffffeff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
+ 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
+ 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
+ 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
+ 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
+ 0x00000000, 0x00000002, 0x67840000, 0x00000000,
+ 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* crstack FROM crs_report.idf
+ *
+ * ctr0: correctly predicted branches by the pop_latch
+ * ctr1: some procedure returns
+ * ctr2: all branches, (includes nullified)
+ * ctr3: remaining procedure returns
+ */
+ {
+ 0x4001e000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffa10300, 0x000fffff,
+ 0xffffbaf8, 0x3000007f, 0xffffffff, 0xfffffeff,
+ 0xff7fffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0xf2ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
+ 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
+ 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
+ 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
+ 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
+ 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
+ 0x00000000, 0x00000002, 0x67840000, 0x00000000,
+ 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
+ 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ },
+
+/* icache_report image
+ *
+ * ctr0 : Icache misses actually used by the core.
+ * ctr1 : ICORE_AV (Icache misses the core THINKS it needs, including fetching down speculative paths).
+ * ctr2 : READs on Runway (Icache misses that made it out to Runway, including
+ * prefetches).
+ * ctr3 : Prefetch returns (1x and 2x).
+ */
+ {
+ 0x00000000, 0x00000000, 0x00010000, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+ 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xd2002d00, 0x00000000,
+ 0x0000000b, 0x46000000, 0x0000000f, 0xf00ff900,
+ 0x00900000, 0x00000000, 0x0000907e, 0x00000000,
+ 0x0000ff00, 0xff83bf03, 0xdf030303, 0x03030000,
+ 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
+ 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffff0000, 0x00000000, 0x80ffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
+ 0x00000000, 0x4fffffff, 0xffffffff, 0xffffffff,
+ 0xffff5555, 0x55500000, 0x3f003f80, 0x274026c0,
+ 0x00000000, 0x00000002, 0x67840000, 0x00000003,
+ 0xfc03fc00, 0x00000000, 0x0eff0000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+ 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
+ 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+ 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
+ 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+ 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+ 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
+ 0xd0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+
+ }
+
+};
+
+#endif
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
new file mode 100644
index 000000000000..46e4a6881f11
--- /dev/null
+++ b/arch/parisc/kernel/process.c
@@ -0,0 +1,396 @@
+/*
+ * PARISC Architecture-dependent parts of process handling
+ * based on the work for i386
+ *
+ * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
+ * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
+ * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
+ * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org>
+ * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
+ * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
+ * Copyright (C) 2000 David Kennedy <dkennedy with linuxcare.com>
+ * Copyright (C) 2000 Richard Hirst <rhirst with parisc-lixux.org>
+ * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
+ * Copyright (C) 2001 Alan Modra <amodra at parisc-linux.org>
+ * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
+ * Copyright (C) 2001-2002 Helge Deller <deller at parisc-linux.org>
+ * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdarg.h>
+
+#include <linux/elf.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/personality.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/kallsyms.h>
+
+#include <asm/io.h>
+#include <asm/offsets.h>
+#include <asm/pdc.h>
+#include <asm/pdc_chassis.h>
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+#include <asm/unwind.h>
+
+static int hlt_counter;
+
+/*
+ * Power off function, if any
+ */
+void (*pm_power_off)(void);
+
+void disable_hlt(void)
+{
+ hlt_counter++;
+}
+
+EXPORT_SYMBOL(disable_hlt);
+
+void enable_hlt(void)
+{
+ hlt_counter--;
+}
+
+EXPORT_SYMBOL(enable_hlt);
+
+void default_idle(void)
+{
+ barrier();
+}
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ while (1) {
+ while (!need_resched())
+ barrier();
+ schedule();
+ check_pgt_cache();
+ }
+}
+
+
+#ifdef __LP64__
+#define COMMAND_GLOBAL 0xfffffffffffe0030UL
+#else
+#define COMMAND_GLOBAL 0xfffe0030
+#endif
+
+#define CMD_RESET 5 /* reset any module */
+
+/*
+** The Wright Brothers and Gecko systems have a H/W problem
+** (Lasi...'nuf said) may cause a broadcast reset to lockup
+** the system. An HVERSION dependent PDC call was developed
+** to perform a "safe", platform specific broadcast reset instead
+** of kludging up all the code.
+**
+** Older machines which do not implement PDC_BROADCAST_RESET will
+** return (with an error) and the regular broadcast reset can be
+** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET
+** the PDC call will not return (the system will be reset).
+*/
+void machine_restart(char *cmd)
+{
+#ifdef FASTBOOT_SELFTEST_SUPPORT
+ /*
+ ** If user has modified the Firmware Selftest Bitmap,
+ ** run the tests specified in the bitmap after the
+ ** system is rebooted w/PDC_DO_RESET.
+ **
+ ** ftc_bitmap = 0x1AUL "Skip destructive memory tests"
+ **
+ ** Using "directed resets" at each processor with the MEM_TOC
+ ** vector cleared will also avoid running destructive
+ ** memory self tests. (Not implemented yet)
+ */
+ if (ftc_bitmap) {
+ pdc_do_firm_test_reset(ftc_bitmap);
+ }
+#endif
+ /* set up a new led state on systems shipped with a LED State panel */
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
+
+ /* "Normal" system reset */
+ pdc_do_reset();
+
+ /* Nope...box should reset with just CMD_RESET now */
+ gsc_writel(CMD_RESET, COMMAND_GLOBAL);
+
+ /* Wait for RESET to lay us to rest. */
+ while (1) ;
+
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void machine_halt(void)
+{
+ /*
+ ** The LED/ChassisCodes are updated by the led_halt()
+ ** function, called by the reboot notifier chain.
+ */
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+
+/*
+ * This routine is called from sys_reboot to actually turn off the
+ * machine
+ */
+void machine_power_off(void)
+{
+ /* If there is a registered power off handler, call it. */
+ if(pm_power_off)
+ pm_power_off();
+
+ /* Put the soft power button back under hardware control.
+ * If the user had already pressed the power button, the
+ * following call will immediately power off. */
+ pdc_soft_power_button(0);
+
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
+
+ /* It seems we have no way to power the system off via
+ * software. The user has to press the button himself. */
+
+ printk(KERN_EMERG "System shut down completed.\n"
+ KERN_EMERG "Please power this system off now.");
+}
+
+EXPORT_SYMBOL(machine_power_off);
+
+
+/*
+ * Create a kernel thread
+ */
+
+extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+
+ /*
+ * FIXME: Once we are sure we don't need any debug here,
+ * kernel_thread can become a #define.
+ */
+
+ return __kernel_thread(fn, arg, flags);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+ /* Only needs to handle fpu stuff or perf monitors.
+ ** REVISIT: several arches implement a "lazy fpu state".
+ */
+ set_fs(USER_DS);
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Fill in the FPU structure for a core dump.
+ */
+
+int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
+{
+ if (regs == NULL)
+ return 0;
+
+ memcpy(r, regs->fr, sizeof *r);
+ return 1;
+}
+
+int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
+{
+ memcpy(r, tsk->thread.regs.fr, sizeof(*r));
+ return 1;
+}
+
+/* Note that "fork()" is implemented in terms of clone, with
+ parameters (SIGCHLD, regs->gr[30], regs). */
+int
+sys_clone(unsigned long clone_flags, unsigned long usp,
+ struct pt_regs *regs)
+{
+ int __user *user_tid = (int __user *)regs->gr[26];
+
+ /* usp must be word aligned. This also prevents users from
+ * passing in the value 1 (which is the signal for a special
+ * return for a kernel thread) */
+ usp = ALIGN(usp, 4);
+
+ /* A zero value for usp means use the current stack */
+ if(usp == 0)
+ usp = regs->gr[30];
+
+ return do_fork(clone_flags, usp, regs, 0, user_tid, NULL);
+}
+
+int
+sys_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL);
+}
+
+int
+copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused, /* in ia64 this is "user_stack_size" */
+ struct task_struct * p, struct pt_regs * pregs)
+{
+ struct pt_regs * cregs = &(p->thread.regs);
+ struct thread_info *ti = p->thread_info;
+
+ /* We have to use void * instead of a function pointer, because
+ * function pointers aren't a pointer to the function on 64-bit.
+ * Make them const so the compiler knows they live in .text */
+ extern void * const ret_from_kernel_thread;
+ extern void * const child_return;
+#ifdef CONFIG_HPUX
+ extern void * const hpux_child_return;
+#endif
+
+ *cregs = *pregs;
+
+ /* Set the return value for the child. Note that this is not
+ actually restored by the syscall exit path, but we put it
+ here for consistency in case of signals. */
+ cregs->gr[28] = 0; /* child */
+
+ /*
+ * We need to differentiate between a user fork and a
+ * kernel fork. We can't use user_mode, because the
+ * the syscall path doesn't save iaoq. Right now
+ * We rely on the fact that kernel_thread passes
+ * in zero for usp.
+ */
+ if (usp == 1) {
+ /* kernel thread */
+ cregs->ksp = (((unsigned long)(ti)) + THREAD_SZ_ALGN);
+ /* Must exit via ret_from_kernel_thread in order
+ * to call schedule_tail()
+ */
+ cregs->kpc = (unsigned long) &ret_from_kernel_thread;
+ /*
+ * Copy function and argument to be called from
+ * ret_from_kernel_thread.
+ */
+#ifdef __LP64__
+ cregs->gr[27] = pregs->gr[27];
+#endif
+ cregs->gr[26] = pregs->gr[26];
+ cregs->gr[25] = pregs->gr[25];
+ } else {
+ /* user thread */
+ /*
+ * Note that the fork wrappers are responsible
+ * for setting gr[21].
+ */
+
+ /* Use same stack depth as parent */
+ cregs->ksp = ((unsigned long)(ti))
+ + (pregs->gr[21] & (THREAD_SIZE - 1));
+ cregs->gr[30] = usp;
+ if (p->personality == PER_HPUX) {
+#ifdef CONFIG_HPUX
+ cregs->kpc = (unsigned long) &hpux_child_return;
+#else
+ BUG();
+#endif
+ } else {
+ cregs->kpc = (unsigned long) &child_return;
+ }
+ }
+
+ return 0;
+}
+
+unsigned long thread_saved_pc(struct task_struct *t)
+{
+ return t->thread.regs.kpc;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+
+asmlinkage int sys_execve(struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname((const char __user *) regs->gr[26]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, (char __user **) regs->gr[25],
+ (char __user **) regs->gr[24], regs);
+ if (error == 0) {
+ task_lock(current);
+ current->ptrace &= ~PT_DTRACE;
+ task_unlock(current);
+ }
+ putname(filename);
+out:
+
+ return error;
+}
+
+unsigned long
+get_wchan(struct task_struct *p)
+{
+ struct unwind_frame_info info;
+ unsigned long ip;
+ int count = 0;
+ /*
+ * These bracket the sleeping functions..
+ */
+
+ unwind_frame_init_from_blocked_task(&info, p);
+ do {
+ if (unwind_once(&info) < 0)
+ return 0;
+ ip = info.ip;
+ if (!in_sched_functions(ip))
+ return ip;
+ } while (count++ < 16);
+ return 0;
+}
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
new file mode 100644
index 000000000000..13b721cb9f55
--- /dev/null
+++ b/arch/parisc/kernel/processor.c
@@ -0,0 +1,400 @@
+/* $Id: processor.c,v 1.1 2002/07/20 16:27:06 rhirst Exp $
+ *
+ * Initial setup-routines for HP 9000 based hardware.
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
+ * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
+ * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
+ * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
+ *
+ * Initial PA-RISC Version: 04-23-1999 by Helge Deller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+
+#include <asm/cache.h>
+#include <asm/hardware.h> /* for register_parisc_driver() stuff */
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/pdcpat.h>
+#include <asm/irq.h> /* for struct irq_region */
+#include <asm/parisc-device.h>
+
+struct system_cpuinfo_parisc boot_cpu_data;
+EXPORT_SYMBOL(boot_cpu_data);
+
+struct cpuinfo_parisc cpu_data[NR_CPUS];
+
+/*
+** PARISC CPU driver - claim "device" and initialize CPU data structures.
+**
+** Consolidate per CPU initialization into (mostly) one module.
+** Monarch CPU will initialize boot_cpu_data which shouldn't
+** change once the system has booted.
+**
+** The callback *should* do per-instance initialization of
+** everything including the monarch. "Per CPU" init code in
+** setup.c:start_parisc() has migrated here and start_parisc()
+** will call register_parisc_driver(&cpu_driver) before calling do_inventory().
+**
+** The goal of consolidating CPU initialization into one place is
+** to make sure all CPU's get initialized the same way.
+** The code path not shared is how PDC hands control of the CPU to the OS.
+** The initialization of OS data structures is the same (done below).
+*/
+
+/**
+ * processor_probe - Determine if processor driver should claim this device.
+ * @dev: The device which has been found.
+ *
+ * Determine if processor driver should claim this chip (return 0) or not
+ * (return 1). If so, initialize the chip and tell other partners in crime
+ * they have work to do.
+ */
+static int __init processor_probe(struct parisc_device *dev)
+{
+ unsigned long txn_addr;
+ unsigned long cpuid;
+ struct cpuinfo_parisc *p;
+
+#ifndef CONFIG_SMP
+ if (boot_cpu_data.cpu_count > 0) {
+ printk(KERN_INFO "CONFIG_SMP=n ignoring additional CPUs\n");
+ return 1;
+ }
+#endif
+
+ /* logical CPU ID and update global counter
+ * May get overwritten by PAT code.
+ */
+ cpuid = boot_cpu_data.cpu_count;
+ txn_addr = dev->hpa; /* for legacy PDC */
+
+#ifdef __LP64__
+ if (is_pdc_pat()) {
+ ulong status;
+ unsigned long bytecnt;
+ pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+#undef USE_PAT_CPUID
+#ifdef USE_PAT_CPUID
+ struct pdc_pat_cpu_num cpu_info;
+#endif
+
+ status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc,
+ dev->mod_index, PA_VIEW, &pa_pdc_cell);
+
+ BUG_ON(PDC_OK != status);
+
+ /* verify it's the same as what do_pat_inventory() found */
+ BUG_ON(dev->mod_info != pa_pdc_cell.mod_info);
+ BUG_ON(dev->pmod_loc != pa_pdc_cell.mod_location);
+
+ txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */
+
+#ifdef USE_PAT_CPUID
+/* We need contiguous numbers for cpuid. Firmware's notion
+ * of cpuid is for physical CPUs and we just don't care yet.
+ * We'll care when we need to query PAT PDC about a CPU *after*
+ * boot time (ie shutdown a CPU from an OS perspective).
+ */
+ /* get the cpu number */
+ status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa);
+
+ BUG_ON(PDC_OK != status);
+
+ if (cpu_info.cpu_num >= NR_CPUS) {
+ printk(KERN_WARNING "IGNORING CPU at 0x%x,"
+ " cpu_slot_id > NR_CPUS"
+ " (%ld > %d)\n",
+ dev->hpa, cpu_info.cpu_num, NR_CPUS);
+ /* Ignore CPU since it will only crash */
+ boot_cpu_data.cpu_count--;
+ return 1;
+ } else {
+ cpuid = cpu_info.cpu_num;
+ }
+#endif
+ }
+#endif
+
+ p = &cpu_data[cpuid];
+ boot_cpu_data.cpu_count++;
+
+ /* initialize counters */
+ memset(p, 0, sizeof(struct cpuinfo_parisc));
+
+ p->loops_per_jiffy = loops_per_jiffy;
+ p->dev = dev; /* Save IODC data in case we need it */
+ p->hpa = dev->hpa; /* save CPU hpa */
+ p->cpuid = cpuid; /* save CPU id */
+ p->txn_addr = txn_addr; /* save CPU IRQ address */
+#ifdef CONFIG_SMP
+ spin_lock_init(&p->lock);
+
+ /*
+ ** FIXME: review if any other initialization is clobbered
+ ** for boot_cpu by the above memset().
+ */
+
+ /* stolen from init_percpu_prof() */
+ cpu_data[cpuid].prof_counter = 1;
+ cpu_data[cpuid].prof_multiplier = 1;
+#endif
+
+ /*
+ ** CONFIG_SMP: init_smp_config() will attempt to get CPU's into
+ ** OS control. RENDEZVOUS is the default state - see mem_set above.
+ ** p->state = STATE_RENDEZVOUS;
+ */
+
+#if 0
+ /* CPU 0 IRQ table is statically allocated/initialized */
+ if (cpuid) {
+ struct irqaction actions[];
+
+ /*
+ ** itimer and ipi IRQ handlers are statically initialized in
+ ** arch/parisc/kernel/irq.c. ie Don't need to register them.
+ */
+ actions = kmalloc(sizeof(struct irqaction)*MAX_CPU_IRQ, GFP_ATOMIC);
+ if (!actions) {
+ /* not getting it's own table, share with monarch */
+ actions = cpu_irq_actions[0];
+ }
+
+ cpu_irq_actions[cpuid] = actions;
+ }
+#endif
+
+ /*
+ * Bring this CPU up now! (ignore bootstrap cpuid == 0)
+ */
+#ifdef CONFIG_SMP
+ if (cpuid) {
+ cpu_set(cpuid, cpu_present_map);
+ cpu_up(cpuid);
+ }
+#endif
+
+ return 0;
+}
+
+/**
+ * collect_boot_cpu_data - Fill the boot_cpu_data structure.
+ *
+ * This function collects and stores the generic processor information
+ * in the boot_cpu_data structure.
+ */
+void __init collect_boot_cpu_data(void)
+{
+ memset(&boot_cpu_data, 0, sizeof(boot_cpu_data));
+
+ boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */
+
+ /* get CPU-Model Information... */
+#define p ((unsigned long *)&boot_cpu_data.pdc.model)
+ if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK)
+ printk(KERN_INFO
+ "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
+#undef p
+
+ if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK)
+ printk(KERN_INFO "vers %08lx\n",
+ boot_cpu_data.pdc.versions);
+
+ if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK)
+ printk(KERN_INFO "CPUID vers %ld rev %ld (0x%08lx)\n",
+ (boot_cpu_data.pdc.cpuid >> 5) & 127,
+ boot_cpu_data.pdc.cpuid & 31,
+ boot_cpu_data.pdc.cpuid);
+
+ if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK)
+ printk(KERN_INFO "capabilities 0x%lx\n",
+ boot_cpu_data.pdc.capabilities);
+
+ if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name) == PDC_OK)
+ printk(KERN_INFO "model %s\n",
+ boot_cpu_data.pdc.sys_model_name);
+
+ boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion;
+ boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion;
+
+ boot_cpu_data.cpu_type = parisc_get_cpu_type(boot_cpu_data.hversion);
+ boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0];
+ boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1];
+}
+
+
+/**
+ * init_cpu_profiler - enable/setup per cpu profiling hooks.
+ * @cpunum: The processor instance.
+ *
+ * FIXME: doesn't do much yet...
+ */
+static inline void __init
+init_percpu_prof(int cpunum)
+{
+ cpu_data[cpunum].prof_counter = 1;
+ cpu_data[cpunum].prof_multiplier = 1;
+}
+
+
+/**
+ * init_per_cpu - Handle individual processor initializations.
+ * @cpunum: logical processor number.
+ *
+ * This function handles initialization for *every* CPU
+ * in the system:
+ *
+ * o Set "default" CPU width for trap handlers
+ *
+ * o Enable FP coprocessor
+ * REVISIT: this could be done in the "code 22" trap handler.
+ * (frowands idea - that way we know which processes need FP
+ * registers saved on the interrupt stack.)
+ * NEWS FLASH: wide kernels need FP coprocessor enabled to handle
+ * formatted printing of %lx for example (double divides I think)
+ *
+ * o Enable CPU profiling hooks.
+ */
+int __init init_per_cpu(int cpunum)
+{
+ int ret;
+ struct pdc_coproc_cfg coproc_cfg;
+
+ set_firmware_width();
+ ret = pdc_coproc_cfg(&coproc_cfg);
+
+ if(ret >= 0 && coproc_cfg.ccr_functional) {
+ mtctl(coproc_cfg.ccr_functional, 10); /* 10 == Coprocessor Control Reg */
+
+ /* FWIW, FP rev/model is a more accurate way to determine
+ ** CPU type. CPU rev/model has some ambiguous cases.
+ */
+ cpu_data[cpunum].fp_rev = coproc_cfg.revision;
+ cpu_data[cpunum].fp_model = coproc_cfg.model;
+
+ printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n",
+ cpunum, coproc_cfg.revision, coproc_cfg.model);
+
+ /*
+ ** store status register to stack (hopefully aligned)
+ ** and clear the T-bit.
+ */
+ asm volatile ("fstd %fr0,8(%sp)");
+
+ } else {
+ printk(KERN_WARNING "WARNING: No FP CoProcessor?!"
+ " (coproc_cfg.ccr_functional == 0x%lx, expected 0xc0)\n"
+#ifdef __LP64__
+ "Halting Machine - FP required\n"
+#endif
+ , coproc_cfg.ccr_functional);
+#ifdef __LP64__
+ mdelay(100); /* previous chars get pushed to console */
+ panic("FP CoProc not reported");
+#endif
+ }
+
+ /* FUTURE: Enable Performance Monitor : ccr bit 0x20 */
+ init_percpu_prof(cpunum);
+
+ return ret;
+}
+
+/*
+ * Display cpu info for all cpu's.
+ */
+int
+show_cpuinfo (struct seq_file *m, void *v)
+{
+ int n;
+
+ for(n=0; n<boot_cpu_data.cpu_count; n++) {
+#ifdef CONFIG_SMP
+ if (0 == cpu_data[n].hpa)
+ continue;
+#ifdef ENTRY_SYS_CPUS
+#error iCOD support wants to show CPU state here
+#endif
+#endif
+ seq_printf(m, "processor\t: %d\n"
+ "cpu family\t: PA-RISC %s\n",
+ n, boot_cpu_data.family_name);
+
+ seq_printf(m, "cpu\t\t: %s\n", boot_cpu_data.cpu_name );
+
+ /* cpu MHz */
+ seq_printf(m, "cpu MHz\t\t: %d.%06d\n",
+ boot_cpu_data.cpu_hz / 1000000,
+ boot_cpu_data.cpu_hz % 1000000 );
+
+ seq_printf(m, "model\t\t: %s\n"
+ "model name\t: %s\n",
+ boot_cpu_data.pdc.sys_model_name,
+ cpu_data[n].dev ?
+ cpu_data[n].dev->name : "Unknown" );
+
+ seq_printf(m, "hversion\t: 0x%08x\n"
+ "sversion\t: 0x%08x\n",
+ boot_cpu_data.hversion,
+ boot_cpu_data.sversion );
+
+ /* print cachesize info */
+ show_cache_info(m);
+
+ seq_printf(m, "bogomips\t: %lu.%02lu\n",
+ cpu_data[n].loops_per_jiffy / (500000 / HZ),
+ (cpu_data[n].loops_per_jiffy / (5000 / HZ)) % 100);
+
+ seq_printf(m, "software id\t: %ld\n\n",
+ boot_cpu_data.pdc.model.sw_id);
+ }
+ return 0;
+}
+
+static struct parisc_device_id processor_tbl[] = {
+ { HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID },
+ { 0, }
+};
+
+static struct parisc_driver cpu_driver = {
+ .name = "CPU",
+ .id_table = processor_tbl,
+ .probe = processor_probe
+};
+
+/**
+ * processor_init - Processor initalization procedure.
+ *
+ * Register this driver.
+ */
+void __init processor_init(void)
+{
+ register_parisc_driver(&cpu_driver);
+}
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
new file mode 100644
index 000000000000..2937a9236384
--- /dev/null
+++ b/arch/parisc/kernel/ptrace.c
@@ -0,0 +1,423 @@
+/*
+ * Kernel support for the ptrace() and syscall tracing interfaces.
+ *
+ * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc.
+ * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/personality.h>
+#include <linux/security.h>
+#include <linux/compat.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/offsets.h>
+
+/* PSW bits we allow the debugger to modify */
+#define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB)
+
+#undef DEBUG_PTRACE
+
+#ifdef DEBUG_PTRACE
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#ifdef __LP64__
+
+/* This function is needed to translate 32 bit pt_regs offsets in to
+ * 64 bit pt_regs offsets. For example, a 32 bit gdb under a 64 bit kernel
+ * will request offset 12 if it wants gr3, but the lower 32 bits of
+ * the 64 bit kernels view of gr3 will be at offset 28 (3*8 + 4).
+ * This code relies on a 32 bit pt_regs being comprised of 32 bit values
+ * except for the fp registers which (a) are 64 bits, and (b) follow
+ * the gr registers at the start of pt_regs. The 32 bit pt_regs should
+ * be half the size of the 64 bit pt_regs, plus 32*4 to allow for fr[]
+ * being 64 bit in both cases.
+ */
+
+static long translate_usr_offset(long offset)
+{
+ if (offset < 0)
+ return -1;
+ else if (offset <= 32*4) /* gr[0..31] */
+ return offset * 2 + 4;
+ else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */
+ return offset + 32*4;
+ else if (offset < sizeof(struct pt_regs)/2 + 32*4)
+ return offset * 2 + 4 - 32*8;
+ else
+ return -1;
+}
+#endif
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ /* make sure the trap bits are not set */
+ pa_psw(child)->r = 0;
+ pa_psw(child)->t = 0;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+}
+
+long sys_ptrace(long request, pid_t pid, long addr, long data)
+{
+ struct task_struct *child;
+ long ret;
+#ifdef DEBUG_PTRACE
+ long oaddr=addr, odata=data;
+#endif
+
+ lock_kernel();
+ ret = -EPERM;
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+
+ ret = security_ptrace(current->parent, current);
+ if (ret)
+ goto out;
+
+ /* set the ptrace bit in the process flags. */
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+ ret = -EPERM;
+ if (pid == 1) /* no messing around with init! */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out_tsk;
+
+ switch (request) {
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ int copied;
+
+#ifdef __LP64__
+ if (is_compat_task(child)) {
+ unsigned int tmp;
+
+ addr &= 0xffffffffL;
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ goto out_tsk;
+ ret = put_user(tmp,(unsigned int *) data);
+ DBG("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n",
+ request == PTRACE_PEEKTEXT ? "TEXT" : "DATA",
+ pid, oaddr, odata, ret, tmp);
+ }
+ else
+#endif
+ {
+ unsigned long tmp;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ goto out_tsk;
+ ret = put_user(tmp,(unsigned long *) data);
+ }
+ goto out_tsk;
+ }
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ ret = 0;
+#ifdef __LP64__
+ if (is_compat_task(child)) {
+ unsigned int tmp = (unsigned int)data;
+ DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
+ request == PTRACE_POKETEXT ? "TEXT" : "DATA",
+ pid, oaddr, odata);
+ addr &= 0xffffffffL;
+ if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp))
+ goto out_tsk;
+ }
+ else
+#endif
+ {
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ goto out_tsk;
+ }
+ ret = -EIO;
+ goto out_tsk;
+
+ /* Read the word at location addr in the USER area. For ptraced
+ processes, the kernel saves all regs on a syscall. */
+ case PTRACE_PEEKUSR: {
+ ret = -EIO;
+#ifdef __LP64__
+ if (is_compat_task(child)) {
+ unsigned int tmp;
+
+ if (addr & (sizeof(int)-1))
+ goto out_tsk;
+ if ((addr = translate_usr_offset(addr)) < 0)
+ goto out_tsk;
+
+ tmp = *(unsigned int *) ((char *) task_regs(child) + addr);
+ ret = put_user(tmp, (unsigned int *) data);
+ DBG("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n",
+ pid, oaddr, odata, ret, addr, tmp);
+ }
+ else
+#endif
+ {
+ unsigned long tmp;
+
+ if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
+ goto out_tsk;
+ tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
+ ret = put_user(tmp, (unsigned long *) data);
+ }
+ goto out_tsk;
+ }
+
+ /* Write the word at location addr in the USER area. This will need
+ to change when the kernel no longer saves all regs on a syscall.
+ FIXME. There is a problem at the moment in that r3-r18 are only
+ saved if the process is ptraced on syscall entry, and even then
+ those values are overwritten by actual register values on syscall
+ exit. */
+ case PTRACE_POKEUSR:
+ ret = -EIO;
+ /* Some register values written here may be ignored in
+ * entry.S:syscall_restore_rfi; e.g. iaoq is written with
+ * r31/r31+4, and not with the values in pt_regs.
+ */
+ /* PT_PSW=0, so this is valid for 32 bit processes under 64
+ * bit kernels.
+ */
+ if (addr == PT_PSW) {
+ /* PT_PSW=0, so this is valid for 32 bit processes
+ * under 64 bit kernels.
+ *
+ * Allow writing to Nullify, Divide-step-correction,
+ * and carry/borrow bits.
+ * BEWARE, if you set N, and then single step, it won't
+ * stop on the nullified instruction.
+ */
+ DBG("sys_ptrace(POKEUSR, %d, %lx, %lx)\n",
+ pid, oaddr, odata);
+ data &= USER_PSW_BITS;
+ task_regs(child)->gr[0] &= ~USER_PSW_BITS;
+ task_regs(child)->gr[0] |= data;
+ ret = 0;
+ goto out_tsk;
+ }
+#ifdef __LP64__
+ if (is_compat_task(child)) {
+ if (addr & (sizeof(int)-1))
+ goto out_tsk;
+ if ((addr = translate_usr_offset(addr)) < 0)
+ goto out_tsk;
+ DBG("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n",
+ pid, oaddr, odata, addr);
+ if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
+ /* Special case, fp regs are 64 bits anyway */
+ *(unsigned int *) ((char *) task_regs(child) + addr) = data;
+ ret = 0;
+ }
+ else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) ||
+ addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 ||
+ addr == PT_SAR+4) {
+ /* Zero the top 32 bits */
+ *(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0;
+ *(unsigned int *) ((char *) task_regs(child) + addr) = data;
+ ret = 0;
+ }
+ goto out_tsk;
+ }
+ else
+#endif
+ {
+ if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
+ goto out_tsk;
+ if ((addr >= PT_GR1 && addr <= PT_GR31) ||
+ addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
+ (addr >= PT_FR0 && addr <= PT_FR31 + 4) ||
+ addr == PT_SAR) {
+ *(unsigned long *) ((char *) task_regs(child) + addr) = data;
+ ret = 0;
+ }
+ goto out_tsk;
+ }
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT:
+ ret = -EIO;
+ DBG("sys_ptrace(%s)\n",
+ request == PTRACE_SYSCALL ? "SYSCALL" : "CONT");
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
+ if (request == PTRACE_SYSCALL) {
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ } else {
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ }
+ child->exit_code = data;
+ goto out_wake_notrap;
+
+ case PTRACE_KILL:
+ /*
+ * make the child exit. Best I can do is send it a
+ * sigkill. perhaps it should be put in the status
+ * that it wants to exit.
+ */
+ DBG("sys_ptrace(KILL)\n");
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ goto out_tsk;
+ child->exit_code = SIGKILL;
+ goto out_wake_notrap;
+
+ case PTRACE_SINGLEBLOCK:
+ DBG("sys_ptrace(SINGLEBLOCK)\n");
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ child->ptrace &= ~PT_SINGLESTEP;
+ child->ptrace |= PT_BLOCKSTEP;
+ child->exit_code = data;
+
+ /* Enable taken branch trap. */
+ pa_psw(child)->r = 0;
+ pa_psw(child)->t = 1;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+ goto out_wake;
+
+ case PTRACE_SINGLESTEP:
+ DBG("sys_ptrace(SINGLESTEP)\n");
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ child->ptrace &= ~PT_BLOCKSTEP;
+ child->ptrace |= PT_SINGLESTEP;
+ child->exit_code = data;
+
+ if (pa_psw(child)->n) {
+ struct siginfo si;
+
+ /* Nullified, just crank over the queue. */
+ task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1];
+ task_regs(child)->iasq[0] = task_regs(child)->iasq[1];
+ task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4;
+ pa_psw(child)->n = 0;
+ pa_psw(child)->x = 0;
+ pa_psw(child)->y = 0;
+ pa_psw(child)->z = 0;
+ pa_psw(child)->b = 0;
+ ptrace_disable(child);
+ /* Don't wake up the child, but let the
+ parent know something happened. */
+ si.si_code = TRAP_TRACE;
+ si.si_addr = (void __user *) (task_regs(child)->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ si.si_errno = 0;
+ force_sig_info(SIGTRAP, &si, child);
+ //notify_parent(child, SIGCHLD);
+ //ret = 0;
+ goto out_wake;
+ }
+
+ /* Enable recovery counter traps. The recovery counter
+ * itself will be set to zero on a task switch. If the
+ * task is suspended on a syscall then the syscall return
+ * path will overwrite the recovery counter with a suitable
+ * value such that it traps once back in user space. We
+ * disable interrupts in the childs PSW here also, to avoid
+ * interrupts while the recovery counter is decrementing.
+ */
+ pa_psw(child)->r = 1;
+ pa_psw(child)->t = 0;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+ /* give it a chance to run. */
+ goto out_wake;
+
+ case PTRACE_DETACH:
+ ret = ptrace_detach(child, data);
+ goto out_tsk;
+
+ case PTRACE_GETEVENTMSG:
+ ret = put_user(child->ptrace_message, (unsigned int __user *) data);
+ goto out_tsk;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ goto out_tsk;
+ }
+
+out_wake_notrap:
+ ptrace_disable(child);
+out_wake:
+ wake_up_process(child);
+ ret = 0;
+out_tsk:
+ put_task_struct(child);
+out:
+ unlock_kernel();
+ DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
+ request, pid, oaddr, odata, ret);
+ return ret;
+}
+
+void syscall_trace(void)
+{
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S
new file mode 100644
index 000000000000..8dd5defb7316
--- /dev/null
+++ b/arch/parisc/kernel/real2.S
@@ -0,0 +1,304 @@
+/*
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
+ *
+ */
+#include <asm/assembly.h>
+#include <asm/psw.h>
+
+ .section .bss
+ .export real_stack
+ .export real32_stack
+ .export real64_stack
+ .align 64
+real_stack:
+real32_stack:
+real64_stack:
+ .block 8192
+
+#ifdef __LP64__
+# define REG_SZ 8
+#else
+# define REG_SZ 4
+#endif
+
+#define N_SAVED_REGS 9
+
+save_cr_space:
+ .block REG_SZ * N_SAVED_REGS
+save_cr_end:
+
+
+/************************ 32-bit real-mode calls ***********************/
+/* This can be called in both narrow and wide kernels */
+
+ .text
+
+ .export real32_call_asm
+
+ /* unsigned long real32_call_asm(unsigned int *sp,
+ * unsigned int *arg0p,
+ * unsigned int iodc_fn)
+ * sp is value of stack pointer to adopt before calling PDC (virt)
+ * arg0p points to where saved arg values may be found
+ * iodc_fn is the IODC function to call
+ */
+
+real32_call_asm:
+ STREG %rp, -RP_OFFSET(%sp) /* save RP */
+#ifdef __LP64__
+ callee_save
+ ldo 2*REG_SZ(%sp), %sp /* room for a couple more saves */
+ STREG %r27, -1*REG_SZ(%sp)
+ STREG %r29, -2*REG_SZ(%sp)
+#endif
+ STREG %sp, -REG_SZ(%arg0) /* save SP on real-mode stack */
+ copy %arg0, %sp /* adopt the real-mode SP */
+
+ /* save iodc_fn */
+ copy %arg2, %r31
+
+ /* load up the arg registers from the saved arg area */
+ /* 32-bit calling convention passes first 4 args in registers */
+ ldw 0(%arg1), %arg0 /* note overwriting arg0 */
+ ldw -8(%arg1), %arg2
+ ldw -12(%arg1), %arg3
+ ldw -4(%arg1), %arg1 /* obviously must do this one last! */
+
+ tophys_r1 %sp
+
+ b,l rfi_virt2real,%r2
+ nop
+
+ b,l save_control_regs,%r2 /* modifies r1, r2, r28 */
+ nop
+
+#ifdef __LP64__
+ rsm PSW_SM_W, %r0 /* go narrow */
+#endif
+
+ load32 PA(ric_ret), %r2
+ bv 0(%r31)
+ nop
+ric_ret:
+#ifdef __LP64__
+ ssm PSW_SM_W, %r0 /* go wide */
+#endif
+ /* restore CRs before going virtual in case we page fault */
+ b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */
+ nop
+
+ b,l rfi_real2virt,%r2
+ nop
+
+ tovirt_r1 %sp
+ LDREG -REG_SZ(%sp), %sp /* restore SP */
+#ifdef __LP64__
+ LDREG -1*REG_SZ(%sp), %r27
+ LDREG -2*REG_SZ(%sp), %r29
+ ldo -2*REG_SZ(%sp), %sp
+ callee_rest
+#endif
+ LDREG -RP_OFFSET(%sp), %rp /* restore RP */
+ bv 0(%rp)
+ nop
+
+
+# define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where)
+# define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r
+
+ .text
+save_control_regs:
+ load32 PA(save_cr_space), %r28
+ PUSH_CR(%cr24, %r28)
+ PUSH_CR(%cr25, %r28)
+ PUSH_CR(%cr26, %r28)
+ PUSH_CR(%cr27, %r28)
+ PUSH_CR(%cr28, %r28)
+ PUSH_CR(%cr29, %r28)
+ PUSH_CR(%cr30, %r28)
+ PUSH_CR(%cr31, %r28)
+ PUSH_CR(%cr15, %r28)
+ bv 0(%r2)
+ nop
+
+restore_control_regs:
+ load32 PA(save_cr_end), %r26
+ POP_CR(%cr15, %r26)
+ POP_CR(%cr31, %r26)
+ POP_CR(%cr30, %r26)
+ POP_CR(%cr29, %r26)
+ POP_CR(%cr28, %r26)
+ POP_CR(%cr27, %r26)
+ POP_CR(%cr26, %r26)
+ POP_CR(%cr25, %r26)
+ POP_CR(%cr24, %r26)
+ bv 0(%r2)
+ nop
+
+/* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for
+ * more general-purpose use by the several places which need RFIs
+ */
+ .align 128
+ .text
+rfi_virt2real:
+ /* switch to real mode... */
+ ssm 0,0 /* See "relied upon translation" */
+ nop /* PA 2.0 Arch. F-5 */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ rsm (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q & I bits to load iia queue */
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ load32 PA(rfi_v2r_1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
+ load32 REAL_MODE_PSW, %r1
+ mtctl %r1, %cr22
+ rfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+rfi_v2r_1:
+ tophys_r1 %r2
+ bv 0(%r2)
+ nop
+
+ .text
+ .align 128
+rfi_real2virt:
+ ssm 0,0 /* See "relied upon translation" */
+ nop /* PA 2.0 Arch. F-5 */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ rsm PSW_SM_Q,%r0 /* disable Q bit to load iia queue */
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ load32 (rfi_r2v_1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
+ load32 KERNEL_PSW, %r1
+ mtctl %r1, %cr22
+ rfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+rfi_r2v_1:
+ tovirt_r1 %r2
+ bv 0(%r2)
+ nop
+
+#ifdef __LP64__
+
+/************************ 64-bit real-mode calls ***********************/
+/* This is only usable in wide kernels right now and will probably stay so */
+ .text
+ .export real64_call_asm
+ /* unsigned long real64_call_asm(unsigned long *sp,
+ * unsigned long *arg0p,
+ * unsigned long fn)
+ * sp is value of stack pointer to adopt before calling PDC (virt)
+ * arg0p points to where saved arg values may be found
+ * iodc_fn is the IODC function to call
+ */
+real64_call_asm:
+ std %rp, -0x10(%sp) /* save RP */
+ std %sp, -8(%arg0) /* save SP on real-mode stack */
+ copy %arg0, %sp /* adopt the real-mode SP */
+
+ /* save fn */
+ copy %arg2, %r31
+
+ /* set up the new ap */
+ ldo 64(%arg1), %r29
+
+ /* load up the arg registers from the saved arg area */
+ /* 32-bit calling convention passes first 4 args in registers */
+ ldd 0*REG_SZ(%arg1), %arg0 /* note overwriting arg0 */
+ ldd 2*REG_SZ(%arg1), %arg2
+ ldd 3*REG_SZ(%arg1), %arg3
+ ldd 4*REG_SZ(%arg1), %r22
+ ldd 5*REG_SZ(%arg1), %r21
+ ldd 6*REG_SZ(%arg1), %r20
+ ldd 7*REG_SZ(%arg1), %r19
+ ldd 1*REG_SZ(%arg1), %arg1 /* do this one last! */
+
+ tophys_r1 %sp
+
+ b,l rfi_virt2real,%r2
+ nop
+
+ b,l save_control_regs,%r2 /* modifies r1, r2, r28 */
+ nop
+
+ load32 PA(r64_ret), %r2
+ bv 0(%r31)
+ nop
+r64_ret:
+ /* restore CRs before going virtual in case we page fault */
+ b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */
+ nop
+
+ b,l rfi_real2virt,%r2
+ nop
+
+ tovirt_r1 %sp
+ ldd -8(%sp), %sp /* restore SP */
+ ldd -0x10(%sp), %rp /* restore RP */
+ bv 0(%rp)
+ nop
+
+#endif
+
+ .export pc_in_user_space
+ .text
+ /* Doesn't belong here but I couldn't find a nicer spot. */
+ /* Should never get called, only used by profile stuff in time.c */
+pc_in_user_space:
+ bv,n 0(%rp)
+ nop
+
+
+ .export __canonicalize_funcptr_for_compare
+ .text
+ /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html
+ ** GCC 3.3 and later has a new function in libgcc.a for
+ ** comparing function pointers.
+ */
+__canonicalize_funcptr_for_compare:
+#ifdef __LP64__
+ bve (%r2)
+#else
+ bv %r0(%r2)
+#endif
+ copy %r26,%r28
diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c
new file mode 100644
index 000000000000..ee806bcc3726
--- /dev/null
+++ b/arch/parisc/kernel/semaphore.c
@@ -0,0 +1,102 @@
+/*
+ * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard
+ */
+
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+/*
+ * Semaphores are complex as we wish to avoid using two variables.
+ * `count' has multiple roles, depending on its value. If it is positive
+ * or zero, there are no waiters. The functions here will never be
+ * called; see <asm/semaphore.h>
+ *
+ * When count is -1 it indicates there is at least one task waiting
+ * for the semaphore.
+ *
+ * When count is less than that, there are '- count - 1' wakeups
+ * pending. ie if it has value -3, there are 2 wakeups pending.
+ *
+ * Note that these functions are only called when there is contention
+ * on the lock, and as such all this is the "non-critical" part of the
+ * whole semaphore business. The critical part is the inline stuff in
+ * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+ sem->count--;
+ wake_up(&sem->wait);
+}
+
+#define wakers(count) (-1 - count)
+
+#define DOWN_HEAD \
+ int ret = 0; \
+ DECLARE_WAITQUEUE(wait, current); \
+ \
+ /* Note that someone is waiting */ \
+ if (sem->count == 0) \
+ sem->count = -1; \
+ \
+ /* protected by the sentry still -- use unlocked version */ \
+ wait.flags = WQ_FLAG_EXCLUSIVE; \
+ __add_wait_queue_tail(&sem->wait, &wait); \
+ lost_race: \
+ spin_unlock_irq(&sem->sentry); \
+
+#define DOWN_TAIL \
+ spin_lock_irq(&sem->sentry); \
+ if (wakers(sem->count) == 0 && ret == 0) \
+ goto lost_race; /* Someone stole our wakeup */ \
+ __remove_wait_queue(&sem->wait, &wait); \
+ current->state = TASK_RUNNING; \
+ if (!waitqueue_active(&sem->wait) && (sem->count < 0)) \
+ sem->count = wakers(sem->count);
+
+#define UPDATE_COUNT \
+ sem->count += (sem->count < 0) ? 1 : - 1;
+
+
+void __sched __down(struct semaphore * sem)
+{
+ DOWN_HEAD
+
+ for(;;) {
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
+ /* we can _read_ this without the sentry */
+ if (sem->count != -1)
+ break;
+ schedule();
+ }
+
+ DOWN_TAIL
+ UPDATE_COUNT
+}
+
+int __sched __down_interruptible(struct semaphore * sem)
+{
+ DOWN_HEAD
+
+ for(;;) {
+ set_task_state(current, TASK_INTERRUPTIBLE);
+ /* we can _read_ this without the sentry */
+ if (sem->count != -1)
+ break;
+
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
+ schedule();
+ }
+
+ DOWN_TAIL
+
+ if (!ret) {
+ UPDATE_COUNT
+ }
+
+ return ret;
+}
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
new file mode 100644
index 000000000000..73e9c34b0948
--- /dev/null
+++ b/arch/parisc/kernel/setup.c
@@ -0,0 +1,368 @@
+/* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $
+ *
+ * Initial setup-routines for HP 9000 based hardware.
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
+ * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
+ * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
+ * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
+ *
+ * Initial PA-RISC Version: 04-23-1999 by Helge Deller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/initrd.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#define PCI_DEBUG
+#include <linux/pci.h>
+#undef PCI_DEBUG
+#include <linux/proc_fs.h>
+
+#include <asm/processor.h>
+#include <asm/pdc.h>
+#include <asm/led.h>
+#include <asm/machdep.h> /* for pa7300lc_init() proto */
+#include <asm/pdc_chassis.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+
+char command_line[COMMAND_LINE_SIZE];
+
+/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
+struct proc_dir_entry * proc_runway_root = NULL;
+struct proc_dir_entry * proc_gsc_root = NULL;
+struct proc_dir_entry * proc_mckinley_root = NULL;
+
+#if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA))
+int parisc_bus_is_phys = 1; /* Assume no IOMMU is present */
+EXPORT_SYMBOL(parisc_bus_is_phys);
+#endif
+
+/* This sets the vmerge boundary and size, it's here because it has to
+ * be available on all platforms (zero means no-virtual merging) */
+unsigned long parisc_vmerge_boundary = 0;
+unsigned long parisc_vmerge_max_size = 0;
+
+void __init setup_cmdline(char **cmdline_p)
+{
+ extern unsigned int boot_args[];
+
+ /* Collect stuff passed in from the boot loader */
+
+ /* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */
+ if (boot_args[0] < 64) {
+ /* called from hpux boot loader */
+ saved_command_line[0] = '\0';
+ } else {
+ strcpy(saved_command_line, (char *)__va(boot_args[1]));
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
+ {
+ initrd_start = (unsigned long)__va(boot_args[2]);
+ initrd_end = (unsigned long)__va(boot_args[3]);
+ }
+#endif
+ }
+
+ strcpy(command_line, saved_command_line);
+ *cmdline_p = command_line;
+}
+
+#ifdef CONFIG_PA11
+void __init dma_ops_init(void)
+{
+ switch (boot_cpu_data.cpu_type) {
+ case pcx:
+ /*
+ * We've got way too many dependencies on 1.1 semantics
+ * to support 1.0 boxes at this point.
+ */
+ panic( "PA-RISC Linux currently only supports machines that conform to\n"
+ "the PA-RISC 1.1 or 2.0 architecture specification.\n");
+
+ case pcxs:
+ case pcxt:
+ hppa_dma_ops = &pcx_dma_ops;
+ break;
+ case pcxl2:
+ pa7300lc_init();
+ case pcxl: /* falls through */
+ hppa_dma_ops = &pcxl_dma_ops;
+ break;
+ default:
+ break;
+ }
+}
+#endif
+
+extern int init_per_cpu(int cpuid);
+extern void collect_boot_cpu_data(void);
+
+void __init setup_arch(char **cmdline_p)
+{
+#ifdef __LP64__
+ extern int parisc_narrow_firmware;
+#endif
+
+ init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */
+
+#ifdef __LP64__
+ printk(KERN_INFO "The 64-bit Kernel has started...\n");
+#else
+ printk(KERN_INFO "The 32-bit Kernel has started...\n");
+#endif
+
+ pdc_console_init();
+
+#ifdef __LP64__
+ if(parisc_narrow_firmware) {
+ printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
+ }
+#endif
+ setup_pdc();
+ setup_cmdline(cmdline_p);
+ collect_boot_cpu_data();
+ do_memory_inventory(); /* probe for physical memory */
+ parisc_cache_init();
+ paging_init();
+
+#ifdef CONFIG_CHASSIS_LCD_LED
+ /* initialize the LCD/LED after boot_cpu_data is available ! */
+ led_init(); /* LCD/LED initialization */
+#endif
+
+#ifdef CONFIG_PA11
+ dma_ops_init();
+#endif
+
+#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con; /* we use take_over_console() later ! */
+#endif
+
+}
+
+/*
+ * Display cpu info for all cpu's.
+ * for parisc this is in processor.c
+ */
+extern int show_cpuinfo (struct seq_file *m, void *v);
+
+static void *
+c_start (struct seq_file *m, loff_t *pos)
+{
+ /* Looks like the caller will call repeatedly until we return
+ * 0, signaling EOF perhaps. This could be used to sequence
+ * through CPUs for example. Since we print all cpu info in our
+ * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above)
+ * we only allow for one "position". */
+ return ((long)*pos < 1) ? (void *)1 : NULL;
+}
+
+static void *
+c_next (struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+
+static void
+c_stop (struct seq_file *m, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo
+};
+
+static void __init parisc_proc_mkdir(void)
+{
+ /*
+ ** Can't call proc_mkdir() until after proc_root_init() has been
+ ** called by start_kernel(). In other words, this code can't
+ ** live in arch/.../setup.c because start_parisc() calls
+ ** start_kernel().
+ */
+ switch (boot_cpu_data.cpu_type) {
+ case pcxl:
+ case pcxl2:
+ if (NULL == proc_gsc_root)
+ {
+ proc_gsc_root = proc_mkdir("bus/gsc", NULL);
+ }
+ break;
+ case pcxt_:
+ case pcxu:
+ case pcxu_:
+ case pcxw:
+ case pcxw_:
+ case pcxw2:
+ if (NULL == proc_runway_root)
+ {
+ proc_runway_root = proc_mkdir("bus/runway", NULL);
+ }
+ break;
+ case mako:
+ if (NULL == proc_mckinley_root)
+ {
+ proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
+ }
+ break;
+ default:
+ /* FIXME: this was added to prevent the compiler
+ * complaining about missing pcx, pcxs and pcxt
+ * I'm assuming they have neither gsc nor runway */
+ break;
+ }
+}
+
+static struct resource central_bus = {
+ .name = "Central Bus",
+ .start = F_EXTEND(0xfff80000),
+ .end = F_EXTEND(0xfffaffff),
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource local_broadcast = {
+ .name = "Local Broadcast",
+ .start = F_EXTEND(0xfffb0000),
+ .end = F_EXTEND(0xfffdffff),
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource global_broadcast = {
+ .name = "Global Broadcast",
+ .start = F_EXTEND(0xfffe0000),
+ .end = F_EXTEND(0xffffffff),
+ .flags = IORESOURCE_MEM,
+};
+
+static int __init parisc_init_resources(void)
+{
+ int result;
+
+ result = request_resource(&iomem_resource, &central_bus);
+ if (result < 0) {
+ printk(KERN_ERR
+ "%s: failed to claim %s address space!\n",
+ __FILE__, central_bus.name);
+ return result;
+ }
+
+ result = request_resource(&iomem_resource, &local_broadcast);
+ if (result < 0) {
+ printk(KERN_ERR
+ "%s: failed to claim %saddress space!\n",
+ __FILE__, local_broadcast.name);
+ return result;
+ }
+
+ result = request_resource(&iomem_resource, &global_broadcast);
+ if (result < 0) {
+ printk(KERN_ERR
+ "%s: failed to claim %s address space!\n",
+ __FILE__, global_broadcast.name);
+ return result;
+ }
+
+ return 0;
+}
+
+extern void gsc_init(void);
+extern void processor_init(void);
+extern void ccio_init(void);
+extern void hppb_init(void);
+extern void dino_init(void);
+extern void iosapic_init(void);
+extern void lba_init(void);
+extern void sba_init(void);
+extern void eisa_init(void);
+
+static int __init parisc_init(void)
+{
+ parisc_proc_mkdir();
+ parisc_init_resources();
+ do_device_inventory(); /* probe for hardware */
+
+ parisc_pdc_chassis_init();
+
+ /* set up a new led state on systems shipped LED State panel */
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART);
+
+ processor_init();
+ printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
+ boot_cpu_data.cpu_count,
+ boot_cpu_data.cpu_name,
+ boot_cpu_data.cpu_hz / 1000000,
+ boot_cpu_data.cpu_hz % 1000000 );
+
+ parisc_setup_cache_timing();
+
+ /* These are in a non-obvious order, will fix when we have an iotree */
+#if defined(CONFIG_IOSAPIC)
+ iosapic_init();
+#endif
+#if defined(CONFIG_IOMMU_SBA)
+ sba_init();
+#endif
+#if defined(CONFIG_PCI_LBA)
+ lba_init();
+#endif
+
+ /* CCIO before any potential subdevices */
+#if defined(CONFIG_IOMMU_CCIO)
+ ccio_init();
+#endif
+
+ /*
+ * Need to register Asp & Wax before the EISA adapters for the IRQ
+ * regions. EISA must come before PCI to be sure it gets IRQ region
+ * 0.
+ */
+#if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX)
+ gsc_init();
+#endif
+#ifdef CONFIG_EISA
+ eisa_init();
+#endif
+
+#if defined(CONFIG_HPPB)
+ hppb_init();
+#endif
+
+#if defined(CONFIG_GSC_DINO)
+ dino_init();
+#endif
+
+#ifdef CONFIG_CHASSIS_LCD_LED
+ register_led_regions(); /* register LED port info in procfs */
+#endif
+
+ return 0;
+}
+
+arch_initcall(parisc_init);
+
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
new file mode 100644
index 000000000000..9421bb98ea63
--- /dev/null
+++ b/arch/parisc/kernel/signal.c
@@ -0,0 +1,664 @@
+/*
+ * linux/arch/parisc/kernel/signal.c: Architecture-specific signal
+ * handling support.
+ *
+ * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
+ * Copyright (C) 2000 Linuxcare, Inc.
+ *
+ * Based on the ia64, i386, and alpha versions.
+ *
+ * Like the IA-64, we are a recent enough port (we are *starting*
+ * with glibc2.2) that we do not need to support the old non-realtime
+ * Linux signals. Therefore we don't. HP/UX signals will go in
+ * arch/parisc/hpux/signal.c when we figure out how to do them.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/compat.h>
+#include <linux/elf.h>
+#include <linux/personality.h>
+#include <asm/ucontext.h>
+#include <asm/rt_sigframe.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/offsets.h>
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#include "signal32.h"
+#endif
+
+#define DEBUG_SIG 0
+#define DEBUG_SIG_LEVEL 2
+
+#if DEBUG_SIG
+#define DBG(LEVEL, ...) \
+ ((DEBUG_SIG_LEVEL >= LEVEL) \
+ ? printk(__VA_ARGS__) : (void) 0)
+#else
+#define DBG(LEVEL, ...)
+#endif
+
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/* gcc will complain if a pointer is cast to an integer of different
+ * size. If you really need to do this (and we do for an ELF32 user
+ * application in an ELF64 kernel) then you have to do a cast to an
+ * integer of the same size first. The A() macro accomplishes
+ * this. */
+#define A(__x) ((unsigned long)(__x))
+
+int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+#ifdef __LP64__
+#include "sys32.h"
+#endif
+
+asmlinkage int
+sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
+{
+ sigset_t saveset, newset;
+#ifdef __LP64__
+ compat_sigset_t newset32;
+
+ if(personality(current->personality) == PER_LINUX32){
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
+ return -EFAULT;
+ sigset_32to64(&newset,&newset32);
+
+ } else
+#endif
+ {
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+ }
+
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ regs->gr[28] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, regs, 1))
+ return -EINTR;
+ }
+}
+
+/*
+ * Do a signal return - restore sigcontext.
+ */
+
+/* Trampoline for calling rt_sigreturn() */
+#define INSN_LDI_R25_0 0x34190000 /* ldi 0,%r25 (in_syscall=0) */
+#define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */
+#define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */
+#define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
+#define INSN_NOP 0x08000240 /* nop */
+/* For debugging */
+#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
+
+static long
+restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
+{
+ long err = 0;
+
+ err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
+ err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
+ err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
+ err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
+ err |= __get_user(regs->sar, &sc->sc_sar);
+ DBG(2,"restore_sigcontext: iaoq is 0x%#lx / 0x%#lx\n",
+ regs->iaoq[0],regs->iaoq[1]);
+ DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
+ return err;
+}
+
+void
+sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
+{
+ struct rt_sigframe __user *frame;
+ struct siginfo si;
+ sigset_t set;
+ unsigned long usp = (regs->gr[30] & ~(0x01UL));
+ unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
+#ifdef __LP64__
+ compat_sigset_t compat_set;
+ struct compat_rt_sigframe __user * compat_frame;
+
+ if(personality(current->personality) == PER_LINUX32)
+ sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
+#endif
+
+
+ /* Unwind the user stack to get the rt_sigframe structure. */
+ frame = (struct rt_sigframe __user *)
+ (usp - sigframe_size);
+ DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
+
+#ifdef __LP64__
+ compat_frame = (struct compat_rt_sigframe __user *)frame;
+
+ if(personality(current->personality) == PER_LINUX32){
+ DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
+ if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
+ goto give_sigsegv;
+ sigset_32to64(&set,&compat_set);
+ } else
+#endif
+ {
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto give_sigsegv;
+ }
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ /* Good thing we saved the old gr[30], eh? */
+#ifdef __LP64__
+ if(personality(current->personality) == PER_LINUX32){
+ DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
+ &compat_frame->uc.uc_mcontext);
+// FIXME: Load upper half from register file
+ if (restore_sigcontext32(&compat_frame->uc.uc_mcontext,
+ &compat_frame->regs, regs))
+ goto give_sigsegv;
+ DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
+ usp, &compat_frame->uc.uc_stack);
+ if (do_sigaltstack32(&compat_frame->uc.uc_stack, NULL, usp) == -EFAULT)
+ goto give_sigsegv;
+ } else
+#endif
+ {
+ DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
+ &frame->uc.uc_mcontext);
+ if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
+ goto give_sigsegv;
+ DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
+ usp, &frame->uc.uc_stack);
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
+ goto give_sigsegv;
+ }
+
+
+
+ /* If we are on the syscall path IAOQ will not be restored, and
+ * if we are on the interrupt path we must not corrupt gr31.
+ */
+ if (in_syscall)
+ regs->gr[31] = regs->iaoq[0];
+#if DEBUG_SIG
+ DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
+ show_regs(regs);
+#endif
+ return;
+
+give_sigsegv:
+ DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SI_KERNEL;
+ si.si_pid = current->pid;
+ si.si_uid = current->uid;
+ si.si_addr = &frame->uc;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+ /*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
+ don't use the parameter it doesn't matter */
+
+ DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
+ (unsigned long)ka, sp, frame_size);
+
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+ sp = current->sas_ss_sp; /* Stacks grow up! */
+
+ DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
+ return (void __user *) sp; /* Stacks grow up. Fun. */
+}
+
+static long
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
+
+{
+ unsigned long flags = 0;
+ long err = 0;
+
+ if (on_sig_stack((unsigned long) sc))
+ flags |= PARISC_SC_FLAG_ONSTACK;
+ if (in_syscall) {
+ flags |= PARISC_SC_FLAG_IN_SYSCALL;
+ /* regs->iaoq is undefined in the syscall return path */
+ err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
+ err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
+ err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
+ err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
+ DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
+ regs->gr[31], regs->gr[31]+4);
+ } else {
+ err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
+ err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
+ DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n",
+ regs->iaoq[0], regs->iaoq[1]);
+ }
+
+ err |= __put_user(flags, &sc->sc_flags);
+ err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
+ err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
+ err |= __put_user(regs->sar, &sc->sc_sar);
+ DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
+
+ return err;
+}
+
+static long
+setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs, int in_syscall)
+{
+ struct rt_sigframe __user *frame;
+ unsigned long rp, usp;
+ unsigned long haddr, sigframe_size;
+ struct siginfo si;
+ int err = 0;
+#ifdef __LP64__
+ compat_int_t compat_val;
+ struct compat_rt_sigframe __user * compat_frame;
+ compat_sigset_t compat_set;
+#endif
+
+ usp = (regs->gr[30] & ~(0x01UL));
+ /*FIXME: frame_size parameter is unused, remove it. */
+ frame = get_sigframe(ka, usp, sizeof(*frame));
+
+ DBG(1,"SETUP_RT_FRAME: START\n");
+ DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
+
+
+#ifdef __LP64__
+
+ compat_frame = (struct compat_rt_sigframe __user *)frame;
+
+ if(personality(current->personality) == PER_LINUX32) {
+ DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
+ err |= compat_copy_siginfo_to_user(&compat_frame->info, info);
+ DBG(1,"SETUP_RT_FRAME: 1\n");
+ compat_val = (compat_int_t)current->sas_ss_sp;
+ err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
+ DBG(1,"SETUP_RT_FRAME: 2\n");
+ compat_val = (compat_int_t)current->sas_ss_size;
+ err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_size);
+ DBG(1,"SETUP_RT_FRAME: 3\n");
+ compat_val = sas_ss_flags(regs->gr[30]);
+ err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_flags);
+ DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
+ DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
+ err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
+ &compat_frame->regs, regs, in_syscall);
+ sigset_64to32(&compat_set,set);
+ err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
+ } else
+#endif
+ {
+ DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
+ err |= copy_siginfo_to_user(&frame->info, info);
+ err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= __put_user(sas_ss_flags(regs->gr[30]),
+ &frame->uc.uc_stack.ss_flags);
+ DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
+ DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
+ /* FIXME: Should probably be converted aswell for the compat case */
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ }
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. The first words of tramp are used to
+ save the previous sigrestartblock trampoline that might be
+ on the stack. We start the sigreturn trampoline at
+ SIGRESTARTBLOCK_TRAMP+X. */
+ err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
+ &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
+ err |= __put_user(INSN_LDI_R20,
+ &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
+ err |= __put_user(INSN_BLE_SR2_R0,
+ &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
+ err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
+
+#if DEBUG_SIG
+ /* Assert that we're flushing in the correct space... */
+ {
+ int sid;
+ asm ("mfsp %%sr3,%0" : "=r" (sid));
+ DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
+ sid, frame->tramp);
+ }
+#endif
+
+ flush_user_dcache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[TRAMP_SIZE]);
+ flush_user_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[TRAMP_SIZE]);
+
+ /* TRAMP Words 0-4, Lenght 5 = SIGRESTARTBLOCK_TRAMP
+ * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
+ * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
+ */
+ rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
+
+ if (err)
+ goto give_sigsegv;
+
+ haddr = A(ka->sa.sa_handler);
+ /* The sa_handler may be a pointer to a function descriptor */
+#ifdef __LP64__
+ if(personality(current->personality) == PER_LINUX32) {
+#endif
+ if (haddr & PA_PLABEL_FDESC) {
+ Elf32_Fdesc fdesc;
+ Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
+
+ err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
+
+ if (err)
+ goto give_sigsegv;
+
+ haddr = fdesc.addr;
+ regs->gr[19] = fdesc.gp;
+ }
+#ifdef __LP64__
+ } else {
+ Elf64_Fdesc fdesc;
+ Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
+
+ err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
+
+ if (err)
+ goto give_sigsegv;
+
+ haddr = fdesc.addr;
+ regs->gr[19] = fdesc.gp;
+ DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
+ haddr, regs->gr[19], in_syscall);
+ }
+#endif
+
+ /* The syscall return path will create IAOQ values from r31.
+ */
+ sigframe_size = PARISC_RT_SIGFRAME_SIZE;
+#ifdef __LP64__
+ if(personality(current->personality) == PER_LINUX32)
+ sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
+#endif
+ if (in_syscall) {
+ regs->gr[31] = haddr;
+#ifdef __LP64__
+ if(personality(current->personality) == PER_LINUX)
+ sigframe_size |= 1;
+#endif
+ } else {
+ unsigned long psw = USER_PSW;
+#ifdef __LP64__
+ if(personality(current->personality) == PER_LINUX)
+ psw |= PSW_W;
+#endif
+
+ /* If we are singlestepping, arrange a trap to be delivered
+ when we return to userspace. Note the semantics -- we
+ should trap before the first insn in the handler is
+ executed. Ref:
+ http://sources.redhat.com/ml/gdb/2004-11/msg00245.html
+ */
+ if (pa_psw(current)->r) {
+ pa_psw(current)->r = 0;
+ psw |= PSW_R;
+ mtctl(-1, 0);
+ }
+
+ regs->gr[0] = psw;
+ regs->iaoq[0] = haddr | 3;
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ }
+
+ regs->gr[2] = rp; /* userland return pointer */
+ regs->gr[26] = sig; /* signal number */
+
+#ifdef __LP64__
+ if(personality(current->personality) == PER_LINUX32){
+ regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
+ regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */
+ } else
+#endif
+ {
+ regs->gr[25] = A(&frame->info); /* siginfo pointer */
+ regs->gr[24] = A(&frame->uc); /* ucontext pointer */
+ }
+
+ DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
+ regs->gr[30], sigframe_size,
+ regs->gr[30] + sigframe_size);
+ /* Raise the user stack pointer to make a proper call frame. */
+ regs->gr[30] = (A(frame) + sigframe_size);
+
+
+ DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
+ current->comm, current->pid, frame, regs->gr[30],
+ regs->iaoq[0], regs->iaoq[1], rp);
+
+ return 1;
+
+give_sigsegv:
+ DBG(1,"setup_rt_frame: sending SIGSEGV\n");
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SI_KERNEL;
+ si.si_pid = current->pid;
+ si.si_uid = current->uid;
+ si.si_addr = frame;
+ force_sig_info(SIGSEGV, &si, current);
+ return 0;
+}
+
+/*
+ * OK, we're invoking a handler.
+ */
+
+static long
+handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+ sigset_t *oldset, struct pt_regs *regs, int in_syscall)
+{
+ DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
+ sig, ka, info, oldset, regs);
+
+ /* Set up the stack frame */
+ if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
+ return 0;
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+ return 1;
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * We need to be able to restore the syscall arguments (r21-r26) to
+ * restart syscalls. Thus, the syscall path should save them in the
+ * pt_regs structure (it's okay to do so since they are caller-save
+ * registers). As noted below, the syscall number gets restored for
+ * us due to the magic of delayed branching.
+ */
+
+asmlinkage int
+do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
+{
+ siginfo_t info;
+ struct k_sigaction ka;
+ int signr;
+
+ DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
+ oldset, regs, regs->sr[7], in_syscall);
+
+ /* Everyone else checks to see if they are in kernel mode at
+ this point and exits if that's the case. I'm not sure why
+ we would be called in that case, but for some reason we
+ are. */
+
+ if (!oldset)
+ oldset = &current->blocked;
+
+ DBG(1,"do_signal: oldset %08lx / %08lx\n",
+ oldset->sig[0], oldset->sig[1]);
+
+
+ /* May need to force signal if handle_signal failed to deliver */
+ while (1) {
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
+
+ if (signr <= 0)
+ break;
+
+ /* Restart a system call if necessary. */
+ if (in_syscall) {
+ /* Check the return code */
+ switch (regs->gr[28]) {
+ case -ERESTART_RESTARTBLOCK:
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+ case -ERESTARTNOHAND:
+ DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
+ regs->gr[28] = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (!(ka.sa.sa_flags & SA_RESTART)) {
+ DBG(1,"ERESTARTSYS: putting -EINTR\n");
+ regs->gr[28] = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ /* A syscall is just a branch, so all
+ we have to do is fiddle the return pointer. */
+ regs->gr[31] -= 8; /* delayed branching */
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+ break;
+ }
+ }
+ /* Whee! Actually deliver the signal. If the
+ delivery failed, we need to continue to iterate in
+ this loop so we can deliver the SIGSEGV... */
+ if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) {
+ DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
+ regs->gr[28]);
+ return 1;
+ }
+ }
+ /* end of while(1) looping forever if we can't force a signal */
+
+ /* Did we come from a system call? */
+ if (in_syscall) {
+ /* Restart the system call - no handlers present */
+ if (regs->gr[28] == -ERESTART_RESTARTBLOCK) {
+ unsigned int *usp = (unsigned int *)regs->gr[30];
+
+ /* Setup a trampoline to restart the syscall
+ * with __NR_restart_syscall
+ *
+ * 0: <return address (orig r31)>
+ * 4: <2nd half for 64-bit>
+ * 8: ldw 0(%sp), %r31
+ * 12: be 0x100(%sr2, %r0)
+ * 16: ldi __NR_restart_syscall, %r20
+ */
+#ifndef __LP64__
+ put_user(regs->gr[31], &usp[0]);
+ put_user(0x0fc0109f, &usp[2]);
+#else
+ put_user(regs->gr[31] >> 32, &usp[0]);
+ put_user(regs->gr[31] & 0xffffffff, &usp[1]);
+ put_user(0x0fc010df, &usp[2]);
+#endif
+ put_user(0xe0008200, &usp[3]);
+ put_user(0x34140000, &usp[4]);
+
+ /* Stack is 64-byte aligned, and we only
+ * need to flush 1 cache line */
+ asm("fdc 0(%%sr3, %0)\n"
+ "fic 0(%%sr3, %0)\n"
+ "sync\n"
+ : : "r"(regs->gr[30]));
+
+ regs->gr[31] = regs->gr[30] + 8;
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+ } else if (regs->gr[28] == -ERESTARTNOHAND ||
+ regs->gr[28] == -ERESTARTSYS ||
+ regs->gr[28] == -ERESTARTNOINTR) {
+ /* Hooray for delayed branching. We don't
+ have to restore %r20 (the system call
+ number) because it gets loaded in the delay
+ slot of the branch external instruction. */
+ regs->gr[31] -= 8;
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+ }
+ }
+
+ DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
+ regs->gr[28]);
+
+ return 0;
+}
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
new file mode 100644
index 000000000000..0792e20efef3
--- /dev/null
+++ b/arch/parisc/kernel/signal32.c
@@ -0,0 +1,400 @@
+/* Signal support for 32-bit kernel builds
+ *
+ * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
+ * Code was mostly borrowed from kernel/signal.c.
+ * See kernel/signal.c for additional Copyrights.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/compat.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+
+#include <asm/compat_signal.h>
+#include <asm/uaccess.h>
+
+#include "signal32.h"
+#include "sys32.h"
+
+#define DEBUG_COMPAT_SIG 0
+#define DEBUG_COMPAT_SIG_LEVEL 2
+
+#if DEBUG_COMPAT_SIG
+#define DBG(LEVEL, ...) \
+ ((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
+ ? printk(__VA_ARGS__) : (void) 0)
+#else
+#define DBG(LEVEL, ...)
+#endif
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+inline void
+sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
+{
+ s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
+}
+
+inline void
+sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
+{
+ s32->sig[0] = s64->sig[0] & 0xffffffffUL;
+ s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
+}
+
+static int
+put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
+{
+ compat_sigset_t s;
+
+ if (sz != sizeof *set) panic("put_sigset32()");
+ sigset_64to32(&s, set);
+
+ return copy_to_user(up, &s, sizeof s);
+}
+
+static int
+get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
+{
+ compat_sigset_t s;
+ int r;
+
+ if (sz != sizeof *set) panic("put_sigset32()");
+
+ if ((r = copy_from_user(&s, up, sz)) == 0) {
+ sigset_32to64(set, &s);
+ }
+
+ return r;
+}
+
+int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
+ unsigned int sigsetsize)
+{
+ sigset_t old_set, new_set;
+ int ret;
+
+ if (set && get_sigset32(set, &new_set, sigsetsize))
+ return -EFAULT;
+
+ KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL,
+ oset ? (sigset_t __user *)&old_set : NULL, sigsetsize);
+
+ if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
+ return -EFAULT;
+
+ return ret;
+}
+
+
+int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize)
+{
+ int ret;
+ sigset_t set;
+
+ KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize);
+
+ if (!ret && put_sigset32(uset, &set, sigsetsize))
+ return -EFAULT;
+
+ return ret;
+}
+
+long
+sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact,
+ size_t sigsetsize)
+{
+ struct k_sigaction32 new_sa32, old_sa32;
+ struct k_sigaction new_sa, old_sa;
+ int ret = -EINVAL;
+
+ if (act) {
+ if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
+ return -EFAULT;
+ new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
+ new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
+ sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
+
+ if (!ret && oact) {
+ sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
+ old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
+ old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
+ if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
+ return -EFAULT;
+ }
+ return ret;
+}
+
+int
+do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp)
+{
+ compat_stack_t ss32, oss32;
+ stack_t ss, oss;
+ stack_t *ssp = NULL, *ossp = NULL;
+ int ret;
+
+ if (uss32) {
+ if (copy_from_user(&ss32, uss32, sizeof ss32))
+ return -EFAULT;
+
+ ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp;
+ ss.ss_flags = ss32.ss_flags;
+ ss.ss_size = ss32.ss_size;
+
+ ssp = &ss;
+ }
+
+ if (uoss32)
+ ossp = &oss;
+
+ KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp);
+
+ if (!ret && uoss32) {
+ oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
+ oss32.ss_flags = oss.ss_flags;
+ oss32.ss_size = oss.ss_size;
+ if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
+long
+restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
+ struct pt_regs *regs)
+{
+ long err = 0;
+ compat_uint_t compat_reg;
+ compat_uint_t compat_regt;
+ int regn;
+
+ /* When loading 32-bit values into 64-bit registers make
+ sure to clear the upper 32-bits */
+ DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
+ DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
+ DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
+ for(regn=0; regn < 32; regn++){
+ err |= __get_user(compat_reg,&sc->sc_gr[regn]);
+ regs->gr[regn] = compat_reg;
+ /* Load upper half */
+ err |= __get_user(compat_regt,&rf->rf_gr[regn]);
+ regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
+ DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n",
+ regn, regs->gr[regn], compat_regt, compat_reg);
+ }
+ DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
+ /* XXX: BE WARNED FR's are 64-BIT! */
+ err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
+
+ /* Better safe than sorry, pass __get_user two things of
+ the same size and let gcc do the upward conversion to
+ 64-bits */
+ err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
+ /* Load upper half */
+ err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
+ regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
+ DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
+ DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n",
+ &sc->sc_iaoq[0], compat_reg);
+
+ err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
+ /* Load upper half */
+ err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
+ regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
+ DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
+ DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n",
+ &sc->sc_iaoq[1],compat_reg);
+ DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n",
+ regs->iaoq[0],regs->iaoq[1]);
+
+ err |= __get_user(compat_reg, &sc->sc_iasq[0]);
+ /* Load the upper half for iasq */
+ err |= __get_user(compat_regt, &rf->rf_iasq[0]);
+ regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
+ DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
+
+ err |= __get_user(compat_reg, &sc->sc_iasq[1]);
+ /* Load the upper half for iasq */
+ err |= __get_user(compat_regt, &rf->rf_iasq[1]);
+ regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
+ DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
+ DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n",
+ regs->iasq[0],regs->iasq[1]);
+
+ err |= __get_user(compat_reg, &sc->sc_sar);
+ /* Load the upper half for sar */
+ err |= __get_user(compat_regt, &rf->rf_sar);
+ regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;
+ DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);
+ DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);
+ DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
+
+ return err;
+}
+
+/*
+ * Set up the sigcontext structure for this process.
+ * This is not an easy task if the kernel is 64-bit, it will require
+ * that we examine the process personality to determine if we need to
+ * truncate for a 32-bit userspace.
+ */
+long
+setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
+ struct pt_regs *regs, int in_syscall)
+{
+ compat_int_t flags = 0;
+ long err = 0;
+ compat_uint_t compat_reg;
+ compat_uint_t compat_regb;
+ int regn;
+
+ if (on_sig_stack((unsigned long) sc))
+ flags |= PARISC_SC_FLAG_ONSTACK;
+
+ if (in_syscall) {
+
+ DBG(1,"setup_sigcontext32: in_syscall\n");
+
+ flags |= PARISC_SC_FLAG_IN_SYSCALL;
+ /* Truncate gr31 */
+ compat_reg = (compat_uint_t)(regs->gr[31]);
+ /* regs->iaoq is undefined in the syscall return path */
+ err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
+ DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
+ &sc->sc_iaoq[0], compat_reg);
+
+ /* Store upper half */
+ compat_reg = (compat_uint_t)(regs->gr[32] >> 32);
+ err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
+ DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
+
+
+ compat_reg = (compat_uint_t)(regs->gr[31]+4);
+ err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
+ DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
+ &sc->sc_iaoq[1], compat_reg);
+ /* Store upper half */
+ compat_reg = (compat_uint_t)((regs->gr[32]+4) >> 32);
+ err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
+ DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
+
+ /* Truncate sr3 */
+ compat_reg = (compat_uint_t)(regs->sr[3]);
+ err |= __put_user(compat_reg, &sc->sc_iasq[0]);
+ err |= __put_user(compat_reg, &sc->sc_iasq[1]);
+
+ /* Store upper half */
+ compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
+ err |= __put_user(compat_reg, &rf->rf_iasq[0]);
+ err |= __put_user(compat_reg, &rf->rf_iasq[1]);
+
+ DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
+ DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
+ DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",
+ regs->gr[31], regs->gr[31]+4);
+
+ } else {
+
+ compat_reg = (compat_uint_t)(regs->iaoq[0]);
+ err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
+ DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
+ &sc->sc_iaoq[0], compat_reg);
+ /* Store upper half */
+ compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
+ err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
+ DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
+
+ compat_reg = (compat_uint_t)(regs->iaoq[1]);
+ err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
+ DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
+ &sc->sc_iaoq[1], compat_reg);
+ /* Store upper half */
+ compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
+ err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
+ DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
+
+
+ compat_reg = (compat_uint_t)(regs->iasq[0]);
+ err |= __put_user(compat_reg, &sc->sc_iasq[0]);
+ DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
+ &sc->sc_iasq[0], compat_reg);
+ /* Store upper half */
+ compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
+ err |= __put_user(compat_reg, &rf->rf_iasq[0]);
+ DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
+
+
+ compat_reg = (compat_uint_t)(regs->iasq[1]);
+ err |= __put_user(compat_reg, &sc->sc_iasq[1]);
+ DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
+ &sc->sc_iasq[1], compat_reg);
+ /* Store upper half */
+ compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
+ err |= __put_user(compat_reg, &rf->rf_iasq[1]);
+ DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
+
+ /* Print out the IAOQ for debugging */
+ DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n",
+ regs->iaoq[0], regs->iaoq[1]);
+ }
+
+ err |= __put_user(flags, &sc->sc_flags);
+
+ DBG(1,"setup_sigcontext32: Truncating general registers.\n");
+
+ for(regn=0; regn < 32; regn++){
+ /* Truncate a general register */
+ compat_reg = (compat_uint_t)(regs->gr[regn]);
+ err |= __put_user(compat_reg, &sc->sc_gr[regn]);
+ /* Store upper half */
+ compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
+ err |= __put_user(compat_regb, &rf->rf_gr[regn]);
+
+ /* DEBUG: Write out the "upper / lower" register data */
+ DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn,
+ compat_regb, compat_reg);
+ }
+
+ /* Copy the floating point registers (same size)
+ XXX: BE WARNED FR's are 64-BIT! */
+ DBG(1,"setup_sigcontext32: Copying from regs to sc, "
+ "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
+ sizeof(regs->fr), sizeof(sc->sc_fr));
+ err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
+
+ compat_reg = (compat_uint_t)(regs->sar);
+ err |= __put_user(compat_reg, &sc->sc_sar);
+ DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
+ /* Store upper half */
+ compat_reg = (compat_uint_t)(regs->sar >> 32);
+ err |= __put_user(compat_reg, &rf->rf_sar);
+ DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
+ DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
+
+ return err;
+}
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
new file mode 100644
index 000000000000..4d1569e717cc
--- /dev/null
+++ b/arch/parisc/kernel/signal32.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
+ * Copyright (C) 2003 Carlos O'Donell <carlos at parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _PARISC64_KERNEL_SIGNAL32_H
+#define _PARISC64_KERNEL_SIGNAL32_H
+
+#include <linux/compat.h>
+#include <asm/compat_signal.h>
+#include <asm/compat_rt_sigframe.h>
+
+/* ELF32 signal handling */
+
+struct k_sigaction32 {
+ struct compat_sigaction sa;
+};
+
+void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
+void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
+int do_sigaltstack32 (const compat_stack_t __user *uss32,
+ compat_stack_t __user *uoss32, unsigned long sp);
+long restore_sigcontext32(struct compat_sigcontext __user *sc,
+ struct compat_regfile __user *rf,
+ struct pt_regs *regs);
+long setup_sigcontext32(struct compat_sigcontext __user *sc,
+ struct compat_regfile __user *rf,
+ struct pt_regs *regs, int in_syscall);
+
+#endif
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
new file mode 100644
index 000000000000..bcc7e83f5142
--- /dev/null
+++ b/arch/parisc/kernel/smp.c
@@ -0,0 +1,723 @@
+/*
+** SMP Support
+**
+** Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+** Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+** Copyright (C) 2001,2004 Grant Grundler <grundler@parisc-linux.org>
+**
+** Lots of stuff stolen from arch/alpha/kernel/smp.c
+** ...and then parisc stole from arch/ia64/kernel/smp.c. Thanks David! :^)
+**
+** Thanks to John Curry and Ullas Ponnadi. I learned alot from their work.
+** -grant (1/12/2001)
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+*/
+#undef ENTRY_SYS_CPUS /* syscall support for iCOD-like functionality */
+
+#include <linux/autoconf.h>
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/current.h>
+#include <asm/delay.h>
+#include <asm/pgalloc.h> /* for flush_tlb_all() proto/macro */
+
+#include <asm/io.h>
+#include <asm/irq.h> /* for CPU_IRQ_REGION and friends */
+#include <asm/mmu_context.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/unistd.h>
+#include <asm/cacheflush.h>
+
+#define kDEBUG 0
+
+DEFINE_SPINLOCK(smp_lock);
+
+volatile struct task_struct *smp_init_current_idle_task;
+
+static volatile int cpu_now_booting = 0; /* track which CPU is booting */
+
+static int parisc_max_cpus = 1;
+
+/* online cpus are ones that we've managed to bring up completely
+ * possible cpus are all valid cpu
+ * present cpus are all detected cpu
+ *
+ * On startup we bring up the "possible" cpus. Since we discover
+ * CPUs later, we add them as hotplug, so the possible cpu mask is
+ * empty in the beginning.
+ */
+
+cpumask_t cpu_online_map = CPU_MASK_NONE; /* Bitmap of online CPUs */
+cpumask_t cpu_possible_map = CPU_MASK_ALL; /* Bitmap of Present CPUs */
+
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_possible_map);
+
+
+struct smp_call_struct {
+ void (*func) (void *info);
+ void *info;
+ long wait;
+ atomic_t unstarted_count;
+ atomic_t unfinished_count;
+};
+static volatile struct smp_call_struct *smp_call_function_data;
+
+enum ipi_message_type {
+ IPI_NOP=0,
+ IPI_RESCHEDULE=1,
+ IPI_CALL_FUNC,
+ IPI_CPU_START,
+ IPI_CPU_STOP,
+ IPI_CPU_TEST
+};
+
+
+/********** SMP inter processor interrupt and communication routines */
+
+#undef PER_CPU_IRQ_REGION
+#ifdef PER_CPU_IRQ_REGION
+/* XXX REVISIT Ignore for now.
+** *May* need this "hook" to register IPI handler
+** once we have perCPU ExtIntr switch tables.
+*/
+static void
+ipi_init(int cpuid)
+{
+
+ /* If CPU is present ... */
+#ifdef ENTRY_SYS_CPUS
+ /* *and* running (not stopped) ... */
+#error iCOD support wants state checked here.
+#endif
+
+#error verify IRQ_OFFSET(IPI_IRQ) is ipi_interrupt() in new IRQ region
+
+ if(cpu_online(cpuid) )
+ {
+ switch_to_idle_task(current);
+ }
+
+ return;
+}
+#endif
+
+
+/*
+** Yoink this CPU from the runnable list...
+**
+*/
+static void
+halt_processor(void)
+{
+#ifdef ENTRY_SYS_CPUS
+#error halt_processor() needs rework
+/*
+** o migrate I/O interrupts off this CPU.
+** o leave IPI enabled - __cli() will disable IPI.
+** o leave CPU in online map - just change the state
+*/
+ cpu_data[this_cpu].state = STATE_STOPPED;
+ mark_bh(IPI_BH);
+#else
+ /* REVISIT : redirect I/O Interrupts to another CPU? */
+ /* REVISIT : does PM *know* this CPU isn't available? */
+ cpu_clear(smp_processor_id(), cpu_online_map);
+ local_irq_disable();
+ for (;;)
+ ;
+#endif
+}
+
+
+irqreturn_t
+ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int this_cpu = smp_processor_id();
+ struct cpuinfo_parisc *p = &cpu_data[this_cpu];
+ unsigned long ops;
+ unsigned long flags;
+
+ /* Count this now; we may make a call that never returns. */
+ p->ipi_count++;
+
+ mb(); /* Order interrupt and bit testing. */
+
+ for (;;) {
+ spin_lock_irqsave(&(p->lock),flags);
+ ops = p->pending_ipi;
+ p->pending_ipi = 0;
+ spin_unlock_irqrestore(&(p->lock),flags);
+
+ mb(); /* Order bit clearing and data access. */
+
+ if (!ops)
+ break;
+
+ while (ops) {
+ unsigned long which = ffz(~ops);
+
+ switch (which) {
+ case IPI_RESCHEDULE:
+#if (kDEBUG>=100)
+ printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu);
+#endif /* kDEBUG */
+ ops &= ~(1 << IPI_RESCHEDULE);
+ /*
+ * Reschedule callback. Everything to be
+ * done is done by the interrupt return path.
+ */
+ break;
+
+ case IPI_CALL_FUNC:
+#if (kDEBUG>=100)
+ printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu);
+#endif /* kDEBUG */
+ ops &= ~(1 << IPI_CALL_FUNC);
+ {
+ volatile struct smp_call_struct *data;
+ void (*func)(void *info);
+ void *info;
+ int wait;
+
+ data = smp_call_function_data;
+ func = data->func;
+ info = data->info;
+ wait = data->wait;
+
+ mb();
+ atomic_dec ((atomic_t *)&data->unstarted_count);
+
+ /* At this point, *data can't
+ * be relied upon.
+ */
+
+ (*func)(info);
+
+ /* Notify the sending CPU that the
+ * task is done.
+ */
+ mb();
+ if (wait)
+ atomic_dec ((atomic_t *)&data->unfinished_count);
+ }
+ break;
+
+ case IPI_CPU_START:
+#if (kDEBUG>=100)
+ printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu);
+#endif /* kDEBUG */
+ ops &= ~(1 << IPI_CPU_START);
+#ifdef ENTRY_SYS_CPUS
+ p->state = STATE_RUNNING;
+#endif
+ break;
+
+ case IPI_CPU_STOP:
+#if (kDEBUG>=100)
+ printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu);
+#endif /* kDEBUG */
+ ops &= ~(1 << IPI_CPU_STOP);
+#ifdef ENTRY_SYS_CPUS
+#else
+ halt_processor();
+#endif
+ break;
+
+ case IPI_CPU_TEST:
+#if (kDEBUG>=100)
+ printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu);
+#endif /* kDEBUG */
+ ops &= ~(1 << IPI_CPU_TEST);
+ break;
+
+ default:
+ printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n",
+ this_cpu, which);
+ ops &= ~(1 << which);
+ return IRQ_NONE;
+ } /* Switch */
+ } /* while (ops) */
+ }
+ return IRQ_HANDLED;
+}
+
+
+static inline void
+ipi_send(int cpu, enum ipi_message_type op)
+{
+ struct cpuinfo_parisc *p = &cpu_data[cpu];
+ unsigned long flags;
+
+ spin_lock_irqsave(&(p->lock),flags);
+ p->pending_ipi |= 1 << op;
+ gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa);
+ spin_unlock_irqrestore(&(p->lock),flags);
+}
+
+
+static inline void
+send_IPI_single(int dest_cpu, enum ipi_message_type op)
+{
+ if (dest_cpu == NO_PROC_ID) {
+ BUG();
+ return;
+ }
+
+ ipi_send(dest_cpu, op);
+}
+
+static inline void
+send_IPI_allbutself(enum ipi_message_type op)
+{
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (cpu_online(i) && i != smp_processor_id())
+ send_IPI_single(i, op);
+ }
+}
+
+
+inline void
+smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); }
+
+static inline void
+smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); }
+
+void
+smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); }
+
+
+/**
+ * Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <retry> If true, keep retrying until ready.
+ * <wait> If true, wait until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code.
+ *
+ * Does not return until remote CPUs are nearly ready to execute <func>
+ * or have executed.
+ */
+
+int
+smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
+{
+ struct smp_call_struct data;
+ unsigned long timeout;
+ static DEFINE_SPINLOCK(lock);
+ int retries = 0;
+
+ if (num_online_cpus() < 2)
+ return 0;
+
+ /* Can deadlock when called with interrupts disabled */
+ WARN_ON(irqs_disabled());
+
+ data.func = func;
+ data.info = info;
+ data.wait = wait;
+ atomic_set(&data.unstarted_count, num_online_cpus() - 1);
+ atomic_set(&data.unfinished_count, num_online_cpus() - 1);
+
+ if (retry) {
+ spin_lock (&lock);
+ while (smp_call_function_data != 0)
+ barrier();
+ }
+ else {
+ spin_lock (&lock);
+ if (smp_call_function_data) {
+ spin_unlock (&lock);
+ return -EBUSY;
+ }
+ }
+
+ smp_call_function_data = &data;
+ spin_unlock (&lock);
+
+ /* Send a message to all other CPUs and wait for them to respond */
+ send_IPI_allbutself(IPI_CALL_FUNC);
+
+ retry:
+ /* Wait for response */
+ timeout = jiffies + HZ;
+ while ( (atomic_read (&data.unstarted_count) > 0) &&
+ time_before (jiffies, timeout) )
+ barrier ();
+
+ if (atomic_read (&data.unstarted_count) > 0) {
+ printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d), try %d\n",
+ smp_processor_id(), ++retries);
+ goto retry;
+ }
+ /* We either got one or timed out. Release the lock */
+
+ mb();
+ smp_call_function_data = NULL;
+
+ while (wait && atomic_read (&data.unfinished_count) > 0)
+ barrier ();
+
+ return 0;
+}
+
+EXPORT_SYMBOL(smp_call_function);
+
+/*
+ * Flush all other CPU's tlb and then mine. Do this with on_each_cpu()
+ * as we want to ensure all TLB's flushed before proceeding.
+ */
+
+extern void flush_tlb_all_local(void);
+
+void
+smp_flush_tlb_all(void)
+{
+ on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
+}
+
+
+void
+smp_do_timer(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+ struct cpuinfo_parisc *data = &cpu_data[cpu];
+
+ if (!--data->prof_counter) {
+ data->prof_counter = data->prof_multiplier;
+ update_process_times(user_mode(regs));
+ }
+}
+
+/*
+ * Called by secondaries to update state and initialize CPU registers.
+ */
+static void __init
+smp_cpu_init(int cpunum)
+{
+ extern int init_per_cpu(int); /* arch/parisc/kernel/setup.c */
+ extern void init_IRQ(void); /* arch/parisc/kernel/irq.c */
+
+ /* Set modes and Enable floating point coprocessor */
+ (void) init_per_cpu(cpunum);
+
+ disable_sr_hashing();
+
+ mb();
+
+ /* Well, support 2.4 linux scheme as well. */
+ if (cpu_test_and_set(cpunum, cpu_online_map))
+ {
+ extern void machine_halt(void); /* arch/parisc.../process.c */
+
+ printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum);
+ machine_halt();
+ }
+
+ /* Initialise the idle task for this CPU */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+ if(current->mm)
+ BUG();
+ enter_lazy_tlb(&init_mm, current);
+
+ init_IRQ(); /* make sure no IRQ's are enabled or pending */
+}
+
+
+/*
+ * Slaves start using C here. Indirectly called from smp_slave_stext.
+ * Do what start_kernel() and main() do for boot strap processor (aka monarch)
+ */
+void __init smp_callin(void)
+{
+ int slave_id = cpu_now_booting;
+#if 0
+ void *istack;
+#endif
+
+ smp_cpu_init(slave_id);
+
+#if 0 /* NOT WORKING YET - see entry.S */
+ istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER);
+ if (istack == NULL) {
+ printk(KERN_CRIT "Failed to allocate interrupt stack for cpu %d\n",slave_id);
+ BUG();
+ }
+ mtctl(istack,31);
+#endif
+
+ flush_cache_all_local(); /* start with known state */
+ flush_tlb_all_local();
+
+ local_irq_enable(); /* Interrupts have been off until now */
+
+ cpu_idle(); /* Wait for timer to schedule some work */
+
+ /* NOTREACHED */
+ panic("smp_callin() AAAAaaaaahhhh....\n");
+}
+
+/*
+ * Bring one cpu online.
+ */
+int __init smp_boot_one_cpu(int cpuid)
+{
+ struct task_struct *idle;
+ long timeout;
+
+ /*
+ * Create an idle task for this CPU. Note the address wed* give
+ * to kernel_thread is irrelevant -- it's going to start
+ * where OS_BOOT_RENDEVZ vector in SAL says to start. But
+ * this gets all the other task-y sort of data structures set
+ * up like we wish. We need to pull the just created idle task
+ * off the run queue and stuff it into the init_tasks[] array.
+ * Sheesh . . .
+ */
+
+ idle = fork_idle(cpuid);
+ if (IS_ERR(idle))
+ panic("SMP: fork failed for CPU:%d", cpuid);
+
+ idle->thread_info->cpu = cpuid;
+
+ /* Let _start know what logical CPU we're booting
+ ** (offset into init_tasks[],cpu_data[])
+ */
+ cpu_now_booting = cpuid;
+
+ /*
+ ** boot strap code needs to know the task address since
+ ** it also contains the process stack.
+ */
+ smp_init_current_idle_task = idle ;
+ mb();
+
+ printk("Releasing cpu %d now, hpa=%lx\n", cpuid, cpu_data[cpuid].hpa);
+
+ /*
+ ** This gets PDC to release the CPU from a very tight loop.
+ **
+ ** From the PA-RISC 2.0 Firmware Architecture Reference Specification:
+ ** "The MEM_RENDEZ vector specifies the location of OS_RENDEZ which
+ ** is executed after receiving the rendezvous signal (an interrupt to
+ ** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the
+ ** contents of memory are valid."
+ */
+ gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, cpu_data[cpuid].hpa);
+ mb();
+
+ /*
+ * OK, wait a bit for that CPU to finish staggering about.
+ * Slave will set a bit when it reaches smp_cpu_init().
+ * Once the "monarch CPU" sees the bit change, it can move on.
+ */
+ for (timeout = 0; timeout < 10000; timeout++) {
+ if(cpu_online(cpuid)) {
+ /* Which implies Slave has started up */
+ cpu_now_booting = 0;
+ smp_init_current_idle_task = NULL;
+ goto alive ;
+ }
+ udelay(100);
+ barrier();
+ }
+
+ put_task_struct(idle);
+ idle = NULL;
+
+ printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);
+ return -1;
+
+alive:
+ /* Remember the Slave data */
+#if (kDEBUG>=100)
+ printk(KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n",
+ cpuid, timeout * 100);
+#endif /* kDEBUG */
+#ifdef ENTRY_SYS_CPUS
+ cpu_data[cpuid].state = STATE_RUNNING;
+#endif
+ return 0;
+}
+
+void __devinit smp_prepare_boot_cpu(void)
+{
+ int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */
+
+#ifdef ENTRY_SYS_CPUS
+ cpu_data[0].state = STATE_RUNNING;
+#endif
+
+ /* Setup BSP mappings */
+ printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor);
+
+ cpu_set(bootstrap_processor, cpu_online_map);
+ cpu_set(bootstrap_processor, cpu_present_map);
+}
+
+
+
+/*
+** inventory.c:do_inventory() hasn't yet been run and thus we
+** don't 'discover' the additional CPU's until later.
+*/
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ cpus_clear(cpu_present_map);
+ cpu_set(0, cpu_present_map);
+
+ parisc_max_cpus = max_cpus;
+ if (!max_cpus)
+ printk(KERN_INFO "SMP mode deactivated.\n");
+}
+
+
+void smp_cpus_done(unsigned int cpu_max)
+{
+ return;
+}
+
+
+int __devinit __cpu_up(unsigned int cpu)
+{
+ if (cpu != 0 && cpu < parisc_max_cpus)
+ smp_boot_one_cpu(cpu);
+
+ return cpu_online(cpu) ? 0 : -ENOSYS;
+}
+
+
+
+#ifdef ENTRY_SYS_CPUS
+/* Code goes along with:
+** entry.s: ENTRY_NAME(sys_cpus) / * 215, for cpu stat * /
+*/
+int sys_cpus(int argc, char **argv)
+{
+ int i,j=0;
+ extern int current_pid(int cpu);
+
+ if( argc > 2 ) {
+ printk("sys_cpus:Only one argument supported\n");
+ return (-1);
+ }
+ if ( argc == 1 ){
+
+#ifdef DUMP_MORE_STATE
+ for(i=0; i<NR_CPUS; i++) {
+ int cpus_per_line = 4;
+ if(cpu_online(i)) {
+ if (j++ % cpus_per_line)
+ printk(" %3d",i);
+ else
+ printk("\n %3d",i);
+ }
+ }
+ printk("\n");
+#else
+ printk("\n 0\n");
+#endif
+ } else if((argc==2) && !(strcmp(argv[1],"-l"))) {
+ printk("\nCPUSTATE TASK CPUNUM CPUID HARDCPU(HPA)\n");
+#ifdef DUMP_MORE_STATE
+ for(i=0;i<NR_CPUS;i++) {
+ if (!cpu_online(i))
+ continue;
+ if (cpu_data[i].cpuid != NO_PROC_ID) {
+ switch(cpu_data[i].state) {
+ case STATE_RENDEZVOUS:
+ printk("RENDEZVS ");
+ break;
+ case STATE_RUNNING:
+ printk((current_pid(i)!=0) ? "RUNNING " : "IDLING ");
+ break;
+ case STATE_STOPPED:
+ printk("STOPPED ");
+ break;
+ case STATE_HALTED:
+ printk("HALTED ");
+ break;
+ default:
+ printk("%08x?", cpu_data[i].state);
+ break;
+ }
+ if(cpu_online(i)) {
+ printk(" %4d",current_pid(i));
+ }
+ printk(" %6d",cpu_number_map(i));
+ printk(" %5d",i);
+ printk(" 0x%lx\n",cpu_data[i].hpa);
+ }
+ }
+#else
+ printk("\n%s %4d 0 0 --------",
+ (current->pid)?"RUNNING ": "IDLING ",current->pid);
+#endif
+ } else if ((argc==2) && !(strcmp(argv[1],"-s"))) {
+#ifdef DUMP_MORE_STATE
+ printk("\nCPUSTATE CPUID\n");
+ for (i=0;i<NR_CPUS;i++) {
+ if (!cpu_online(i))
+ continue;
+ if (cpu_data[i].cpuid != NO_PROC_ID) {
+ switch(cpu_data[i].state) {
+ case STATE_RENDEZVOUS:
+ printk("RENDEZVS");break;
+ case STATE_RUNNING:
+ printk((current_pid(i)!=0) ? "RUNNING " : "IDLING");
+ break;
+ case STATE_STOPPED:
+ printk("STOPPED ");break;
+ case STATE_HALTED:
+ printk("HALTED ");break;
+ default:
+ }
+ printk(" %5d\n",i);
+ }
+ }
+#else
+ printk("\n%s CPU0",(current->pid==0)?"RUNNING ":"IDLING ");
+#endif
+ } else {
+ printk("sys_cpus:Unknown request\n");
+ return (-1);
+ }
+ return 0;
+}
+#endif /* ENTRY_SYS_CPUS */
+
+#ifdef CONFIG_PROC_FS
+int __init
+setup_profiling_timer(unsigned int multiplier)
+{
+ return -EINVAL;
+}
+#endif
diff --git a/arch/parisc/kernel/sys32.h b/arch/parisc/kernel/sys32.h
new file mode 100644
index 000000000000..06c2090cfaba
--- /dev/null
+++ b/arch/parisc/kernel/sys32.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2002 Richard Hirst <rhirst at parisc-linux.org>
+ * Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org>
+ * Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _PARISC64_KERNEL_SYS32_H
+#define _PARISC64_KERNEL_SYS32_H
+
+#include <linux/compat.h>
+
+/* Call a kernel syscall which will use kernel space instead of user
+ * space for its copy_to/from_user.
+ */
+#define KERNEL_SYSCALL(ret, syscall, args...) \
+{ \
+ mm_segment_t old_fs = get_fs(); \
+ set_fs(KERNEL_DS); \
+ ret = syscall(args); \
+ set_fs (old_fs); \
+}
+
+#ifdef CONFIG_COMPAT
+
+typedef __u32 __sighandler_t32;
+
+struct sigaction32 {
+ __sighandler_t32 sa_handler;
+ unsigned int sa_flags;
+ compat_sigset_t sa_mask; /* mask last for extensibility */
+};
+
+#endif
+
+#endif
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
new file mode 100644
index 000000000000..7958cd8c8bf8
--- /dev/null
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -0,0 +1,253 @@
+
+/*
+ * PARISC specific syscalls
+ *
+ * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
+ * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
+ * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <asm/uaccess.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/shm.h>
+#include <linux/smp_lock.h>
+#include <linux/syscalls.h>
+
+int sys_pipe(int __user *fildes)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2*sizeof(int)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+static unsigned long get_unshared_area(unsigned long addr, unsigned long len)
+{
+ struct vm_area_struct *vma;
+
+ addr = PAGE_ALIGN(addr);
+
+ for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (TASK_SIZE - len < addr)
+ return -ENOMEM;
+ if (!vma || addr + len <= vma->vm_start)
+ return addr;
+ addr = vma->vm_end;
+ }
+}
+
+#define DCACHE_ALIGN(addr) (((addr) + (SHMLBA - 1)) &~ (SHMLBA - 1))
+
+/*
+ * We need to know the offset to use. Old scheme was to look for
+ * existing mapping and use the same offset. New scheme is to use the
+ * address of the kernel data structure as the seed for the offset.
+ * We'll see how that works...
+ *
+ * The mapping is cacheline aligned, so there's no information in the bottom
+ * few bits of the address. We're looking for 10 bits (4MB / 4k), so let's
+ * drop the bottom 8 bits and use bits 8-17.
+ */
+static int get_offset(struct address_space *mapping)
+{
+ int offset = (unsigned long) mapping << (PAGE_SHIFT - 8);
+ return offset & 0x3FF000;
+}
+
+static unsigned long get_shared_area(struct address_space *mapping,
+ unsigned long addr, unsigned long len, unsigned long pgoff)
+{
+ struct vm_area_struct *vma;
+ int offset = mapping ? get_offset(mapping) : 0;
+
+ addr = DCACHE_ALIGN(addr - offset) + offset;
+
+ for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (TASK_SIZE - len < addr)
+ return -ENOMEM;
+ if (!vma || addr + len <= vma->vm_start)
+ return addr;
+ addr = DCACHE_ALIGN(vma->vm_end - offset) + offset;
+ if (addr < vma->vm_end) /* handle wraparound */
+ return -ENOMEM;
+ }
+}
+
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ if (len > TASK_SIZE)
+ return -ENOMEM;
+ if (!addr)
+ addr = TASK_UNMAPPED_BASE;
+
+ if (filp) {
+ addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
+ } else if(flags & MAP_SHARED) {
+ addr = get_shared_area(NULL, addr, len, pgoff);
+ } else {
+ addr = get_unshared_area(addr, len);
+ }
+ return addr;
+}
+
+static unsigned long do_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags, unsigned long fd,
+ unsigned long pgoff)
+{
+ struct file * file = NULL;
+ unsigned long error = -EBADF;
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ down_write(&current->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(&current->mm->mmap_sem);
+
+ if (file != NULL)
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags, unsigned long fd,
+ unsigned long pgoff)
+{
+ /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
+ we have. */
+ return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
+}
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags, unsigned long fd,
+ unsigned long offset)
+{
+ if (!(offset & ~PAGE_MASK)) {
+ return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+ } else {
+ return -EINVAL;
+ }
+}
+
+long sys_shmat_wrapper(int shmid, char __user *shmaddr, int shmflag)
+{
+ unsigned long raddr;
+ int r;
+
+ r = do_shmat(shmid, shmaddr, shmflag, &raddr);
+ if (r < 0)
+ return r;
+ return raddr;
+}
+
+/* Fucking broken ABI */
+
+#ifdef CONFIG_64BIT
+asmlinkage long parisc_truncate64(const char __user * path,
+ unsigned int high, unsigned int low)
+{
+ return sys_truncate(path, (long)high << 32 | low);
+}
+
+asmlinkage long parisc_ftruncate64(unsigned int fd,
+ unsigned int high, unsigned int low)
+{
+ return sys_ftruncate(fd, (long)high << 32 | low);
+}
+
+/* stubs for the benefit of the syscall_table since truncate64 and truncate
+ * are identical on LP64 */
+asmlinkage long sys_truncate64(const char __user * path, unsigned long length)
+{
+ return sys_truncate(path, length);
+}
+asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length)
+{
+ return sys_ftruncate(fd, length);
+}
+asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ return sys_fcntl(fd, cmd, arg);
+}
+#else
+
+asmlinkage long parisc_truncate64(const char __user * path,
+ unsigned int high, unsigned int low)
+{
+ return sys_truncate64(path, (loff_t)high << 32 | low);
+}
+
+asmlinkage long parisc_ftruncate64(unsigned int fd,
+ unsigned int high, unsigned int low)
+{
+ return sys_ftruncate64(fd, (loff_t)high << 32 | low);
+}
+#endif
+
+asmlinkage ssize_t parisc_pread64(unsigned int fd, char __user *buf, size_t count,
+ unsigned int high, unsigned int low)
+{
+ return sys_pread64(fd, buf, count, (loff_t)high << 32 | low);
+}
+
+asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char __user *buf,
+ size_t count, unsigned int high, unsigned int low)
+{
+ return sys_pwrite64(fd, buf, count, (loff_t)high << 32 | low);
+}
+
+asmlinkage ssize_t parisc_readahead(int fd, unsigned int high, unsigned int low,
+ size_t count)
+{
+ return sys_readahead(fd, (loff_t)high << 32 | low, count);
+}
+
+asmlinkage long parisc_fadvise64_64(int fd,
+ unsigned int high_off, unsigned int low_off,
+ unsigned int high_len, unsigned int low_len, int advice)
+{
+ return sys_fadvise64_64(fd, (loff_t)high_off << 32 | low_off,
+ (loff_t)high_len << 32 | low_len, advice);
+}
+
+asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag)
+{
+ return -ENOMEM;
+}
+
+asmlinkage int sys_free_hugepages(unsigned long addr)
+{
+ return -EINVAL;
+}
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
new file mode 100644
index 000000000000..613569018410
--- /dev/null
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -0,0 +1,720 @@
+/*
+ * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls.
+ *
+ * Copyright (C) 2000-2001 Hewlett Packard Company
+ * Copyright (C) 2000 John Marvin
+ * Copyright (C) 2001 Matthew Wilcox
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * environment. Based heavily on sys_ia32.c and sys_sparc32.c.
+ */
+
+#include <linux/config.h>
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/file.h>
+#include <linux/signal.h>
+#include <linux/resource.h>
+#include <linux/times.h>
+#include <linux/utsname.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/slab.h>
+#include <linux/uio.h>
+#include <linux/nfs_fs.h>
+#include <linux/ncp_fs.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/cache.h>
+#include <linux/nfsd/xdr.h>
+#include <linux/nfsd/syscall.h>
+#include <linux/poll.h>
+#include <linux/personality.h>
+#include <linux/stat.h>
+#include <linux/highmem.h>
+#include <linux/highuid.h>
+#include <linux/mman.h>
+#include <linux/binfmts.h>
+#include <linux/namei.h>
+#include <linux/vfs.h>
+#include <linux/ptrace.h>
+#include <linux/swap.h>
+#include <linux/syscalls.h>
+
+#include <asm/types.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <asm/mmu_context.h>
+
+#include "sys32.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x) printk x
+#else
+#define DBG(x)
+#endif
+
+/*
+ * sys32_execve() executes a new program.
+ */
+
+asmlinkage int sys32_execve(struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
+ filename = getname((const char __user *) regs->gr[26]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = compat_do_execve(filename, compat_ptr(regs->gr[25]),
+ compat_ptr(regs->gr[24]), regs);
+ if (error == 0) {
+ task_lock(current);
+ current->ptrace &= ~PT_DTRACE;
+ task_unlock(current);
+ }
+ putname(filename);
+out:
+
+ return error;
+}
+
+asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
+ int r22, int r21, int r20)
+{
+ printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n",
+ current->comm, current->pid, r20);
+ return -ENOSYS;
+}
+
+#ifdef CONFIG_SYSCTL
+
+struct __sysctl_args32 {
+ u32 name;
+ int nlen;
+ u32 oldval;
+ u32 oldlenp;
+ u32 newval;
+ u32 newlen;
+ u32 __unused[4];
+};
+
+asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
+{
+ struct __sysctl_args32 tmp;
+ int error;
+ unsigned int oldlen32;
+ size_t oldlen, *oldlenp = NULL;
+ unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
+ extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen);
+
+ DBG(("sysctl32(%p)\n", args));
+
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
+ return -EFAULT;
+
+ if (tmp.oldval && tmp.oldlenp) {
+ /* Duh, this is ugly and might not work if sysctl_args
+ is in read-only memory, but do_sysctl does indirectly
+ a lot of uaccess in both directions and we'd have to
+ basically copy the whole sysctl.c here, and
+ glibc's __sysctl uses rw memory for the structure
+ anyway. */
+ /* a possibly better hack than this, which will avoid the
+ * problem if the struct is read only, is to push the
+ * 'oldlen' value out to the user's stack instead. -PB
+ */
+ if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
+ return -EFAULT;
+ oldlen = oldlen32;
+ if (put_user(oldlen, (size_t *)addr))
+ return -EFAULT;
+ oldlenp = (size_t *)addr;
+ }
+
+ lock_kernel();
+ error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval,
+ oldlenp, (void *)(u64)tmp.newval, tmp.newlen);
+ unlock_kernel();
+ if (oldlenp) {
+ if (!error) {
+ if (get_user(oldlen, (size_t *)addr)) {
+ error = -EFAULT;
+ } else {
+ oldlen32 = oldlen;
+ if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
+ error = -EFAULT;
+ }
+ }
+ if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+#endif /* CONFIG_SYSCTL */
+
+asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
+ struct compat_timespec __user *interval)
+{
+ struct timespec t;
+ int ret;
+
+ KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t);
+ if (put_compat_timespec(&t, interval))
+ return -EFAULT;
+ return ret;
+}
+
+static int
+put_compat_timeval(struct compat_timeval __user *u, struct timeval *t)
+{
+ struct compat_timeval t32;
+ t32.tv_sec = t->tv_sec;
+ t32.tv_usec = t->tv_usec;
+ return copy_to_user(u, &t32, sizeof t32);
+}
+
+static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
+{
+ long usec;
+
+ if (__get_user(o->tv_sec, &i->tv_sec))
+ return -EFAULT;
+ if (__get_user(usec, &i->tv_usec))
+ return -EFAULT;
+ o->tv_nsec = usec * 1000;
+ return 0;
+}
+
+asmlinkage int
+sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
+{
+ extern void do_gettimeofday(struct timeval *tv);
+
+ if (tv) {
+ struct timeval ktv;
+ do_gettimeofday(&ktv);
+ if (put_compat_timeval(tv, &ktv))
+ return -EFAULT;
+ }
+ if (tz) {
+ extern struct timezone sys_tz;
+ if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+asmlinkage
+int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
+{
+ struct timespec kts;
+ struct timezone ktz;
+
+ if (tv) {
+ if (get_ts32(&kts, tv))
+ return -EFAULT;
+ }
+ if (tz) {
+ if (copy_from_user(&ktz, tz, sizeof(ktz)))
+ return -EFAULT;
+ }
+
+ return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
+}
+
+int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
+{
+ int err;
+
+ if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
+ !new_valid_dev(stat->rdev))
+ return -EOVERFLOW;
+
+ err = put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
+ err |= put_user(stat->ino, &statbuf->st_ino);
+ err |= put_user(stat->mode, &statbuf->st_mode);
+ err |= put_user(stat->nlink, &statbuf->st_nlink);
+ err |= put_user(0, &statbuf->st_reserved1);
+ err |= put_user(0, &statbuf->st_reserved2);
+ err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
+ err |= put_user(stat->size, &statbuf->st_size);
+ err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
+ err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
+ err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
+ err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
+ err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
+ err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
+ err |= put_user(stat->blksize, &statbuf->st_blksize);
+ err |= put_user(stat->blocks, &statbuf->st_blocks);
+ err |= put_user(0, &statbuf->__unused1);
+ err |= put_user(0, &statbuf->__unused2);
+ err |= put_user(0, &statbuf->__unused3);
+ err |= put_user(0, &statbuf->__unused4);
+ err |= put_user(0, &statbuf->__unused5);
+ err |= put_user(0, &statbuf->st_fstype); /* not avail */
+ err |= put_user(0, &statbuf->st_realdev); /* not avail */
+ err |= put_user(0, &statbuf->st_basemode); /* not avail */
+ err |= put_user(0, &statbuf->st_spareshort);
+ err |= put_user(stat->uid, &statbuf->st_uid);
+ err |= put_user(stat->gid, &statbuf->st_gid);
+ err |= put_user(0, &statbuf->st_spare4[0]);
+ err |= put_user(0, &statbuf->st_spare4[1]);
+ err |= put_user(0, &statbuf->st_spare4[2]);
+
+ return err;
+}
+
+struct linux32_dirent {
+ u32 d_ino;
+ compat_off_t d_off;
+ u16 d_reclen;
+ char d_name[1];
+};
+
+struct old_linux32_dirent {
+ u32 d_ino;
+ u32 d_offset;
+ u16 d_namlen;
+ char d_name[1];
+};
+
+struct getdents32_callback {
+ struct linux32_dirent __user * current_dir;
+ struct linux32_dirent __user * previous;
+ int count;
+ int error;
+};
+
+struct readdir32_callback {
+ struct old_linux32_dirent __user * dirent;
+ int count;
+};
+
+#define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
+static int
+filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
+ unsigned int d_type)
+{
+ struct linux32_dirent __user * dirent;
+ struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
+ int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
+
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
+ dirent = buf->previous;
+ if (dirent)
+ put_user(offset, &dirent->d_off);
+ dirent = buf->current_dir;
+ buf->previous = dirent;
+ put_user(ino, &dirent->d_ino);
+ put_user(reclen, &dirent->d_reclen);
+ copy_to_user(dirent->d_name, name, namlen);
+ put_user(0, dirent->d_name + namlen);
+ dirent = ((void __user *)dirent) + reclen;
+ buf->current_dir = dirent;
+ buf->count -= reclen;
+ return 0;
+}
+
+asmlinkage long
+sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
+{
+ struct file * file;
+ struct linux32_dirent __user * lastdirent;
+ struct getdents32_callback buf;
+ int error;
+
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ buf.current_dir = (struct linux32_dirent __user *) dirent;
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
+
+ error = vfs_readdir(file, filldir32, &buf);
+ if (error < 0)
+ goto out_putf;
+ error = buf.error;
+ lastdirent = buf.previous;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
+ }
+
+out_putf:
+ fput(file);
+out:
+ return error;
+}
+
+static int
+fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
+ unsigned int d_type)
+{
+ struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
+ struct old_linux32_dirent __user * dirent;
+
+ if (buf->count)
+ return -EINVAL;
+ buf->count++;
+ dirent = buf->dirent;
+ put_user(ino, &dirent->d_ino);
+ put_user(offset, &dirent->d_offset);
+ put_user(namlen, &dirent->d_namlen);
+ copy_to_user(dirent->d_name, name, namlen);
+ put_user(0, dirent->d_name + namlen);
+ return 0;
+}
+
+asmlinkage long
+sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count)
+{
+ int error;
+ struct file * file;
+ struct readdir32_callback buf;
+
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ buf.count = 0;
+ buf.dirent = dirent;
+
+ error = vfs_readdir(file, fillonedir32, &buf);
+ if (error >= 0)
+ error = buf.count;
+ fput(file);
+out:
+ return error;
+}
+
+/*** copied from mips64 ***/
+/*
+ * Ooo, nasty. We need here to frob 32-bit unsigned longs to
+ * 64-bit unsigned longs.
+ */
+
+static inline int
+get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+{
+ n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
+ if (ufdset) {
+ unsigned long odd;
+
+ if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32)))
+ return -EFAULT;
+
+ odd = n & 1UL;
+ n &= ~1UL;
+ while (n) {
+ unsigned long h, l;
+ __get_user(l, ufdset);
+ __get_user(h, ufdset+1);
+ ufdset += 2;
+ *fdset++ = h << 32 | l;
+ n -= 2;
+ }
+ if (odd)
+ __get_user(*fdset, ufdset);
+ } else {
+ /* Tricky, must clear full unsigned long in the
+ * kernel fdset at the end, this makes sure that
+ * actually happens.
+ */
+ memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
+ }
+ return 0;
+}
+
+static inline void
+set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+{
+ unsigned long odd;
+ n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
+
+ if (!ufdset)
+ return;
+
+ odd = n & 1UL;
+ n &= ~1UL;
+ while (n) {
+ unsigned long h, l;
+ l = *fdset++;
+ h = l >> 32;
+ __put_user(l, ufdset);
+ __put_user(h, ufdset+1);
+ ufdset += 2;
+ n -= 2;
+ }
+ if (odd)
+ __put_user(*fdset, ufdset);
+}
+
+struct msgbuf32 {
+ int mtype;
+ char mtext[1];
+};
+
+asmlinkage long sys32_msgsnd(int msqid,
+ struct msgbuf32 __user *umsgp32,
+ size_t msgsz, int msgflg)
+{
+ struct msgbuf *mb;
+ struct msgbuf32 mb32;
+ int err;
+
+ if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ err = get_user(mb32.mtype, &umsgp32->mtype);
+ mb->mtype = mb32.mtype;
+ err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz);
+
+ if (err)
+ err = -EFAULT;
+ else
+ KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg);
+
+ kfree(mb);
+ return err;
+}
+
+asmlinkage long sys32_msgrcv(int msqid,
+ struct msgbuf32 __user *umsgp32,
+ size_t msgsz, long msgtyp, int msgflg)
+{
+ struct msgbuf *mb;
+ struct msgbuf32 mb32;
+ int err, len;
+
+ if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg);
+
+ if (err >= 0) {
+ len = err;
+ mb32.mtype = mb->mtype;
+ err = put_user(mb32.mtype, &umsgp32->mtype);
+ err |= copy_to_user(&umsgp32->mtext, mb->mtext, len);
+ if (err)
+ err = -EFAULT;
+ else
+ err = len;
+ }
+
+ kfree(mb);
+ return err;
+}
+
+asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
+{
+ mm_segment_t old_fs = get_fs();
+ int ret;
+ off_t of;
+
+ if (offset && get_user(of, offset))
+ return -EFAULT;
+
+ set_fs(KERNEL_DS);
+ ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
+ set_fs(old_fs);
+
+ if (offset && put_user(of, offset))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
+{
+ mm_segment_t old_fs = get_fs();
+ int ret;
+ loff_t lof;
+
+ if (offset && get_user(lof, offset))
+ return -EFAULT;
+
+ set_fs(KERNEL_DS);
+ ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count);
+ set_fs(old_fs);
+
+ if (offset && put_user(lof, offset))
+ return -EFAULT;
+
+ return ret;
+}
+
+
+struct timex32 {
+ unsigned int modes; /* mode selector */
+ int offset; /* time offset (usec) */
+ int freq; /* frequency offset (scaled ppm) */
+ int maxerror; /* maximum error (usec) */
+ int esterror; /* estimated error (usec) */
+ int status; /* clock command/status */
+ int constant; /* pll time constant */
+ int precision; /* clock precision (usec) (read only) */
+ int tolerance; /* clock frequency tolerance (ppm)
+ * (read only)
+ */
+ struct compat_timeval time; /* (read only) */
+ int tick; /* (modified) usecs between clock ticks */
+
+ int ppsfreq; /* pps frequency (scaled ppm) (ro) */
+ int jitter; /* pps jitter (us) (ro) */
+ int shift; /* interval duration (s) (shift) (ro) */
+ int stabil; /* pps stability (scaled ppm) (ro) */
+ int jitcnt; /* jitter limit exceeded (ro) */
+ int calcnt; /* calibration intervals (ro) */
+ int errcnt; /* calibration errors (ro) */
+ int stbcnt; /* stability limit exceeded (ro) */
+
+ int :32; int :32; int :32; int :32;
+ int :32; int :32; int :32; int :32;
+ int :32; int :32; int :32; int :32;
+};
+
+asmlinkage long sys32_adjtimex(struct timex32 __user *txc_p32)
+{
+ struct timex txc;
+ struct timex32 t32;
+ int ret;
+ extern int do_adjtimex(struct timex *txc);
+
+ if(copy_from_user(&t32, txc_p32, sizeof(struct timex32)))
+ return -EFAULT;
+#undef CP
+#define CP(x) txc.x = t32.x
+ CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
+ CP(status); CP(constant); CP(precision); CP(tolerance);
+ CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
+ CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
+ CP(stbcnt);
+ ret = do_adjtimex(&txc);
+#undef CP
+#define CP(x) t32.x = txc.x
+ CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
+ CP(status); CP(constant); CP(precision); CP(tolerance);
+ CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
+ CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
+ CP(stbcnt);
+ return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret;
+}
+
+
+struct sysinfo32 {
+ s32 uptime;
+ u32 loads[3];
+ u32 totalram;
+ u32 freeram;
+ u32 sharedram;
+ u32 bufferram;
+ u32 totalswap;
+ u32 freeswap;
+ unsigned short procs;
+ u32 totalhigh;
+ u32 freehigh;
+ u32 mem_unit;
+ char _f[12];
+};
+
+/* We used to call sys_sysinfo and translate the result. But sys_sysinfo
+ * undoes the good work done elsewhere, and rather than undoing the
+ * damage, I decided to just duplicate the code from sys_sysinfo here.
+ */
+
+asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
+{
+ struct sysinfo val;
+ int err;
+ unsigned long seq;
+
+ /* We don't need a memset here because we copy the
+ * struct to userspace once element at a time.
+ */
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ val.uptime = jiffies / HZ;
+
+ val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
+ val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
+ val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
+
+ val.procs = nr_threads;
+ } while (read_seqretry(&xtime_lock, seq));
+
+
+ si_meminfo(&val);
+ si_swapinfo(&val);
+
+ err = put_user (val.uptime, &info->uptime);
+ err |= __put_user (val.loads[0], &info->loads[0]);
+ err |= __put_user (val.loads[1], &info->loads[1]);
+ err |= __put_user (val.loads[2], &info->loads[2]);
+ err |= __put_user (val.totalram, &info->totalram);
+ err |= __put_user (val.freeram, &info->freeram);
+ err |= __put_user (val.sharedram, &info->sharedram);
+ err |= __put_user (val.bufferram, &info->bufferram);
+ err |= __put_user (val.totalswap, &info->totalswap);
+ err |= __put_user (val.freeswap, &info->freeswap);
+ err |= __put_user (val.procs, &info->procs);
+ err |= __put_user (val.totalhigh, &info->totalhigh);
+ err |= __put_user (val.freehigh, &info->freehigh);
+ err |= __put_user (val.mem_unit, &info->mem_unit);
+ return err ? -EFAULT : 0;
+}
+
+
+/* lseek() needs a wrapper because 'offset' can be negative, but the top
+ * half of the argument has been zeroed by syscall.S.
+ */
+
+asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin)
+{
+ return sys_lseek(fd, offset, origin);
+}
+
+asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg)
+{
+ union semun u;
+
+ if (cmd == SETVAL) {
+ /* Ugh. arg is a union of int,ptr,ptr,ptr, so is 8 bytes.
+ * The int should be in the first 4, but our argument
+ * frobbing has left it in the last 4.
+ */
+ u.val = *((int *)&arg + 1);
+ return sys_semctl (semid, semnum, cmd, u);
+ }
+ return sys_semctl (semid, semnum, cmd, arg);
+}
+
+long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
+ size_t len)
+{
+ return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
+ buf, len);
+}
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
new file mode 100644
index 000000000000..32ea701f4d20
--- /dev/null
+++ b/arch/parisc/kernel/syscall.S
@@ -0,0 +1,703 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
+ * Licensed under the GNU GPL.
+ * thanks to Philipp Rumpf, Mike Shaver and various others
+ * sorry about the wall, puffin..
+ */
+
+#include <asm/offsets.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/psw.h>
+#include <asm/thread_info.h>
+
+#include <asm/assembly.h>
+#include <asm/processor.h>
+
+ /* We fill the empty parts of the gateway page with
+ * something that will kill the kernel or a
+ * userspace application.
+ */
+#define KILL_INSN break 0,0
+
+#include <linux/config.h> /* for CONFIG_SMP */
+
+#ifdef __LP64__
+ .level 2.0w
+#else
+ .level 1.1
+#endif
+
+#ifndef __LP64__
+ .macro fixup_branch,lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch,lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
+ .text
+
+ .import syscall_exit,code
+ .import syscall_exit_rfi,code
+ .export linux_gateway_page
+
+ /* Linux gateway page is aliased to virtual page 0 in the kernel
+ * address space. Since it is a gateway page it cannot be
+ * dereferenced, so null pointers will still fault. We start
+ * the actual entry point at 0x100. We put break instructions
+ * at the beginning of the page to trap null indirect function
+ * pointers.
+ */
+
+ .align 4096
+linux_gateway_page:
+
+ /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
+ .rept 44
+ KILL_INSN
+ .endr
+
+ /* ADDRESS 0xb0 to 0xb4, lws uses 1 insns for entry */
+ /* Light-weight-syscall entry must always be located at 0xb0 */
+ /* WARNING: Keep this number updated with table size changes */
+#define __NR_lws_entries (2)
+
+lws_entry:
+ /* Unconditional branch to lws_start, located on the
+ same gateway page */
+ b,n lws_start
+
+ /* Fill from 0xb4 to 0xe0 */
+ .rept 11
+ KILL_INSN
+ .endr
+
+ /* This function MUST be located at 0xe0 for glibc's threading
+ mechanism to work. DO NOT MOVE THIS CODE EVER! */
+set_thread_pointer:
+ gate .+8, %r0 /* increase privilege */
+ depi 3, 31, 2, %r31 /* Ensure we return into user mode. */
+ be 0(%sr7,%r31) /* return to user space */
+ mtctl %r26, %cr27 /* move arg0 to the control register */
+
+ /* Increase the chance of trapping if random jumps occur to this
+ address, fill from 0xf0 to 0x100 */
+ .rept 4
+ KILL_INSN
+ .endr
+
+/* This address must remain fixed at 0x100 for glibc's syscalls to work */
+ .align 256
+linux_gateway_entry:
+ gate .+8, %r0 /* become privileged */
+ mtsp %r0,%sr4 /* get kernel space into sr4 */
+ mtsp %r0,%sr5 /* get kernel space into sr5 */
+ mtsp %r0,%sr6 /* get kernel space into sr6 */
+ mfsp %sr7,%r1 /* save user sr7 */
+ mtsp %r1,%sr3 /* and store it in sr3 */
+
+#ifdef __LP64__
+ /* for now we can *always* set the W bit on entry to the syscall
+ * since we don't support wide userland processes. We could
+ * also save the current SM other than in r0 and restore it on
+ * exit from the syscall, and also use that value to know
+ * whether to do narrow or wide syscalls. -PB
+ */
+ ssm PSW_SM_W, %r1
+ extrd,u %r1,PSW_W_BIT,1,%r1
+ /* sp must be aligned on 4, so deposit the W bit setting into
+ * the bottom of sp temporarily */
+ or,ev %r1,%r30,%r30
+ b,n 1f
+ /* The top halves of argument registers must be cleared on syscall
+ * entry from narrow executable.
+ */
+ depdi 0, 31, 32, %r26
+ depdi 0, 31, 32, %r25
+ depdi 0, 31, 32, %r24
+ depdi 0, 31, 32, %r23
+ depdi 0, 31, 32, %r22
+ depdi 0, 31, 32, %r21
+1:
+#endif
+ mfctl %cr30,%r1
+ xor %r1,%r30,%r30 /* ye olde xor trick */
+ xor %r1,%r30,%r1
+ xor %r1,%r30,%r30
+
+ ldo THREAD_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */
+
+ /* N.B.: It is critical that we don't set sr7 to 0 until r30
+ * contains a valid kernel stack pointer. It is also
+ * critical that we don't start using the kernel stack
+ * until after sr7 has been set to 0.
+ */
+
+ mtsp %r0,%sr7 /* get kernel space into sr7 */
+ STREGM %r1,FRAME_SIZE(%r30) /* save r1 (usp) here for now */
+ mfctl %cr30,%r1 /* get task ptr in %r1 */
+ LDREG TI_TASK(%r1),%r1
+
+ /* Save some registers for sigcontext and potential task
+ switch (see entry.S for the details of which ones are
+ saved/restored). TASK_PT_PSW is zeroed so we can see whether
+ a process is on a syscall or not. For an interrupt the real
+ PSW value is stored. This is needed for gdb and sys_ptrace. */
+ STREG %r0, TASK_PT_PSW(%r1)
+ STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
+ STREG %r19, TASK_PT_GR19(%r1)
+
+ LDREGM -FRAME_SIZE(%r30), %r2 /* get users sp back */
+#ifdef __LP64__
+ extrd,u %r2,63,1,%r19 /* W hidden in bottom bit */
+#if 0
+ xor %r19,%r2,%r2 /* clear bottom bit */
+ depd,z %r19,1,1,%r19
+ std %r19,TASK_PT_PSW(%r1)
+#endif
+#endif
+ STREG %r2, TASK_PT_GR30(%r1) /* ... and save it */
+
+ STREG %r20, TASK_PT_GR20(%r1)
+ STREG %r21, TASK_PT_GR21(%r1)
+ STREG %r22, TASK_PT_GR22(%r1)
+ STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */
+ STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */
+ STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */
+ STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
+ STREG %r27, TASK_PT_GR27(%r1) /* user dp */
+ STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
+ STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */
+ STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */
+ STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
+
+ ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */
+ save_fp %r27 /* or potential task switch */
+
+ mfctl %cr11, %r27 /* i.e. SAR */
+ STREG %r27, TASK_PT_SAR(%r1)
+
+ loadgp
+
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+ copy %r19,%r2 /* W bit back to r2 */
+#else
+ /* no need to save these on stack in wide mode because the first 8
+ * args are passed in registers */
+ stw %r22, -52(%r30) /* 5th argument */
+ stw %r21, -56(%r30) /* 6th argument */
+#endif
+
+ /* Are we being ptraced? */
+ mfctl %cr30, %r1
+ LDREG TI_TASK(%r1),%r1
+ LDREG TASK_PTRACE(%r1), %r1
+ bb,<,n %r1,31,.Ltracesys
+
+ /* Note! We cannot use the syscall table that is mapped
+ nearby since the gateway page is mapped execute-only. */
+
+#ifdef __LP64__
+ ldil L%sys_call_table, %r1
+ or,= %r2,%r2,%r2
+ addil L%(sys_call_table64-sys_call_table), %r1
+ ldo R%sys_call_table(%r1), %r19
+ or,= %r2,%r2,%r2
+ ldo R%sys_call_table64(%r1), %r19
+#else
+ ldil L%sys_call_table, %r1
+ ldo R%sys_call_table(%r1), %r19
+#endif
+ comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+ b,n .Lsyscall_nosys
+
+ LDREGX %r20(%r19), %r19
+
+ /* If this is a sys_rt_sigreturn call, and the signal was received
+ * when not in_syscall, then we want to return via syscall_exit_rfi,
+ * not syscall_exit. Signal no. in r20, in_syscall in r25 (see
+ * trampoline code in signal.c).
+ */
+ ldi __NR_rt_sigreturn,%r2
+ comb,= %r2,%r20,.Lrt_sigreturn
+.Lin_syscall:
+ ldil L%syscall_exit,%r2
+ be 0(%sr7,%r19)
+ ldo R%syscall_exit(%r2),%r2
+.Lrt_sigreturn:
+ comib,<> 0,%r25,.Lin_syscall
+ ldil L%syscall_exit_rfi,%r2
+ be 0(%sr7,%r19)
+ ldo R%syscall_exit_rfi(%r2),%r2
+
+ /* Note! Because we are not running where we were linked, any
+ calls to functions external to this file must be indirect. To
+ be safe, we apply the opposite rule to functions within this
+ file, with local labels given to them to ensure correctness. */
+
+.Lsyscall_nosys:
+syscall_nosys:
+ ldil L%syscall_exit,%r1
+ be R%syscall_exit(%sr7,%r1)
+ ldo -ENOSYS(%r0),%r28 /* set errno */
+
+
+/* Warning! This trace code is a virtual duplicate of the code above so be
+ * sure to maintain both! */
+.Ltracesys:
+tracesys:
+ /* Need to save more registers so the debugger can see where we
+ * are. This saves only the lower 8 bits of PSW, so that the C
+ * bit is still clear on syscalls, and the D bit is set if this
+ * full register save path has been executed. We check the D
+ * bit on syscall_return_rfi to determine which registers to
+ * restore. An interrupt results in a full PSW saved with the
+ * C bit set, a non-straced syscall entry results in C and D clear
+ * in the saved PSW.
+ */
+ ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
+ LDREG TI_TASK(%r1), %r1
+ ssm 0,%r2
+ STREG %r2,TASK_PT_PSW(%r1) /* Lower 8 bits only!! */
+ mfsp %sr0,%r2
+ STREG %r2,TASK_PT_SR0(%r1)
+ mfsp %sr1,%r2
+ STREG %r2,TASK_PT_SR1(%r1)
+ mfsp %sr2,%r2
+ STREG %r2,TASK_PT_SR2(%r1)
+ mfsp %sr3,%r2
+ STREG %r2,TASK_PT_SR3(%r1)
+ STREG %r2,TASK_PT_SR4(%r1)
+ STREG %r2,TASK_PT_SR5(%r1)
+ STREG %r2,TASK_PT_SR6(%r1)
+ STREG %r2,TASK_PT_SR7(%r1)
+ STREG %r2,TASK_PT_IASQ0(%r1)
+ STREG %r2,TASK_PT_IASQ1(%r1)
+ LDREG TASK_PT_GR31(%r1),%r2
+ STREG %r2,TASK_PT_IAOQ0(%r1)
+ ldo 4(%r2),%r2
+ STREG %r2,TASK_PT_IAOQ1(%r1)
+ ldo TASK_REGS(%r1),%r2
+ /* reg_save %r2 */
+ STREG %r3,PT_GR3(%r2)
+ STREG %r4,PT_GR4(%r2)
+ STREG %r5,PT_GR5(%r2)
+ STREG %r6,PT_GR6(%r2)
+ STREG %r7,PT_GR7(%r2)
+ STREG %r8,PT_GR8(%r2)
+ STREG %r9,PT_GR9(%r2)
+ STREG %r10,PT_GR10(%r2)
+ STREG %r11,PT_GR11(%r2)
+ STREG %r12,PT_GR12(%r2)
+ STREG %r13,PT_GR13(%r2)
+ STREG %r14,PT_GR14(%r2)
+ STREG %r15,PT_GR15(%r2)
+ STREG %r16,PT_GR16(%r2)
+ STREG %r17,PT_GR17(%r2)
+ STREG %r18,PT_GR18(%r2)
+ /* Finished saving things for the debugger */
+
+ ldil L%syscall_trace,%r1
+ ldil L%tracesys_next,%r2
+ be R%syscall_trace(%sr7,%r1)
+ ldo R%tracesys_next(%r2),%r2
+
+tracesys_next:
+ ldil L%sys_call_table,%r1
+ ldo R%sys_call_table(%r1), %r19
+
+ ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
+ LDREG TI_TASK(%r1), %r1
+ LDREG TASK_PT_GR20(%r1), %r20
+ LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */
+ LDREG TASK_PT_GR25(%r1), %r25
+ LDREG TASK_PT_GR24(%r1), %r24
+ LDREG TASK_PT_GR23(%r1), %r23
+#ifdef __LP64__
+ LDREG TASK_PT_GR22(%r1), %r22
+ LDREG TASK_PT_GR21(%r1), %r21
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+
+ comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+ b,n .Lsyscall_nosys
+
+ LDREGX %r20(%r19), %r19
+
+ /* If this is a sys_rt_sigreturn call, and the signal was received
+ * when not in_syscall, then we want to return via syscall_exit_rfi,
+ * not syscall_exit. Signal no. in r20, in_syscall in r25 (see
+ * trampoline code in signal.c).
+ */
+ ldi __NR_rt_sigreturn,%r2
+ comb,= %r2,%r20,.Ltrace_rt_sigreturn
+.Ltrace_in_syscall:
+ ldil L%tracesys_exit,%r2
+ be 0(%sr7,%r19)
+ ldo R%tracesys_exit(%r2),%r2
+
+ /* Do *not* call this function on the gateway page, because it
+ makes a direct call to syscall_trace. */
+
+tracesys_exit:
+ ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
+ LDREG TI_TASK(%r1), %r1
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+ bl syscall_trace, %r2
+ STREG %r28,TASK_PT_GR28(%r1) /* save return value now */
+ ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
+ LDREG TI_TASK(%r1), %r1
+ LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */
+
+ ldil L%syscall_exit,%r1
+ be,n R%syscall_exit(%sr7,%r1)
+
+.Ltrace_rt_sigreturn:
+ comib,<> 0,%r25,.Ltrace_in_syscall
+ ldil L%tracesys_sigexit,%r2
+ be 0(%sr7,%r19)
+ ldo R%tracesys_sigexit(%r2),%r2
+
+tracesys_sigexit:
+ ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
+ LDREG 0(%r1), %r1
+#ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
+#endif
+ bl syscall_trace, %r2
+ nop
+
+ ldil L%syscall_exit_rfi,%r1
+ be,n R%syscall_exit_rfi(%sr7,%r1)
+
+
+ /*********************************************************
+ Light-weight-syscall code
+
+ r20 - lws number
+ r26,r25,r24,r23,r22 - Input registers
+ r28 - Function return register
+ r21 - Error code.
+
+ Scracth: Any of the above that aren't being
+ currently used, including r1.
+
+ Return pointer: r31 (Not usable)
+
+ Error codes returned by entry path:
+
+ ENOSYS - r20 was an invalid LWS number.
+
+ *********************************************************/
+lws_start:
+ /* Gate and ensure we return to userspace */
+ gate .+8, %r0
+ depi 3, 31, 2, %r31 /* Ensure we return to userspace */
+
+#ifdef __LP64__
+ /* FIXME: If we are a 64-bit kernel just
+ * turn this on unconditionally.
+ */
+ ssm PSW_SM_W, %r1
+ extrd,u %r1,PSW_W_BIT,1,%r1
+ /* sp must be aligned on 4, so deposit the W bit setting into
+ * the bottom of sp temporarily */
+ or,ev %r1,%r30,%r30
+
+ /* Clip LWS number to a 32-bit value always */
+ depdi 0, 31, 32, %r20
+#endif
+
+ /* Is the lws entry number valid? */
+ comiclr,>>= __NR_lws_entries, %r20, %r0
+ b,n lws_exit_nosys
+
+ /* WARNING: Trashing sr2 and sr3 */
+ mfsp %sr7,%r1 /* get userspace into sr3 */
+ mtsp %r1,%sr3
+ mtsp %r0,%sr2 /* get kernel space into sr2 */
+
+ /* Load table start */
+ ldil L%lws_table, %r1
+ ldo R%lws_table(%r1), %r28 /* Scratch use of r28 */
+ LDREGX %r20(%sr2,r28), %r21 /* Scratch use of r21 */
+
+ /* Jump to lws, lws table pointers already relocated */
+ be,n 0(%sr2,%r21)
+
+lws_exit_nosys:
+ ldo -ENOSYS(%r0),%r21 /* set errno */
+ /* Fall through: Return to userspace */
+
+lws_exit:
+#ifdef __LP64__
+ /* decide whether to reset the wide mode bit
+ *
+ * For a syscall, the W bit is stored in the lowest bit
+ * of sp. Extract it and reset W if it is zero */
+ extrd,u,*<> %r30,63,1,%r1
+ rsm PSW_SM_W, %r0
+ /* now reset the lowest bit of sp if it was set */
+ xor %r30,%r1,%r30
+#endif
+ be,n 0(%sr3, %r31)
+
+
+
+ /***************************************************
+ Implementing CAS as an atomic operation:
+
+ %r26 - Address to examine
+ %r25 - Old value to check (old)
+ %r24 - New value to set (new)
+ %r28 - Return prev through this register.
+ %r21 - Kernel error code
+
+ If debugging is DISabled:
+
+ %r21 has the following meanings:
+
+ EAGAIN - CAS is busy, ldcw failed, try again.
+ EFAULT - Read or write failed.
+
+ If debugging is enabled:
+
+ EDEADLOCK - CAS called recursively.
+ EAGAIN && r28 == 1 - CAS is busy. Lock contended.
+ EAGAIN && r28 == 2 - CAS is busy. ldcw failed.
+ EFAULT - Read or write failed.
+
+ Scratch: r20, r28, r1
+
+ ****************************************************/
+
+ /* Do not enable LWS debugging */
+#define ENABLE_LWS_DEBUG 0
+
+ /* ELF64 Process entry path */
+lws_compare_and_swap64:
+#ifdef __LP64__
+ b,n lws_compare_and_swap
+#else
+ /* If we are not a 64-bit kernel, then we don't
+ * implement having 64-bit input registers
+ */
+ b,n lws_exit_nosys
+#endif
+
+ /* ELF32 Process entry path */
+lws_compare_and_swap32:
+#ifdef __LP64__
+ /* Clip all the input registers */
+ depdi 0, 31, 32, %r26
+ depdi 0, 31, 32, %r25
+ depdi 0, 31, 32, %r24
+#endif
+
+lws_compare_and_swap:
+#ifdef CONFIG_SMP
+ /* Load start of lock table */
+ ldil L%lws_lock_start, %r20
+ ldo R%lws_lock_start(%r20), %r28
+
+ /* Extract four bits from r26 and hash lock (Bits 4-7) */
+ extru %r26, 27, 4, %r20
+
+ /* Find lock to use, the hash is either one of 0 to
+ 15, multiplied by 16 (keep it 16-byte aligned)
+ and add to the lock table offset. */
+ shlw %r20, 4, %r20
+ add %r20, %r28, %r20
+
+# ifdef ENABLE_LWS_DEBUG
+ /*
+ DEBUG, check for deadlock!
+ If the thread register values are the same
+ then we were the one that locked it last and
+ this is a recurisve call that will deadlock.
+ We *must* giveup this call and fail.
+ */
+ ldw 4(%sr2,%r20), %r28 /* Load thread register */
+ mfctl %cr27, %r21 /* Get current thread register */
+ cmpb,<>,n %r21, %r28, cas_lock /* Called recursive? */
+ b lws_exit /* Return error! */
+ ldo -EDEADLOCK(%r0), %r21
+cas_lock:
+ cmpb,=,n %r0, %r28, cas_nocontend /* Is nobody using it? */
+ ldo 1(%r0), %r28 /* 1st case */
+ b lws_exit /* Contended... */
+ ldo -EAGAIN(%r0), %r21 /* Spin in userspace */
+cas_nocontend:
+# endif
+/* ENABLE_LWS_DEBUG */
+
+ ldcw 0(%sr2,%r20), %r28 /* Try to acquire the lock */
+ cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */
+cas_wouldblock:
+ ldo 2(%r0), %r28 /* 2nd case */
+ b lws_exit /* Contended... */
+ ldo -EAGAIN(%r0), %r21 /* Spin in userspace */
+#endif
+/* CONFIG_SMP */
+
+ /*
+ prev = *addr;
+ if ( prev == old )
+ *addr = new;
+ return prev;
+ */
+
+ /* NOTES:
+ This all works becuse intr_do_signal
+ and schedule both check the return iasq
+ and see that we are on the kernel page
+ so this process is never scheduled off
+ or is ever sent any signal of any sort,
+ thus it is wholly atomic from usrspaces
+ perspective
+ */
+cas_action:
+#if defined CONFIG_SMP && defined ENABLE_LWS_DEBUG
+ /* DEBUG */
+ mfctl %cr27, %r1
+ stw %r1, 4(%sr2,%r20)
+#endif
+ /* The load and store could fail */
+1: ldw 0(%sr3,%r26), %r28
+ sub,<> %r28, %r25, %r0
+2: stw %r24, 0(%sr3,%r26)
+#ifdef CONFIG_SMP
+ /* Free lock */
+ stw %r20, 0(%sr2,%r20)
+# ifdef ENABLE_LWS_DEBUG
+ /* Clear thread register indicator */
+ stw %r0, 4(%sr2,%r20)
+# endif
+#endif
+ /* Return to userspace, set no error */
+ b lws_exit
+ copy %r0, %r21
+
+3:
+ /* Error occured on load or store */
+#ifdef CONFIG_SMP
+ /* Free lock */
+ stw %r20, 0(%sr2,%r20)
+# ifdef ENABLE_LWS_DEBUG
+ stw %r0, 4(%sr2,%r20)
+# endif
+#endif
+ b lws_exit
+ ldo -EFAULT(%r0),%r21 /* set errno */
+ nop
+ nop
+ nop
+ nop
+
+ /* Two exception table entries, one for the load,
+ the other for the store. Either return -EFAULT.
+ Each of the entries must be relocated. */
+ .section __ex_table,"aw"
+#ifdef __LP64__
+ /* Pad the address calculation */
+ .word 0,(2b - linux_gateway_page)
+ .word 0,(3b - linux_gateway_page)
+#else
+ .word (2b - linux_gateway_page)
+ .word (3b - linux_gateway_page)
+#endif
+ .previous
+
+ .section __ex_table,"aw"
+#ifdef __LP64__
+ /* Pad the address calculation */
+ .word 0,(1b - linux_gateway_page)
+ .word 0,(3b - linux_gateway_page)
+#else
+ .word (1b - linux_gateway_page)
+ .word (3b - linux_gateway_page)
+#endif
+ .previous
+
+end_compare_and_swap:
+
+ /* Make sure nothing else is placed on this page */
+ .align 4096
+ .export end_linux_gateway_page
+end_linux_gateway_page:
+
+ /* Relocate symbols assuming linux_gateway_page is mapped
+ to virtual address 0x0 */
+#ifdef __LP64__
+ /* FIXME: The code will always be on the gateay page
+ and thus it will be on the first 4k, the
+ assembler seems to think that the final
+ subtraction result is only a word in
+ length, so we pad the value.
+ */
+#define LWS_ENTRY(_name_) .word 0,(lws_##_name_ - linux_gateway_page)
+#else
+#define LWS_ENTRY(_name_) .word (lws_##_name_ - linux_gateway_page)
+#endif
+
+ .align 4096
+ /* Light-weight-syscall table */
+ /* Start of lws table. */
+ .export lws_table
+.Llws_table:
+lws_table:
+ LWS_ENTRY(compare_and_swap32) /* 0 - ELF32 Atomic compare and swap */
+ LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic compare and swap */
+ /* End of lws table */
+
+ .align 4096
+ .export sys_call_table
+.Lsys_call_table:
+sys_call_table:
+#include "syscall_table.S"
+
+#ifdef __LP64__
+ .align 4096
+ .export sys_call_table64
+.Lsys_call_table64:
+sys_call_table64:
+#define SYSCALL_TABLE_64BIT
+#include "syscall_table.S"
+#endif
+
+#ifdef CONFIG_SMP
+ /*
+ All light-weight-syscall atomic operations
+ will use this set of locks
+ */
+ .section .data
+ .align 4096
+ .export lws_lock_start
+.Llws_lock_start:
+lws_lock_start:
+ /* lws locks */
+ .align 16
+ .rept 16
+ /* Keep locks aligned at 16-bytes */
+ .word 1
+ .word 0
+ .word 0
+ .word 0
+ .endr
+ .previous
+#endif
+/* CONFIG_SMP for lws_lock_start */
+
+.end
+
+
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
new file mode 100644
index 000000000000..779b537100ec
--- /dev/null
+++ b/arch/parisc/kernel/syscall_table.S
@@ -0,0 +1,372 @@
+/* System Call Table
+ *
+ * Copyright (C) 1999-2004 Matthew Wilcox <willy at parisc-linux.org>
+ * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org>
+ * Copyright (C) 2000 Alan Modra <amodra at parisc-linux.org>
+ * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
+ * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
+ * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
+ * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org>
+ * Copyright (C) 2000 Grant Grundler <grundler at parisc-linux.org>
+ * Copyright (C) 2001 Richard Hirst <rhirst with parisc-linux.org>
+ * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
+ * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
+ * Copyright (C) 2000-2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
+ * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#undef ENTRY_SAME
+#undef ENTRY_DIFF
+#undef ENTRY_UHOH
+#undef ENTRY_COMP
+#undef ENTRY_OURS
+#if defined(__LP64__) && !defined(SYSCALL_TABLE_64BIT)
+/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
+ * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
+ * implementation is required on wide palinux. Use ENTRY_COMP where
+ * the compatability layer has a useful 32-bit implementation.
+ */
+#define ENTRY_SAME(_name_) .dword sys_##_name_
+#define ENTRY_DIFF(_name_) .dword sys32_##_name_
+#define ENTRY_UHOH(_name_) .dword sys32_##unimplemented
+#define ENTRY_OURS(_name_) .dword parisc_##_name_
+#define ENTRY_COMP(_name_) .dword compat_sys_##_name_
+#elif defined(__LP64__) && defined(SYSCALL_TABLE_64BIT)
+#define ENTRY_SAME(_name_) .dword sys_##_name_
+#define ENTRY_DIFF(_name_) .dword sys_##_name_
+#define ENTRY_UHOH(_name_) .dword sys_##_name_
+#define ENTRY_OURS(_name_) .dword sys_##_name_
+#define ENTRY_COMP(_name_) .dword sys_##_name_
+#else
+#define ENTRY_SAME(_name_) .word sys_##_name_
+#define ENTRY_DIFF(_name_) .word sys_##_name_
+#define ENTRY_UHOH(_name_) .word sys_##_name_
+#define ENTRY_OURS(_name_) .word parisc_##_name_
+#define ENTRY_COMP(_name_) .word sys_##_name_
+#endif
+
+ ENTRY_SAME(restart_syscall) /* 0 */
+ ENTRY_SAME(exit)
+ ENTRY_SAME(fork_wrapper)
+ ENTRY_SAME(read)
+ ENTRY_SAME(write)
+ ENTRY_SAME(open) /* 5 */
+ ENTRY_SAME(close)
+ ENTRY_SAME(waitpid)
+ ENTRY_SAME(creat)
+ ENTRY_SAME(link)
+ ENTRY_SAME(unlink) /* 10 */
+ ENTRY_DIFF(execve_wrapper)
+ ENTRY_SAME(chdir)
+ /* See comments in kernel/time.c!!! Maybe we don't need this? */
+ ENTRY_COMP(time)
+ ENTRY_SAME(mknod)
+ ENTRY_SAME(chmod) /* 15 */
+ ENTRY_SAME(lchown)
+ ENTRY_SAME(socket)
+ /* struct stat is MAYBE identical wide and narrow ?? */
+ ENTRY_COMP(newstat)
+ ENTRY_DIFF(lseek)
+ ENTRY_SAME(getpid) /* 20 */
+ /* the 'void * data' parameter may need re-packing in wide */
+ ENTRY_COMP(mount)
+ /* concerned about struct sockaddr in wide/narrow */
+ /* ---> I think sockaddr is OK unless the compiler packs the struct */
+ /* differently to align the char array */
+ ENTRY_SAME(bind)
+ ENTRY_SAME(setuid)
+ ENTRY_SAME(getuid)
+ ENTRY_COMP(stime) /* 25 */
+ ENTRY_SAME(ptrace)
+ ENTRY_SAME(alarm)
+ /* see stat comment */
+ ENTRY_COMP(newfstat)
+ ENTRY_SAME(pause)
+ /* struct utimbuf uses time_t which might vary */
+ ENTRY_COMP(utime) /* 30 */
+ /* struct sockaddr... */
+ ENTRY_SAME(connect)
+ ENTRY_SAME(listen)
+ ENTRY_SAME(access)
+ ENTRY_SAME(nice)
+ /* struct sockaddr... */
+ ENTRY_SAME(accept) /* 35 */
+ ENTRY_SAME(sync)
+ ENTRY_SAME(kill)
+ ENTRY_SAME(rename)
+ ENTRY_SAME(mkdir)
+ ENTRY_SAME(rmdir) /* 40 */
+ ENTRY_SAME(dup)
+ ENTRY_SAME(pipe)
+ ENTRY_COMP(times)
+ /* struct sockaddr... */
+ ENTRY_SAME(getsockname)
+ /* it seems possible brk() could return a >4G pointer... */
+ ENTRY_SAME(brk) /* 45 */
+ ENTRY_SAME(setgid)
+ ENTRY_SAME(getgid)
+ ENTRY_SAME(signal)
+ ENTRY_SAME(geteuid)
+ ENTRY_SAME(getegid) /* 50 */
+ ENTRY_SAME(acct)
+ ENTRY_SAME(umount)
+ /* struct sockaddr... */
+ ENTRY_SAME(getpeername)
+ ENTRY_COMP(ioctl)
+ ENTRY_COMP(fcntl) /* 55 */
+ ENTRY_SAME(socketpair)
+ ENTRY_SAME(setpgid)
+ ENTRY_SAME(send)
+ ENTRY_SAME(newuname)
+ ENTRY_SAME(umask) /* 60 */
+ ENTRY_SAME(chroot)
+ ENTRY_SAME(ustat)
+ ENTRY_SAME(dup2)
+ ENTRY_SAME(getppid)
+ ENTRY_SAME(getpgrp) /* 65 */
+ ENTRY_SAME(setsid)
+ ENTRY_SAME(pivot_root)
+ /* I don't like this */
+ ENTRY_UHOH(sgetmask)
+ ENTRY_UHOH(ssetmask)
+ ENTRY_SAME(setreuid) /* 70 */
+ ENTRY_SAME(setregid)
+ ENTRY_SAME(mincore)
+ ENTRY_COMP(sigpending)
+ ENTRY_SAME(sethostname)
+ /* Following 3 have linux-common-code structs containing longs -( */
+ ENTRY_COMP(setrlimit) /* 75 */
+ ENTRY_COMP(getrlimit)
+ ENTRY_COMP(getrusage)
+ /* struct timeval and timezone are maybe?? consistent wide and narrow */
+ ENTRY_DIFF(gettimeofday)
+ ENTRY_DIFF(settimeofday)
+ ENTRY_SAME(getgroups) /* 80 */
+ ENTRY_SAME(setgroups)
+ /* struct socketaddr... */
+ ENTRY_SAME(sendto)
+ ENTRY_SAME(symlink)
+ /* see stat comment */
+ ENTRY_COMP(newlstat)
+ ENTRY_SAME(readlink) /* 85 */
+ ENTRY_SAME(ni_syscall) /* was uselib */
+ ENTRY_SAME(swapon)
+ ENTRY_SAME(reboot)
+ ENTRY_SAME(mmap2)
+ ENTRY_SAME(mmap) /* 90 */
+ ENTRY_SAME(munmap)
+ ENTRY_SAME(truncate)
+ ENTRY_SAME(ftruncate)
+ ENTRY_SAME(fchmod)
+ ENTRY_SAME(fchown) /* 95 */
+ ENTRY_SAME(getpriority)
+ ENTRY_SAME(setpriority)
+ ENTRY_SAME(recv)
+ ENTRY_COMP(statfs)
+ ENTRY_COMP(fstatfs) /* 100 */
+ ENTRY_SAME(stat64)
+ ENTRY_SAME(ni_syscall) /* was socketcall */
+ ENTRY_SAME(syslog)
+ /* even though manpage says struct timeval contains longs, ours has
+ * time_t and suseconds_t -- both of which are safe wide/narrow */
+ ENTRY_COMP(setitimer)
+ ENTRY_COMP(getitimer) /* 105 */
+ ENTRY_SAME(capget)
+ ENTRY_SAME(capset)
+ ENTRY_OURS(pread64)
+ ENTRY_OURS(pwrite64)
+ ENTRY_SAME(getcwd) /* 110 */
+ ENTRY_SAME(vhangup)
+ ENTRY_SAME(fstat64)
+ ENTRY_SAME(vfork_wrapper)
+ /* struct rusage contains longs... */
+ ENTRY_COMP(wait4)
+ ENTRY_SAME(swapoff) /* 115 */
+ ENTRY_DIFF(sysinfo)
+ ENTRY_SAME(shutdown)
+ ENTRY_SAME(fsync)
+ ENTRY_SAME(madvise)
+ ENTRY_SAME(clone_wrapper) /* 120 */
+ ENTRY_SAME(setdomainname)
+ ENTRY_DIFF(sendfile)
+ /* struct sockaddr... */
+ ENTRY_SAME(recvfrom)
+ /* struct timex contains longs */
+ ENTRY_DIFF(adjtimex)
+ ENTRY_SAME(mprotect) /* 125 */
+ /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
+ ENTRY_COMP(sigprocmask)
+ ENTRY_SAME(ni_syscall) /* create_module */
+ ENTRY_SAME(init_module)
+ ENTRY_SAME(delete_module)
+ ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */
+ /* time_t inside struct dqblk */
+ ENTRY_SAME(quotactl)
+ ENTRY_SAME(getpgid)
+ ENTRY_SAME(fchdir)
+ ENTRY_SAME(bdflush)
+ ENTRY_SAME(sysfs) /* 135 */
+ ENTRY_SAME(personality)
+ ENTRY_SAME(ni_syscall) /* for afs_syscall */
+ ENTRY_SAME(setfsuid)
+ ENTRY_SAME(setfsgid)
+ /* I think this might work */
+ ENTRY_SAME(llseek) /* 140 */
+ /* struct linux_dirent has longs, like 'unsigned long d_ino' which
+ * almost definitely should be 'ino_t d_ino' but it's too late now */
+ ENTRY_DIFF(getdents)
+ /* it is POSSIBLE that select will be OK because even though fd_set
+ * contains longs, the macros and sizes are clever. */
+ ENTRY_COMP(select)
+ ENTRY_SAME(flock)
+ ENTRY_SAME(msync)
+ /* struct iovec contains pointers */
+ ENTRY_COMP(readv) /* 145 */
+ ENTRY_COMP(writev)
+ ENTRY_SAME(getsid)
+ ENTRY_SAME(fdatasync)
+ /* struct __sysctl_args is a mess */
+ ENTRY_DIFF(sysctl)
+ ENTRY_SAME(mlock) /* 150 */
+ ENTRY_SAME(munlock)
+ ENTRY_SAME(mlockall)
+ ENTRY_SAME(munlockall)
+ /* struct sched_param is ok for now */
+ ENTRY_SAME(sched_setparam)
+ ENTRY_SAME(sched_getparam) /* 155 */
+ ENTRY_SAME(sched_setscheduler)
+ ENTRY_SAME(sched_getscheduler)
+ ENTRY_SAME(sched_yield)
+ ENTRY_SAME(sched_get_priority_max)
+ ENTRY_SAME(sched_get_priority_min) /* 160 */
+ /* These 2 would've worked if someone had defined struct timespec
+ * carefully, like timeval for example (which is about the same).
+ * Unfortunately it contains a long :-( */
+ ENTRY_DIFF(sched_rr_get_interval)
+ ENTRY_COMP(nanosleep)
+ ENTRY_SAME(mremap)
+ ENTRY_SAME(setresuid)
+ ENTRY_SAME(getresuid) /* 165 */
+ ENTRY_DIFF(sigaltstack_wrapper)
+ ENTRY_SAME(ni_syscall) /* query_module */
+ ENTRY_SAME(poll)
+ /* structs contain pointers and an in_addr... */
+ ENTRY_COMP(nfsservctl)
+ ENTRY_SAME(setresgid) /* 170 */
+ ENTRY_SAME(getresgid)
+ ENTRY_SAME(prctl)
+ /* signals need a careful review */
+ ENTRY_SAME(rt_sigreturn_wrapper)
+ ENTRY_DIFF(rt_sigaction)
+ ENTRY_DIFF(rt_sigprocmask) /* 175 */
+ ENTRY_DIFF(rt_sigpending)
+ ENTRY_COMP(rt_sigtimedwait)
+ /* even though the struct siginfo_t is different, it appears like
+ * all the paths use values which should be same wide and narrow.
+ * Also the struct is padded to 128 bytes which means we don't have
+ * to worry about faulting trying to copy in a larger 64-bit
+ * struct from a 32-bit user-space app.
+ */
+ ENTRY_SAME(rt_sigqueueinfo)
+ ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
+ ENTRY_SAME(chown) /* 180 */
+ /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
+ ENTRY_COMP(setsockopt)
+ ENTRY_SAME(getsockopt)
+ ENTRY_COMP(sendmsg)
+ ENTRY_COMP(recvmsg)
+ ENTRY_SAME(semop) /* 185 */
+ ENTRY_SAME(semget)
+ ENTRY_DIFF(semctl)
+ ENTRY_DIFF(msgsnd)
+ ENTRY_DIFF(msgrcv)
+ ENTRY_SAME(msgget) /* 190 */
+ ENTRY_SAME(msgctl)
+ ENTRY_SAME(shmat_wrapper)
+ ENTRY_SAME(shmdt)
+ ENTRY_SAME(shmget)
+ ENTRY_SAME(shmctl) /* 195 */
+ ENTRY_SAME(ni_syscall) /* streams1 */
+ ENTRY_SAME(ni_syscall) /* streams2 */
+ ENTRY_SAME(lstat64)
+ ENTRY_OURS(truncate64)
+ ENTRY_OURS(ftruncate64) /* 200 */
+ ENTRY_SAME(getdents64)
+ ENTRY_COMP(fcntl64)
+ ENTRY_SAME(ni_syscall) /* attrctl -- dead */
+ ENTRY_SAME(ni_syscall) /* acl_get -- dead */
+ ENTRY_SAME(ni_syscall) /* 205 (acl_set -- dead) */
+ ENTRY_SAME(gettid)
+ ENTRY_OURS(readahead)
+ ENTRY_SAME(tkill)
+ ENTRY_SAME(sendfile64)
+ ENTRY_COMP(futex) /* 210 */
+ ENTRY_COMP(sched_setaffinity)
+ ENTRY_COMP(sched_getaffinity)
+ ENTRY_SAME(ni_syscall) /* set_thread_area */
+ ENTRY_SAME(ni_syscall) /* get_thread_area */
+ ENTRY_SAME(io_setup) /* 215 */
+ ENTRY_SAME(io_destroy)
+ ENTRY_SAME(io_getevents)
+ ENTRY_SAME(io_submit)
+ ENTRY_SAME(io_cancel)
+ ENTRY_SAME(alloc_hugepages) /* 220 */
+ ENTRY_SAME(free_hugepages)
+ ENTRY_SAME(exit_group)
+ ENTRY_DIFF(lookup_dcookie)
+ ENTRY_SAME(epoll_create)
+ ENTRY_SAME(epoll_ctl) /* 225 */
+ ENTRY_SAME(epoll_wait)
+ ENTRY_SAME(remap_file_pages)
+ ENTRY_SAME(semtimedop)
+ ENTRY_SAME(mq_open)
+ ENTRY_SAME(mq_unlink) /* 230 */
+ ENTRY_SAME(mq_timedsend)
+ ENTRY_SAME(mq_timedreceive)
+ ENTRY_SAME(mq_notify)
+ ENTRY_SAME(mq_getsetattr)
+ ENTRY_COMP(waitid) /* 235 */
+ ENTRY_OURS(fadvise64_64)
+ ENTRY_SAME(set_tid_address)
+ ENTRY_SAME(setxattr)
+ ENTRY_SAME(lsetxattr)
+ ENTRY_SAME(fsetxattr) /* 240 */
+ ENTRY_SAME(getxattr)
+ ENTRY_SAME(lgetxattr)
+ ENTRY_SAME(fgetxattr)
+ ENTRY_SAME(listxattr)
+ ENTRY_SAME(llistxattr) /* 245 */
+ ENTRY_SAME(flistxattr)
+ ENTRY_SAME(removexattr)
+ ENTRY_SAME(lremovexattr)
+ ENTRY_SAME(fremovexattr)
+ ENTRY_COMP(timer_create) /* 250 */
+ ENTRY_COMP(timer_settime)
+ ENTRY_COMP(timer_gettime)
+ ENTRY_SAME(timer_getoverrun)
+ ENTRY_SAME(timer_delete)
+ ENTRY_COMP(clock_settime) /* 255 */
+ ENTRY_COMP(clock_gettime)
+ ENTRY_COMP(clock_getres)
+ ENTRY_COMP(clock_nanosleep)
+ ENTRY_SAME(tgkill)
+ ENTRY_COMP(mbind) /* 260 */
+ ENTRY_COMP(get_mempolicy)
+ ENTRY_COMP(set_mempolicy)
+ /* Nothing yet */
+
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
new file mode 100644
index 000000000000..6cf7407344ba
--- /dev/null
+++ b/arch/parisc/kernel/time.c
@@ -0,0 +1,243 @@
+/*
+ * linux/arch/parisc/kernel/time.c
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King
+ * Copyright (C) 1999 SuSE GmbH, (Philipp Rumpf, prumpf@tux.org)
+ *
+ * 1994-07-02 Alan Modra
+ * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
+ * 1998-12-20 Updated NTP code according to technical memorandum Jan '96
+ * "A Kernel Model for Precision Timekeeping" by Dave Mills
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/profile.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/param.h>
+#include <asm/pdc.h>
+#include <asm/led.h>
+
+#include <linux/timex.h>
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+EXPORT_SYMBOL(jiffies_64);
+
+/* xtime and wall_jiffies keep wall-clock time */
+extern unsigned long wall_jiffies;
+
+static long clocktick; /* timer cycles per tick */
+static long halftick;
+
+#ifdef CONFIG_SMP
+extern void smp_do_timer(struct pt_regs *regs);
+#endif
+
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ long now;
+ long next_tick;
+ int nticks;
+ int cpu = smp_processor_id();
+
+ profile_tick(CPU_PROFILING, regs);
+
+ now = mfctl(16);
+ /* initialize next_tick to time at last clocktick */
+ next_tick = cpu_data[cpu].it_value;
+
+ /* since time passes between the interrupt and the mfctl()
+ * above, it is never true that last_tick + clocktick == now. If we
+ * never miss a clocktick, we could set next_tick = last_tick + clocktick
+ * but maybe we'll miss ticks, hence the loop.
+ *
+ * Variables are *signed*.
+ */
+
+ nticks = 0;
+ while((next_tick - now) < halftick) {
+ next_tick += clocktick;
+ nticks++;
+ }
+ mtctl(next_tick, 16);
+ cpu_data[cpu].it_value = next_tick;
+
+ while (nticks--) {
+#ifdef CONFIG_SMP
+ smp_do_timer(regs);
+#else
+ update_process_times(user_mode(regs));
+#endif
+ if (cpu == 0) {
+ write_seqlock(&xtime_lock);
+ do_timer(regs);
+ write_sequnlock(&xtime_lock);
+ }
+ }
+
+#ifdef CONFIG_CHASSIS_LCD_LED
+ /* Only schedule the led tasklet on cpu 0, and only if it
+ * is enabled.
+ */
+ if (cpu == 0 && !atomic_read(&led_tasklet.count))
+ tasklet_schedule(&led_tasklet);
+#endif
+
+ /* check soft power switch status */
+ if (cpu == 0 && !atomic_read(&power_tasklet.count))
+ tasklet_schedule(&power_tasklet);
+
+ return IRQ_HANDLED;
+}
+
+/*** converted from ia64 ***/
+/*
+ * Return the number of micro-seconds that elapsed since the last
+ * update to wall time (aka xtime aka wall_jiffies). The xtime_lock
+ * must be at least read-locked when calling this routine.
+ */
+static inline unsigned long
+gettimeoffset (void)
+{
+#ifndef CONFIG_SMP
+ /*
+ * FIXME: This won't work on smp because jiffies are updated by cpu 0.
+ * Once parisc-linux learns the cr16 difference between processors,
+ * this could be made to work.
+ */
+ long last_tick;
+ long elapsed_cycles;
+
+ /* it_value is the intended time of the next tick */
+ last_tick = cpu_data[smp_processor_id()].it_value;
+
+ /* Subtract one tick and account for possible difference between
+ * when we expected the tick and when it actually arrived.
+ * (aka wall vs real)
+ */
+ last_tick -= clocktick * (jiffies - wall_jiffies + 1);
+ elapsed_cycles = mfctl(16) - last_tick;
+
+ /* the precision of this math could be improved */
+ return elapsed_cycles / (PAGE0->mem_10msec / 10000);
+#else
+ return 0;
+#endif
+}
+
+void
+do_gettimeofday (struct timeval *tv)
+{
+ unsigned long flags, seq, usec, sec;
+
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ usec = gettimeoffset();
+ sec = xtime.tv_sec;
+ usec += (xtime.tv_nsec / 1000);
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+
+ while (usec >= 1000000) {
+ usec -= 1000000;
+ ++sec;
+ }
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+int
+do_settimeofday (struct timespec *tv)
+{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
+ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ return -EINVAL;
+
+ write_seqlock_irq(&xtime_lock);
+ {
+ /*
+ * This is revolting. We need to set "xtime"
+ * correctly. However, the value in this location is
+ * the value at the most recent update of wall time.
+ * Discover what correction gettimeofday would have
+ * done, and then undo it!
+ */
+ nsec -= gettimeoffset() * 1000;
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+ }
+ write_sequnlock_irq(&xtime_lock);
+ clock_was_set();
+ return 0;
+}
+EXPORT_SYMBOL(do_settimeofday);
+
+/*
+ * XXX: We can do better than this.
+ * Returns nanoseconds
+ */
+
+unsigned long long sched_clock(void)
+{
+ return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+
+void __init time_init(void)
+{
+ unsigned long next_tick;
+ static struct pdc_tod tod_data;
+
+ clocktick = (100 * PAGE0->mem_10msec) / HZ;
+ halftick = clocktick / 2;
+
+ /* Setup clock interrupt timing */
+
+ next_tick = mfctl(16);
+ next_tick += clocktick;
+ cpu_data[smp_processor_id()].it_value = next_tick;
+
+ /* kick off Itimer (CR16) */
+ mtctl(next_tick, 16);
+
+ if(pdc_tod_read(&tod_data) == 0) {
+ write_seqlock_irq(&xtime_lock);
+ xtime.tv_sec = tod_data.tod_sec;
+ xtime.tv_nsec = tod_data.tod_usec * 1000;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+ write_sequnlock_irq(&xtime_lock);
+ } else {
+ printk(KERN_ERR "Error reading tod clock\n");
+ xtime.tv_sec = 0;
+ xtime.tv_nsec = 0;
+ }
+}
+
diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c
new file mode 100644
index 000000000000..ac2a40681414
--- /dev/null
+++ b/arch/parisc/kernel/topology.c
@@ -0,0 +1,37 @@
+/*
+ * arch/parisc/kernel/topology.c - Populate driverfs with topology information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+
+static struct cpu cpu_devices[NR_CPUS];
+
+static int __init topology_init(void)
+{
+ struct node *parent = NULL;
+ int num;
+
+ for_each_present_cpu(num) {
+ register_cpu(&cpu_devices[num], num, parent);
+ }
+ return 0;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
new file mode 100644
index 000000000000..d2e5b229a2f4
--- /dev/null
+++ b/arch/parisc/kernel/traps.c
@@ -0,0 +1,834 @@
+/*
+ * linux/arch/parisc/traps.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org>
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+#include <linux/kallsyms.h>
+
+#include <asm/assembly.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/unaligned.h>
+#include <asm/atomic.h>
+#include <asm/smp.h>
+#include <asm/pdc.h>
+#include <asm/pdc_chassis.h>
+#include <asm/unwind.h>
+
+#include "../math-emu/math-emu.h" /* for handle_fpe() */
+
+#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
+ /* dumped to the console via printk) */
+
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+DEFINE_SPINLOCK(pa_dbit_lock);
+#endif
+
+int printbinary(char *buf, unsigned long x, int nbits)
+{
+ unsigned long mask = 1UL << (nbits - 1);
+ while (mask != 0) {
+ *buf++ = (mask & x ? '1' : '0');
+ mask >>= 1;
+ }
+ *buf = '\0';
+
+ return nbits;
+}
+
+#ifdef __LP64__
+#define RFMT "%016lx"
+#else
+#define RFMT "%08lx"
+#endif
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+ char buf[128], *p;
+ char *level;
+ unsigned long cr30;
+ unsigned long cr31;
+
+ level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
+
+ printk("%s\n", level); /* don't want to have that pretty register dump messed up */
+
+ printk("%s YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);
+ printbinary(buf, regs->gr[0], 32);
+ printk("%sPSW: %s %s\n", level, buf, print_tainted());
+
+ for (i = 0; i < 32; i += 4) {
+ int j;
+ p = buf;
+ p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3);
+ for (j = 0; j < 4; j++) {
+ p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]);
+ }
+ printk("%s\n", buf);
+ }
+
+ for (i = 0; i < 8; i += 4) {
+ int j;
+ p = buf;
+ p += sprintf(p, "%ssr%d-%d ", level, i, i + 3);
+ for (j = 0; j < 4; j++) {
+ p += sprintf(p, " " RFMT, regs->sr[i + j]);
+ }
+ printk("%s\n", buf);
+ }
+
+#if RIDICULOUSLY_VERBOSE
+ for (i = 0; i < 32; i += 2)
+ printk("%sFR%02d : %016lx FR%2d : %016lx", level, i,
+ regs->fr[i], i+1, regs->fr[i+1]);
+#endif
+
+ cr30 = mfctl(30);
+ cr31 = mfctl(31);
+ printk("%s\n", level);
+ printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n",
+ level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
+ printk("%s IIR: %08lx ISR: " RFMT " IOR: " RFMT "\n",
+ level, regs->iir, regs->isr, regs->ior);
+ printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n",
+ level, current_thread_info()->cpu, cr30, cr31);
+ printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);
+ printk(level);
+ print_symbol(" IAOQ[0]: %s\n", regs->iaoq[0]);
+ printk(level);
+ print_symbol(" IAOQ[1]: %s\n", regs->iaoq[1]);
+ printk(level);
+ print_symbol(" RP(r2): %s\n", regs->gr[2]);
+}
+
+
+void dump_stack(void)
+{
+ show_stack(NULL, NULL);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+static void do_show_stack(struct unwind_frame_info *info)
+{
+ int i = 1;
+
+ printk("Backtrace:\n");
+ while (i <= 16) {
+ if (unwind_once(info) < 0 || info->ip == 0)
+ break;
+
+ if (__kernel_text_address(info->ip)) {
+ printk(" [<" RFMT ">] ", info->ip);
+#ifdef CONFIG_KALLSYMS
+ print_symbol("%s\n", info->ip);
+#else
+ if ((i & 0x03) == 0)
+ printk("\n");
+#endif
+ i++;
+ }
+ }
+ printk("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *s)
+{
+ struct unwind_frame_info info;
+
+ if (!task) {
+ unsigned long sp;
+ struct pt_regs *r;
+
+HERE:
+ asm volatile ("copy %%r30, %0" : "=r"(sp));
+ r = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+ if (!r)
+ return;
+ memset(r, 0, sizeof(struct pt_regs));
+ r->iaoq[0] = (unsigned long)&&HERE;
+ r->gr[2] = (unsigned long)__builtin_return_address(0);
+ r->gr[30] = sp;
+ unwind_frame_init(&info, current, r);
+ kfree(r);
+ } else {
+ unwind_frame_init_from_blocked_task(&info, task);
+ }
+
+ do_show_stack(&info);
+}
+
+void die_if_kernel(char *str, struct pt_regs *regs, long err)
+{
+ if (user_mode(regs)) {
+ if (err == 0)
+ return; /* STFU */
+
+ printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
+ current->comm, current->pid, str, err, regs->iaoq[0]);
+#ifdef PRINT_USER_FAULTS
+ /* XXX for debugging only */
+ show_regs(regs);
+#endif
+ return;
+ }
+
+ oops_in_progress = 1;
+
+ /* Amuse the user in a SPARC fashion */
+ printk(
+" _______________________________ \n"
+" < Your System ate a SPARC! Gah! >\n"
+" ------------------------------- \n"
+" \\ ^__^\n"
+" \\ (xx)\\_______\n"
+" (__)\\ )\\/\\\n"
+" U ||----w |\n"
+" || ||\n");
+
+ /* unlock the pdc lock if necessary */
+ pdc_emergency_unlock();
+
+ /* maybe the kernel hasn't booted very far yet and hasn't been able
+ * to initialize the serial or STI console. In that case we should
+ * re-enable the pdc console, so that the user will be able to
+ * identify the problem. */
+ if (!console_drivers)
+ pdc_console_restart();
+
+ printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
+ current->comm, current->pid, str, err);
+ show_regs(regs);
+
+ /* Wot's wrong wif bein' racy? */
+ if (current->thread.flags & PARISC_KERNEL_DEATH) {
+ printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
+ local_irq_enable();
+ while (1);
+ }
+
+ current->thread.flags |= PARISC_KERNEL_DEATH;
+ do_exit(SIGSEGV);
+}
+
+int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
+{
+ return syscall(regs);
+}
+
+/* gdb uses break 4,8 */
+#define GDB_BREAK_INSN 0x10004
+void handle_gdb_break(struct pt_regs *regs, int wot)
+{
+ struct siginfo si;
+
+ si.si_code = wot;
+ si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ si.si_errno = 0;
+ force_sig_info(SIGTRAP, &si, current);
+}
+
+void handle_break(unsigned iir, struct pt_regs *regs)
+{
+ struct siginfo si;
+
+ switch(iir) {
+ case 0x00:
+#ifdef PRINT_USER_FAULTS
+ printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n",
+ current->pid, current->comm);
+#endif
+ die_if_kernel("Breakpoint", regs, 0);
+#ifdef PRINT_USER_FAULTS
+ show_regs(regs);
+#endif
+ si.si_code = TRAP_BRKPT;
+ si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ force_sig_info(SIGTRAP, &si, current);
+ break;
+
+ case GDB_BREAK_INSN:
+ die_if_kernel("Breakpoint", regs, 0);
+ handle_gdb_break(regs, TRAP_BRKPT);
+ break;
+
+ default:
+#ifdef PRINT_USER_FAULTS
+ printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n",
+ iir, current->pid, current->comm);
+ show_regs(regs);
+#endif
+ si.si_signo = SIGTRAP;
+ si.si_code = TRAP_BRKPT;
+ si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
+ force_sig_info(SIGTRAP, &si, current);
+ return;
+ }
+}
+
+
+int handle_toc(void)
+{
+ printk(KERN_CRIT "TOC call.\n");
+ return 0;
+}
+
+static void default_trap(int code, struct pt_regs *regs)
+{
+ printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id());
+ show_regs(regs);
+}
+
+void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
+
+
+void transfer_pim_to_trap_frame(struct pt_regs *regs)
+{
+ register int i;
+ extern unsigned int hpmc_pim_data[];
+ struct pdc_hpmc_pim_11 *pim_narrow;
+ struct pdc_hpmc_pim_20 *pim_wide;
+
+ if (boot_cpu_data.cpu_type >= pcxu) {
+
+ pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
+
+ /*
+ * Note: The following code will probably generate a
+ * bunch of truncation error warnings from the compiler.
+ * Could be handled with an ifdef, but perhaps there
+ * is a better way.
+ */
+
+ regs->gr[0] = pim_wide->cr[22];
+
+ for (i = 1; i < 32; i++)
+ regs->gr[i] = pim_wide->gr[i];
+
+ for (i = 0; i < 32; i++)
+ regs->fr[i] = pim_wide->fr[i];
+
+ for (i = 0; i < 8; i++)
+ regs->sr[i] = pim_wide->sr[i];
+
+ regs->iasq[0] = pim_wide->cr[17];
+ regs->iasq[1] = pim_wide->iasq_back;
+ regs->iaoq[0] = pim_wide->cr[18];
+ regs->iaoq[1] = pim_wide->iaoq_back;
+
+ regs->sar = pim_wide->cr[11];
+ regs->iir = pim_wide->cr[19];
+ regs->isr = pim_wide->cr[20];
+ regs->ior = pim_wide->cr[21];
+ }
+ else {
+ pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
+
+ regs->gr[0] = pim_narrow->cr[22];
+
+ for (i = 1; i < 32; i++)
+ regs->gr[i] = pim_narrow->gr[i];
+
+ for (i = 0; i < 32; i++)
+ regs->fr[i] = pim_narrow->fr[i];
+
+ for (i = 0; i < 8; i++)
+ regs->sr[i] = pim_narrow->sr[i];
+
+ regs->iasq[0] = pim_narrow->cr[17];
+ regs->iasq[1] = pim_narrow->iasq_back;
+ regs->iaoq[0] = pim_narrow->cr[18];
+ regs->iaoq[1] = pim_narrow->iaoq_back;
+
+ regs->sar = pim_narrow->cr[11];
+ regs->iir = pim_narrow->cr[19];
+ regs->isr = pim_narrow->cr[20];
+ regs->ior = pim_narrow->cr[21];
+ }
+
+ /*
+ * The following fields only have meaning if we came through
+ * another path. So just zero them here.
+ */
+
+ regs->ksp = 0;
+ regs->kpc = 0;
+ regs->orig_r28 = 0;
+}
+
+
+/*
+ * This routine is called as a last resort when everything else
+ * has gone clearly wrong. We get called for faults in kernel space,
+ * and HPMC's.
+ */
+void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
+{
+ static DEFINE_SPINLOCK(terminate_lock);
+
+ oops_in_progress = 1;
+
+ set_eiem(0);
+ local_irq_disable();
+ spin_lock(&terminate_lock);
+
+ /* unlock the pdc lock if necessary */
+ pdc_emergency_unlock();
+
+ /* restart pdc console if necessary */
+ if (!console_drivers)
+ pdc_console_restart();
+
+ /* Not all paths will gutter the processor... */
+ switch(code){
+
+ case 1:
+ transfer_pim_to_trap_frame(regs);
+ break;
+
+ default:
+ /* Fall through */
+ break;
+
+ }
+
+ {
+ /* show_stack(NULL, (unsigned long *)regs->gr[30]); */
+ struct unwind_frame_info info;
+ unwind_frame_init(&info, current, regs);
+ do_show_stack(&info);
+ }
+
+ printk("\n");
+ printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
+ msg, code, regs, offset);
+ show_regs(regs);
+
+ spin_unlock(&terminate_lock);
+
+ /* put soft power button back under hardware control;
+ * if the user had pressed it once at any time, the
+ * system will shut down immediately right here. */
+ pdc_soft_power_button(0);
+
+ /* Call kernel panic() so reboot timeouts work properly
+ * FIXME: This function should be on the list of
+ * panic notifiers, and we should call panic
+ * directly from the location that we wish.
+ * e.g. We should not call panic from
+ * parisc_terminate, but rather the oter way around.
+ * This hack works, prints the panic message twice,
+ * and it enables reboot timers!
+ */
+ panic(msg);
+}
+
+void handle_interruption(int code, struct pt_regs *regs)
+{
+ unsigned long fault_address = 0;
+ unsigned long fault_space = 0;
+ struct siginfo si;
+
+ if (code == 1)
+ pdc_console_restart(); /* switch back to pdc if HPMC */
+ else
+ local_irq_enable();
+
+ /* Security check:
+ * If the priority level is still user, and the
+ * faulting space is not equal to the active space
+ * then the user is attempting something in a space
+ * that does not belong to them. Kill the process.
+ *
+ * This is normally the situation when the user
+ * attempts to jump into the kernel space at the
+ * wrong offset, be it at the gateway page or a
+ * random location.
+ *
+ * We cannot normally signal the process because it
+ * could *be* on the gateway page, and processes
+ * executing on the gateway page can't have signals
+ * delivered.
+ *
+ * We merely readjust the address into the users
+ * space, at a destination address of zero, and
+ * allow processing to continue.
+ */
+ if (((unsigned long)regs->iaoq[0] & 3) &&
+ ((unsigned long)regs->iasq[0] != (unsigned long)regs->sr[7])) {
+ /* Kill the user process later */
+ regs->iaoq[0] = 0 | 3;
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ regs->iasq[0] = regs->iasq[0] = regs->sr[7];
+ regs->gr[0] &= ~PSW_B;
+ return;
+ }
+
+#if 0
+ printk(KERN_CRIT "Interruption # %d\n", code);
+#endif
+
+ switch(code) {
+
+ case 1:
+ /* High-priority machine check (HPMC) */
+
+ /* set up a new led state on systems shipped with a LED State panel */
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_HPMC);
+
+ parisc_terminate("High Priority Machine Check (HPMC)",
+ regs, code, 0);
+ /* NOT REACHED */
+
+ case 2:
+ /* Power failure interrupt */
+ printk(KERN_CRIT "Power failure interrupt !\n");
+ return;
+
+ case 3:
+ /* Recovery counter trap */
+ regs->gr[0] &= ~PSW_R;
+ if (user_space(regs))
+ handle_gdb_break(regs, TRAP_TRACE);
+ /* else this must be the start of a syscall - just let it run */
+ return;
+
+ case 5:
+ /* Low-priority machine check */
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC);
+
+ flush_all_caches();
+ cpu_lpmc(5, regs);
+ return;
+
+ case 6:
+ /* Instruction TLB miss fault/Instruction page fault */
+ fault_address = regs->iaoq[0];
+ fault_space = regs->iasq[0];
+ break;
+
+ case 8:
+ /* Illegal instruction trap */
+ die_if_kernel("Illegal instruction", regs, code);
+ si.si_code = ILL_ILLOPC;
+ goto give_sigill;
+
+ case 9:
+ /* Break instruction trap */
+ handle_break(regs->iir,regs);
+ return;
+
+ case 10:
+ /* Privileged operation trap */
+ die_if_kernel("Privileged operation", regs, code);
+ si.si_code = ILL_PRVOPC;
+ goto give_sigill;
+
+ case 11:
+ /* Privileged register trap */
+ if ((regs->iir & 0xffdfffe0) == 0x034008a0) {
+
+ /* This is a MFCTL cr26/cr27 to gr instruction.
+ * PCXS traps on this, so we need to emulate it.
+ */
+
+ if (regs->iir & 0x00200000)
+ regs->gr[regs->iir & 0x1f] = mfctl(27);
+ else
+ regs->gr[regs->iir & 0x1f] = mfctl(26);
+
+ regs->iaoq[0] = regs->iaoq[1];
+ regs->iaoq[1] += 4;
+ regs->iasq[0] = regs->iasq[1];
+ return;
+ }
+
+ die_if_kernel("Privileged register usage", regs, code);
+ si.si_code = ILL_PRVREG;
+ give_sigill:
+ si.si_signo = SIGILL;
+ si.si_errno = 0;
+ si.si_addr = (void __user *) regs->iaoq[0];
+ force_sig_info(SIGILL, &si, current);
+ return;
+
+ case 12:
+ /* Overflow Trap, let the userland signal handler do the cleanup */
+ si.si_signo = SIGFPE;
+ si.si_code = FPE_INTOVF;
+ si.si_addr = (void __user *) regs->iaoq[0];
+ force_sig_info(SIGFPE, &si, current);
+ return;
+
+ case 13:
+ /* Conditional Trap
+ The condition succees in an instruction which traps
+ on condition */
+ if(user_mode(regs)){
+ si.si_signo = SIGFPE;
+ /* Set to zero, and let the userspace app figure it out from
+ the insn pointed to by si_addr */
+ si.si_code = 0;
+ si.si_addr = (void __user *) regs->iaoq[0];
+ force_sig_info(SIGFPE, &si, current);
+ return;
+ }
+ /* The kernel doesn't want to handle condition codes */
+ break;
+
+ case 14:
+ /* Assist Exception Trap, i.e. floating point exception. */
+ die_if_kernel("Floating point exception", regs, 0); /* quiet */
+ handle_fpe(regs);
+ return;
+
+ case 15:
+ /* Data TLB miss fault/Data page fault */
+ /* Fall through */
+ case 16:
+ /* Non-access instruction TLB miss fault */
+ /* The instruction TLB entry needed for the target address of the FIC
+ is absent, and hardware can't find it, so we get to cleanup */
+ /* Fall through */
+ case 17:
+ /* Non-access data TLB miss fault/Non-access data page fault */
+ /* FIXME:
+ Still need to add slow path emulation code here!
+ If the insn used a non-shadow register, then the tlb
+ handlers could not have their side-effect (e.g. probe
+ writing to a target register) emulated since rfir would
+ erase the changes to said register. Instead we have to
+ setup everything, call this function we are in, and emulate
+ by hand. Technically we need to emulate:
+ fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw
+ */
+ fault_address = regs->ior;
+ fault_space = regs->isr;
+ break;
+
+ case 18:
+ /* PCXS only -- later cpu's split this into types 26,27 & 28 */
+ /* Check for unaligned access */
+ if (check_unaligned(regs)) {
+ handle_unaligned(regs);
+ return;
+ }
+ /* Fall Through */
+ case 26:
+ /* PCXL: Data memory access rights trap */
+ fault_address = regs->ior;
+ fault_space = regs->isr;
+ break;
+
+ case 19:
+ /* Data memory break trap */
+ regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
+ /* fall thru */
+ case 21:
+ /* Page reference trap */
+ handle_gdb_break(regs, TRAP_HWBKPT);
+ return;
+
+ case 25:
+ /* Taken branch trap */
+ regs->gr[0] &= ~PSW_T;
+ if (user_space(regs))
+ handle_gdb_break(regs, TRAP_BRANCH);
+ /* else this must be the start of a syscall - just let it
+ * run.
+ */
+ return;
+
+ case 7:
+ /* Instruction access rights */
+ /* PCXL: Instruction memory protection trap */
+
+ /*
+ * This could be caused by either: 1) a process attempting
+ * to execute within a vma that does not have execute
+ * permission, or 2) an access rights violation caused by a
+ * flush only translation set up by ptep_get_and_clear().
+ * So we check the vma permissions to differentiate the two.
+ * If the vma indicates we have execute permission, then
+ * the cause is the latter one. In this case, we need to
+ * call do_page_fault() to fix the problem.
+ */
+
+ if (user_mode(regs)) {
+ struct vm_area_struct *vma;
+
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(current->mm,regs->iaoq[0]);
+ if (vma && (regs->iaoq[0] >= vma->vm_start)
+ && (vma->vm_flags & VM_EXEC)) {
+
+ fault_address = regs->iaoq[0];
+ fault_space = regs->iasq[0];
+
+ up_read(&current->mm->mmap_sem);
+ break; /* call do_page_fault() */
+ }
+ up_read(&current->mm->mmap_sem);
+ }
+ /* Fall Through */
+ case 27:
+ /* Data memory protection ID trap */
+ die_if_kernel("Protection id trap", regs, code);
+ si.si_code = SEGV_MAPERR;
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ if (code == 7)
+ si.si_addr = (void __user *) regs->iaoq[0];
+ else
+ si.si_addr = (void __user *) regs->ior;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+
+ case 28:
+ /* Unaligned data reference trap */
+ handle_unaligned(regs);
+ return;
+
+ default:
+ if (user_mode(regs)) {
+#ifdef PRINT_USER_FAULTS
+ printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n",
+ current->pid, current->comm);
+ show_regs(regs);
+#endif
+ /* SIGBUS, for lack of a better one. */
+ si.si_signo = SIGBUS;
+ si.si_code = BUS_OBJERR;
+ si.si_errno = 0;
+ si.si_addr = (void __user *) regs->ior;
+ force_sig_info(SIGBUS, &si, current);
+ return;
+ }
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
+
+ parisc_terminate("Unexpected interruption", regs, code, 0);
+ /* NOT REACHED */
+ }
+
+ if (user_mode(regs)) {
+ if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
+#ifdef PRINT_USER_FAULTS
+ if (fault_space == 0)
+ printk(KERN_DEBUG "User Fault on Kernel Space ");
+ else
+ printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
+ code);
+ printk("pid=%d command='%s'\n", current->pid, current->comm);
+ show_regs(regs);
+#endif
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SEGV_MAPERR;
+ si.si_addr = (void __user *) regs->ior;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+ }
+ }
+ else {
+
+ /*
+ * The kernel should never fault on its own address space.
+ */
+
+ if (fault_space == 0)
+ {
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
+ parisc_terminate("Kernel Fault", regs, code, fault_address);
+
+ }
+ }
+
+ do_page_fault(regs, code, fault_address);
+}
+
+
+int __init check_ivt(void *iva)
+{
+ int i;
+ u32 check = 0;
+ u32 *ivap;
+ u32 *hpmcp;
+ u32 length;
+ extern void os_hpmc(void);
+ extern void os_hpmc_end(void);
+
+ if (strcmp((char *)iva, "cows can fly"))
+ return -1;
+
+ ivap = (u32 *)iva;
+
+ for (i = 0; i < 8; i++)
+ *ivap++ = 0;
+
+ /* Compute Checksum for HPMC handler */
+
+ length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);
+ ivap[7] = length;
+
+ hpmcp = (u32 *)os_hpmc;
+
+ for (i=0; i<length/4; i++)
+ check += *hpmcp++;
+
+ for (i=0; i<8; i++)
+ check += ivap[i];
+
+ ivap[5] = -check;
+
+ return 0;
+}
+
+#ifndef __LP64__
+extern const void fault_vector_11;
+#endif
+extern const void fault_vector_20;
+
+void __init trap_init(void)
+{
+ void *iva;
+
+ if (boot_cpu_data.cpu_type >= pcxu)
+ iva = (void *) &fault_vector_20;
+ else
+#ifdef __LP64__
+ panic("Can't boot 64-bit OS on PA1.1 processor!");
+#else
+ iva = (void *) &fault_vector_11;
+#endif
+
+ if (check_ivt(iva))
+ panic("IVT invalid");
+}
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
new file mode 100644
index 000000000000..62eea35bcd69
--- /dev/null
+++ b/arch/parisc/kernel/unaligned.c
@@ -0,0 +1,816 @@
+/*
+ * Unaligned memory access handler
+ *
+ * Copyright (C) 2001 Randolph Chung <tausq@debian.org>
+ * Significantly tweaked by LaMont Jones <lamont@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+/* #define DEBUG_UNALIGNED 1 */
+
+#ifdef DEBUG_UNALIGNED
+#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+#ifdef __LP64__
+#define RFMT "%016lx"
+#else
+#define RFMT "%08lx"
+#endif
+
+#define FIXUP_BRANCH(lbl) \
+ "\tldil L%%" #lbl ", %%r1\n" \
+ "\tldo R%%" #lbl "(%%r1), %%r1\n" \
+ "\tbv,n %%r0(%%r1)\n"
+
+/* 1111 1100 0000 0000 0001 0011 1100 0000 */
+#define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6)
+#define OPCODE2(a,b) ((a)<<26|(b)<<1)
+#define OPCODE3(a,b) ((a)<<26|(b)<<2)
+#define OPCODE4(a) ((a)<<26)
+#define OPCODE1_MASK OPCODE1(0x3f,1,0xf)
+#define OPCODE2_MASK OPCODE2(0x3f,1)
+#define OPCODE3_MASK OPCODE3(0x3f,1)
+#define OPCODE4_MASK OPCODE4(0x3f)
+
+/* skip LDB - never unaligned (index) */
+#define OPCODE_LDH_I OPCODE1(0x03,0,0x1)
+#define OPCODE_LDW_I OPCODE1(0x03,0,0x2)
+#define OPCODE_LDD_I OPCODE1(0x03,0,0x3)
+#define OPCODE_LDDA_I OPCODE1(0x03,0,0x4)
+#define OPCODE_LDCD_I OPCODE1(0x03,0,0x5)
+#define OPCODE_LDWA_I OPCODE1(0x03,0,0x6)
+#define OPCODE_LDCW_I OPCODE1(0x03,0,0x7)
+/* skip LDB - never unaligned (short) */
+#define OPCODE_LDH_S OPCODE1(0x03,1,0x1)
+#define OPCODE_LDW_S OPCODE1(0x03,1,0x2)
+#define OPCODE_LDD_S OPCODE1(0x03,1,0x3)
+#define OPCODE_LDDA_S OPCODE1(0x03,1,0x4)
+#define OPCODE_LDCD_S OPCODE1(0x03,1,0x5)
+#define OPCODE_LDWA_S OPCODE1(0x03,1,0x6)
+#define OPCODE_LDCW_S OPCODE1(0x03,1,0x7)
+/* skip STB - never unaligned */
+#define OPCODE_STH OPCODE1(0x03,1,0x9)
+#define OPCODE_STW OPCODE1(0x03,1,0xa)
+#define OPCODE_STD OPCODE1(0x03,1,0xb)
+/* skip STBY - never unaligned */
+/* skip STDBY - never unaligned */
+#define OPCODE_STWA OPCODE1(0x03,1,0xe)
+#define OPCODE_STDA OPCODE1(0x03,1,0xf)
+
+#define OPCODE_FLDWX OPCODE1(0x09,0,0x0)
+#define OPCODE_FLDWXR OPCODE1(0x09,0,0x1)
+#define OPCODE_FSTWX OPCODE1(0x09,0,0x8)
+#define OPCODE_FSTWXR OPCODE1(0x09,0,0x9)
+#define OPCODE_FLDWS OPCODE1(0x09,1,0x0)
+#define OPCODE_FLDWSR OPCODE1(0x09,1,0x1)
+#define OPCODE_FSTWS OPCODE1(0x09,1,0x8)
+#define OPCODE_FSTWSR OPCODE1(0x09,1,0x9)
+#define OPCODE_FLDDX OPCODE1(0x0b,0,0x0)
+#define OPCODE_FSTDX OPCODE1(0x0b,0,0x8)
+#define OPCODE_FLDDS OPCODE1(0x0b,1,0x0)
+#define OPCODE_FSTDS OPCODE1(0x0b,1,0x8)
+
+#define OPCODE_LDD_L OPCODE2(0x14,0)
+#define OPCODE_FLDD_L OPCODE2(0x14,1)
+#define OPCODE_STD_L OPCODE2(0x1c,0)
+#define OPCODE_FSTD_L OPCODE2(0x1c,1)
+
+#define OPCODE_LDW_M OPCODE3(0x17,1)
+#define OPCODE_FLDW_L OPCODE3(0x17,0)
+#define OPCODE_FSTW_L OPCODE3(0x1f,0)
+#define OPCODE_STW_M OPCODE3(0x1f,1)
+
+#define OPCODE_LDH_L OPCODE4(0x11)
+#define OPCODE_LDW_L OPCODE4(0x12)
+#define OPCODE_LDWM OPCODE4(0x13)
+#define OPCODE_STH_L OPCODE4(0x19)
+#define OPCODE_STW_L OPCODE4(0x1A)
+#define OPCODE_STWM OPCODE4(0x1B)
+
+#define MAJOR_OP(i) (((i)>>26)&0x3f)
+#define R1(i) (((i)>>21)&0x1f)
+#define R2(i) (((i)>>16)&0x1f)
+#define R3(i) ((i)&0x1f)
+#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
+#define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
+#define IM5_2(i) IM((i)>>16,5)
+#define IM5_3(i) IM((i),5)
+#define IM14(i) IM((i),14)
+
+#define ERR_NOTHANDLED -1
+#define ERR_PAGEFAULT -2
+
+int unaligned_enabled = 1;
+
+void die_if_kernel (char *str, struct pt_regs *regs, long err);
+
+static int emulate_ldh(struct pt_regs *regs, int toreg)
+{
+ unsigned long saddr = regs->ior;
+ unsigned long val = 0;
+ int ret;
+
+ DPRINTF("load " RFMT ":" RFMT " to r%d for 2 bytes\n",
+ regs->isr, regs->ior, toreg);
+
+ __asm__ __volatile__ (
+" mtsp %4, %%sr1\n"
+"1: ldbs 0(%%sr1,%3), %%r20\n"
+"2: ldbs 1(%%sr1,%3), %0\n"
+" depw %%r20, 23, 24, %0\n"
+" copy %%r0, %1\n"
+"3: \n"
+" .section .fixup,\"ax\"\n"
+"4: ldi -2, %1\n"
+ FIXUP_BRANCH(3b)
+" .previous\n"
+" .section __ex_table,\"aw\"\n"
+#ifdef __LP64__
+" .dword 1b,4b\n"
+" .dword 2b,4b\n"
+#else
+" .word 1b,4b\n"
+" .word 2b,4b\n"
+#endif
+" .previous\n"
+ : "=r" (val), "=r" (ret)
+ : "0" (val), "r" (saddr), "r" (regs->isr)
+ : "r20" );
+
+ DPRINTF("val = 0x" RFMT "\n", val);
+
+ if (toreg)
+ regs->gr[toreg] = val;
+
+ return ret;
+}
+
+static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
+{
+ unsigned long saddr = regs->ior;
+ unsigned long val = 0;
+ int ret;
+
+ DPRINTF("load " RFMT ":" RFMT " to r%d for 4 bytes\n",
+ regs->isr, regs->ior, toreg);
+
+ __asm__ __volatile__ (
+" zdep %3,28,2,%%r19\n" /* r19=(ofs&3)*8 */
+" mtsp %4, %%sr1\n"
+" depw %%r0,31,2,%3\n"
+"1: ldw 0(%%sr1,%3),%0\n"
+"2: ldw 4(%%sr1,%3),%%r20\n"
+" subi 32,%%r19,%%r19\n"
+" mtctl %%r19,11\n"
+" vshd %0,%%r20,%0\n"
+" copy %%r0, %1\n"
+"3: \n"
+" .section .fixup,\"ax\"\n"
+"4: ldi -2, %1\n"
+ FIXUP_BRANCH(3b)
+" .previous\n"
+" .section __ex_table,\"aw\"\n"
+#ifdef __LP64__
+" .dword 1b,4b\n"
+" .dword 2b,4b\n"
+#else
+" .word 1b,4b\n"
+" .word 2b,4b\n"
+#endif
+" .previous\n"
+ : "=r" (val), "=r" (ret)
+ : "0" (val), "r" (saddr), "r" (regs->isr)
+ : "r19", "r20" );
+
+ DPRINTF("val = 0x" RFMT "\n", val);
+
+ if (flop)
+ ((__u32*)(regs->fr))[toreg] = val;
+ else if (toreg)
+ regs->gr[toreg] = val;
+
+ return ret;
+}
+static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
+{
+ unsigned long saddr = regs->ior;
+ __u64 val = 0;
+ int ret;
+
+ DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n",
+ regs->isr, regs->ior, toreg);
+#ifdef CONFIG_PA20
+
+#ifndef __LP64__
+ if (!flop)
+ return -1;
+#endif
+ __asm__ __volatile__ (
+" depd,z %3,60,3,%%r19\n" /* r19=(ofs&7)*8 */
+" mtsp %4, %%sr1\n"
+" depd %%r0,63,3,%3\n"
+"1: ldd 0(%%sr1,%3),%0\n"
+"2: ldd 8(%%sr1,%3),%%r20\n"
+" subi 64,%%r19,%%r19\n"
+" mtsar %%r19\n"
+" shrpd %0,%%r20,%%sar,%0\n"
+" copy %%r0, %1\n"
+"3: \n"
+" .section .fixup,\"ax\"\n"
+"4: ldi -2, %1\n"
+ FIXUP_BRANCH(3b)
+" .previous\n"
+" .section __ex_table,\"aw\"\n"
+#ifdef __LP64__
+" .dword 1b,4b\n"
+" .dword 2b,4b\n"
+#else
+" .word 1b,4b\n"
+" .word 2b,4b\n"
+#endif
+" .previous\n"
+ : "=r" (val), "=r" (ret)
+ : "0" (val), "r" (saddr), "r" (regs->isr)
+ : "r19", "r20" );
+#else
+ {
+ unsigned long valh=0,vall=0;
+ __asm__ __volatile__ (
+" zdep %5,29,2,%%r19\n" /* r19=(ofs&3)*8 */
+" mtsp %6, %%sr1\n"
+" dep %%r0,31,2,%5\n"
+"1: ldw 0(%%sr1,%5),%0\n"
+"2: ldw 4(%%sr1,%5),%1\n"
+"3: ldw 8(%%sr1,%5),%%r20\n"
+" subi 32,%%r19,%%r19\n"
+" mtsar %%r19\n"
+" vshd %0,%1,%0\n"
+" vshd %1,%%r20,%1\n"
+" copy %%r0, %2\n"
+"4: \n"
+" .section .fixup,\"ax\"\n"
+"5: ldi -2, %2\n"
+ FIXUP_BRANCH(4b)
+" .previous\n"
+" .section __ex_table,\"aw\"\n"
+#ifdef __LP64__
+" .dword 1b,5b\n"
+" .dword 2b,5b\n"
+" .dword 3b,5b\n"
+#else
+" .word 1b,5b\n"
+" .word 2b,5b\n"
+" .word 3b,5b\n"
+#endif
+" .previous\n"
+ : "=r" (valh), "=r" (vall), "=r" (ret)
+ : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
+ : "r19", "r20" );
+ val=((__u64)valh<<32)|(__u64)vall;
+ }
+#endif
+
+ DPRINTF("val = 0x%llx\n", val);
+
+ if (flop)
+ regs->fr[toreg] = val;
+ else if (toreg)
+ regs->gr[toreg] = val;
+
+ return ret;
+}
+
+static int emulate_sth(struct pt_regs *regs, int frreg)
+{
+ unsigned long val = regs->gr[frreg];
+ int ret;
+
+ if (!frreg)
+ val = 0;
+
+ DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg,
+ val, regs->isr, regs->ior);
+
+ __asm__ __volatile__ (
+" mtsp %3, %%sr1\n"
+" extrw,u %1, 23, 8, %%r19\n"
+"1: stb %1, 1(%%sr1, %2)\n"
+"2: stb %%r19, 0(%%sr1, %2)\n"
+" copy %%r0, %0\n"
+"3: \n"
+" .section .fixup,\"ax\"\n"
+"4: ldi -2, %0\n"
+ FIXUP_BRANCH(3b)
+" .previous\n"
+" .section __ex_table,\"aw\"\n"
+#ifdef __LP64__
+" .dword 1b,4b\n"
+" .dword 2b,4b\n"
+#else
+" .word 1b,4b\n"
+" .word 2b,4b\n"
+#endif
+" .previous\n"
+ : "=r" (ret)
+ : "r" (val), "r" (regs->ior), "r" (regs->isr)
+ : "r19" );
+
+ return ret;
+}
+
+static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
+{
+ unsigned long val;
+ int ret;
+
+ if (flop)
+ val = ((__u32*)(regs->fr))[frreg];
+ else if (frreg)
+ val = regs->gr[frreg];
+ else
+ val = 0;
+
+ DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg,
+ val, regs->isr, regs->ior);
+
+
+ __asm__ __volatile__ (
+" mtsp %3, %%sr1\n"
+" zdep %2, 28, 2, %%r19\n"
+" dep %%r0, 31, 2, %2\n"
+" mtsar %%r19\n"
+" depwi,z -2, %%sar, 32, %%r19\n"
+"1: ldw 0(%%sr1,%2),%%r20\n"
+"2: ldw 4(%%sr1,%2),%%r21\n"
+" vshd %%r0, %1, %%r22\n"
+" vshd %1, %%r0, %%r1\n"
+" and %%r20, %%r19, %%r20\n"
+" andcm %%r21, %%r19, %%r21\n"
+" or %%r22, %%r20, %%r20\n"
+" or %%r1, %%r21, %%r21\n"
+" stw %%r20,0(%%sr1,%2)\n"
+" stw %%r21,4(%%sr1,%2)\n"
+" copy %%r0, %0\n"
+"3: \n"
+" .section .fixup,\"ax\"\n"
+"4: ldi -2, %0\n"
+ FIXUP_BRANCH(3b)
+" .previous\n"
+" .section __ex_table,\"aw\"\n"
+#ifdef __LP64__
+" .dword 1b,4b\n"
+" .dword 2b,4b\n"
+#else
+" .word 1b,4b\n"
+" .word 2b,4b\n"
+#endif
+" .previous\n"
+ : "=r" (ret)
+ : "r" (val), "r" (regs->ior), "r" (regs->isr)
+ : "r19", "r20", "r21", "r22", "r1" );
+
+ return 0;
+}
+static int emulate_std(struct pt_regs *regs, int frreg, int flop)
+{
+ __u64 val;
+ int ret;
+
+ if (flop)
+ val = regs->fr[frreg];
+ else if (frreg)
+ val = regs->gr[frreg];
+ else
+ val = 0;
+
+ DPRINTF("store r%d (0x%016llx) to " RFMT ":" RFMT " for 8 bytes\n", frreg,
+ val, regs->isr, regs->ior);
+
+#ifdef CONFIG_PA20
+#ifndef __LP64__
+ if (!flop)
+ return -1;
+#endif
+ __asm__ __volatile__ (
+" mtsp %3, %%sr1\n"
+" depd,z %2, 60, 3, %%r19\n"
+" depd %%r0, 63, 3, %2\n"
+" mtsar %%r19\n"
+" depdi,z -2, %%sar, 64, %%r19\n"
+"1: ldd 0(%%sr1,%2),%%r20\n"
+"2: ldd 8(%%sr1,%2),%%r21\n"
+" shrpd %%r0, %1, %%sar, %%r22\n"
+" shrpd %1, %%r0, %%sar, %%r1\n"
+" and %%r20, %%r19, %%r20\n"
+" andcm %%r21, %%r19, %%r21\n"
+" or %%r22, %%r20, %%r20\n"
+" or %%r1, %%r21, %%r21\n"
+"3: std %%r20,0(%%sr1,%2)\n"
+"4: std %%r21,8(%%sr1,%2)\n"
+" copy %%r0, %0\n"
+"5: \n"
+" .section .fixup,\"ax\"\n"
+"6: ldi -2, %0\n"
+ FIXUP_BRANCH(5b)
+" .previous\n"
+" .section __ex_table,\"aw\"\n"
+#ifdef __LP64__
+" .dword 1b,6b\n"
+" .dword 2b,6b\n"
+" .dword 3b,6b\n"
+" .dword 4b,6b\n"
+#else
+" .word 1b,6b\n"
+" .word 2b,6b\n"
+" .word 3b,6b\n"
+" .word 4b,6b\n"
+#endif
+" .previous\n"
+ : "=r" (ret)
+ : "r" (val), "r" (regs->ior), "r" (regs->isr)
+ : "r19", "r20", "r21", "r22", "r1" );
+#else
+ {
+ unsigned long valh=(val>>32),vall=(val&0xffffffffl);
+ __asm__ __volatile__ (
+" mtsp %4, %%sr1\n"
+" zdep %2, 29, 2, %%r19\n"
+" dep %%r0, 31, 2, %2\n"
+" mtsar %%r19\n"
+" zvdepi -2, 32, %%r19\n"
+"1: ldw 0(%%sr1,%3),%%r20\n"
+"2: ldw 8(%%sr1,%3),%%r21\n"
+" vshd %1, %2, %%r1\n"
+" vshd %%r0, %1, %1\n"
+" vshd %2, %%r0, %2\n"
+" and %%r20, %%r19, %%r20\n"
+" andcm %%r21, %%r19, %%r21\n"
+" or %1, %%r20, %1\n"
+" or %2, %%r21, %2\n"
+"3: stw %1,0(%%sr1,%1)\n"
+"4: stw %%r1,4(%%sr1,%3)\n"
+"5: stw %2,8(%%sr1,%3)\n"
+" copy %%r0, %0\n"
+"6: \n"
+" .section .fixup,\"ax\"\n"
+"7: ldi -2, %0\n"
+ FIXUP_BRANCH(6b)
+" .previous\n"
+" .section __ex_table,\"aw\"\n"
+#ifdef __LP64__
+" .dword 1b,7b\n"
+" .dword 2b,7b\n"
+" .dword 3b,7b\n"
+" .dword 4b,7b\n"
+" .dword 5b,7b\n"
+#else
+" .word 1b,7b\n"
+" .word 2b,7b\n"
+" .word 3b,7b\n"
+" .word 4b,7b\n"
+" .word 5b,7b\n"
+#endif
+" .previous\n"
+ : "=r" (ret)
+ : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
+ : "r19", "r20", "r21", "r1" );
+ }
+#endif
+
+ return ret;
+}
+
+void handle_unaligned(struct pt_regs *regs)
+{
+ static unsigned long unaligned_count = 0;
+ static unsigned long last_time = 0;
+ unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
+ int modify = 0;
+ int ret = ERR_NOTHANDLED;
+ struct siginfo si;
+ register int flop=0; /* true if this is a flop */
+
+ /* log a message with pacing */
+ if (user_mode(regs))
+ {
+ if (unaligned_count > 5 && jiffies - last_time > 5*HZ)
+ {
+ unaligned_count = 0;
+ last_time = jiffies;
+ }
+ if (++unaligned_count < 5)
+ {
+ char buf[256];
+ sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n",
+ current->comm, current->pid, regs->ior, regs->iaoq[0]);
+ printk(KERN_WARNING "%s", buf);
+#ifdef DEBUG_UNALIGNED
+ show_regs(regs);
+#endif
+ }
+ if (!unaligned_enabled)
+ goto force_sigbus;
+ }
+
+ /* handle modification - OK, it's ugly, see the instruction manual */
+ switch (MAJOR_OP(regs->iir))
+ {
+ case 0x03:
+ case 0x09:
+ case 0x0b:
+ if (regs->iir&0x20)
+ {
+ modify = 1;
+ if (regs->iir&0x1000) /* short loads */
+ if (regs->iir&0x200)
+ newbase += IM5_3(regs->iir);
+ else
+ newbase += IM5_2(regs->iir);
+ else if (regs->iir&0x2000) /* scaled indexed */
+ {
+ int shift=0;
+ switch (regs->iir & OPCODE1_MASK)
+ {
+ case OPCODE_LDH_I:
+ shift= 1; break;
+ case OPCODE_LDW_I:
+ shift= 2; break;
+ case OPCODE_LDD_I:
+ case OPCODE_LDDA_I:
+ shift= 3; break;
+ }
+ newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift;
+ } else /* simple indexed */
+ newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0);
+ }
+ break;
+ case 0x13:
+ case 0x1b:
+ modify = 1;
+ newbase += IM14(regs->iir);
+ break;
+ case 0x14:
+ case 0x1c:
+ if (regs->iir&8)
+ {
+ modify = 1;
+ newbase += IM14(regs->iir&~0xe);
+ }
+ break;
+ case 0x16:
+ case 0x1e:
+ modify = 1;
+ newbase += IM14(regs->iir&6);
+ break;
+ case 0x17:
+ case 0x1f:
+ if (regs->iir&4)
+ {
+ modify = 1;
+ newbase += IM14(regs->iir&~4);
+ }
+ break;
+ }
+
+ /* TODO: make this cleaner... */
+ switch (regs->iir & OPCODE1_MASK)
+ {
+ case OPCODE_LDH_I:
+ case OPCODE_LDH_S:
+ ret = emulate_ldh(regs, R3(regs->iir));
+ break;
+
+ case OPCODE_LDW_I:
+ case OPCODE_LDWA_I:
+ case OPCODE_LDW_S:
+ case OPCODE_LDWA_S:
+ ret = emulate_ldw(regs, R3(regs->iir),0);
+ break;
+
+ case OPCODE_STH:
+ ret = emulate_sth(regs, R2(regs->iir));
+ break;
+
+ case OPCODE_STW:
+ case OPCODE_STWA:
+ ret = emulate_stw(regs, R2(regs->iir),0);
+ break;
+
+#ifdef CONFIG_PA20
+ case OPCODE_LDD_I:
+ case OPCODE_LDDA_I:
+ case OPCODE_LDD_S:
+ case OPCODE_LDDA_S:
+ ret = emulate_ldd(regs, R3(regs->iir),0);
+ break;
+
+ case OPCODE_STD:
+ case OPCODE_STDA:
+ ret = emulate_std(regs, R2(regs->iir),0);
+ break;
+#endif
+
+ case OPCODE_FLDWX:
+ case OPCODE_FLDWS:
+ case OPCODE_FLDWXR:
+ case OPCODE_FLDWSR:
+ flop=1;
+ ret = emulate_ldw(regs,FR3(regs->iir),1);
+ break;
+
+ case OPCODE_FLDDX:
+ case OPCODE_FLDDS:
+ flop=1;
+ ret = emulate_ldd(regs,R3(regs->iir),1);
+ break;
+
+ case OPCODE_FSTWX:
+ case OPCODE_FSTWS:
+ case OPCODE_FSTWXR:
+ case OPCODE_FSTWSR:
+ flop=1;
+ ret = emulate_stw(regs,FR3(regs->iir),1);
+ break;
+
+ case OPCODE_FSTDX:
+ case OPCODE_FSTDS:
+ flop=1;
+ ret = emulate_std(regs,R3(regs->iir),1);
+ break;
+
+ case OPCODE_LDCD_I:
+ case OPCODE_LDCW_I:
+ case OPCODE_LDCD_S:
+ case OPCODE_LDCW_S:
+ ret = ERR_NOTHANDLED; /* "undefined", but lets kill them. */
+ break;
+ }
+#ifdef CONFIG_PA20
+ switch (regs->iir & OPCODE2_MASK)
+ {
+ case OPCODE_FLDD_L:
+ flop=1;
+ ret = emulate_ldd(regs,R2(regs->iir),1);
+ break;
+ case OPCODE_FSTD_L:
+ flop=1;
+ ret = emulate_std(regs, R2(regs->iir),1);
+ break;
+
+#ifdef CONFIG_PA20
+ case OPCODE_LDD_L:
+ ret = emulate_ldd(regs, R2(regs->iir),0);
+ break;
+ case OPCODE_STD_L:
+ ret = emulate_std(regs, R2(regs->iir),0);
+ break;
+#endif
+ }
+#endif
+ switch (regs->iir & OPCODE3_MASK)
+ {
+ case OPCODE_FLDW_L:
+ flop=1;
+ ret = emulate_ldw(regs, R2(regs->iir),0);
+ break;
+ case OPCODE_LDW_M:
+ ret = emulate_ldw(regs, R2(regs->iir),1);
+ break;
+
+ case OPCODE_FSTW_L:
+ flop=1;
+ ret = emulate_stw(regs, R2(regs->iir),1);
+ break;
+ case OPCODE_STW_M:
+ ret = emulate_stw(regs, R2(regs->iir),0);
+ break;
+ }
+ switch (regs->iir & OPCODE4_MASK)
+ {
+ case OPCODE_LDH_L:
+ ret = emulate_ldh(regs, R2(regs->iir));
+ break;
+ case OPCODE_LDW_L:
+ case OPCODE_LDWM:
+ ret = emulate_ldw(regs, R2(regs->iir),0);
+ break;
+ case OPCODE_STH_L:
+ ret = emulate_sth(regs, R2(regs->iir));
+ break;
+ case OPCODE_STW_L:
+ case OPCODE_STWM:
+ ret = emulate_stw(regs, R2(regs->iir),0);
+ break;
+ }
+
+ if (modify && R1(regs->iir))
+ regs->gr[R1(regs->iir)] = newbase;
+
+
+ if (ret == ERR_NOTHANDLED)
+ printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir);
+
+ DPRINTF("ret = %d\n", ret);
+
+ if (ret)
+ {
+ printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
+ die_if_kernel("Unaligned data reference", regs, 28);
+
+ if (ret == ERR_PAGEFAULT)
+ {
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SEGV_MAPERR;
+ si.si_addr = (void __user *)regs->ior;
+ force_sig_info(SIGSEGV, &si, current);
+ }
+ else
+ {
+force_sigbus:
+ /* couldn't handle it ... */
+ si.si_signo = SIGBUS;
+ si.si_errno = 0;
+ si.si_code = BUS_ADRALN;
+ si.si_addr = (void __user *)regs->ior;
+ force_sig_info(SIGBUS, &si, current);
+ }
+
+ return;
+ }
+
+ /* else we handled it, let life go on. */
+ regs->gr[0]|=PSW_N;
+}
+
+/*
+ * NB: check_unaligned() is only used for PCXS processors right
+ * now, so we only check for PA1.1 encodings at this point.
+ */
+
+int
+check_unaligned(struct pt_regs *regs)
+{
+ unsigned long align_mask;
+
+ /* Get alignment mask */
+
+ align_mask = 0UL;
+ switch (regs->iir & OPCODE1_MASK) {
+
+ case OPCODE_LDH_I:
+ case OPCODE_LDH_S:
+ case OPCODE_STH:
+ align_mask = 1UL;
+ break;
+
+ case OPCODE_LDW_I:
+ case OPCODE_LDWA_I:
+ case OPCODE_LDW_S:
+ case OPCODE_LDWA_S:
+ case OPCODE_STW:
+ case OPCODE_STWA:
+ align_mask = 3UL;
+ break;
+
+ default:
+ switch (regs->iir & OPCODE4_MASK) {
+ case OPCODE_LDH_L:
+ case OPCODE_STH_L:
+ align_mask = 1UL;
+ break;
+ case OPCODE_LDW_L:
+ case OPCODE_LDWM:
+ case OPCODE_STW_L:
+ case OPCODE_STWM:
+ align_mask = 3UL;
+ break;
+ }
+ break;
+ }
+
+ return (int)(regs->ior & align_mask);
+}
+
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
new file mode 100644
index 000000000000..db141108412e
--- /dev/null
+++ b/arch/parisc/kernel/unwind.c
@@ -0,0 +1,393 @@
+/*
+ * Kernel unwinding support
+ *
+ * (c) 2002-2004 Randolph Chung <tausq@debian.org>
+ *
+ * Derived partially from the IA64 implementation. The PA-RISC
+ * Runtime Architecture Document is also a useful reference to
+ * understand what is happening here
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kallsyms.h>
+
+#include <asm/uaccess.h>
+#include <asm/assembly.h>
+
+#include <asm/unwind.h>
+
+/* #define DEBUG 1 */
+#ifdef DEBUG
+#define dbg(x...) printk(x)
+#else
+#define dbg(x...)
+#endif
+
+extern struct unwind_table_entry __start___unwind[];
+extern struct unwind_table_entry __stop___unwind[];
+
+static spinlock_t unwind_lock;
+/*
+ * the kernel unwind block is not dynamically allocated so that
+ * we can call unwind_init as early in the bootup process as
+ * possible (before the slab allocator is initialized)
+ */
+static struct unwind_table kernel_unwind_table;
+static LIST_HEAD(unwind_tables);
+
+static inline const struct unwind_table_entry *
+find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
+{
+ const struct unwind_table_entry *e = NULL;
+ unsigned long lo, hi, mid;
+
+ lo = 0;
+ hi = table->length - 1;
+
+ while (lo <= hi) {
+ mid = (hi - lo) / 2 + lo;
+ e = &table->table[mid];
+ if (addr < e->region_start)
+ hi = mid - 1;
+ else if (addr > e->region_end)
+ lo = mid + 1;
+ else
+ return e;
+ }
+
+ return NULL;
+}
+
+static const struct unwind_table_entry *
+find_unwind_entry(unsigned long addr)
+{
+ struct unwind_table *table;
+ const struct unwind_table_entry *e = NULL;
+
+ if (addr >= kernel_unwind_table.start &&
+ addr <= kernel_unwind_table.end)
+ e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
+ else
+ list_for_each_entry(table, &unwind_tables, list) {
+ if (addr >= table->start &&
+ addr <= table->end)
+ e = find_unwind_entry_in_table(table, addr);
+ if (e)
+ break;
+ }
+
+ return e;
+}
+
+static void
+unwind_table_init(struct unwind_table *table, const char *name,
+ unsigned long base_addr, unsigned long gp,
+ void *table_start, void *table_end)
+{
+ struct unwind_table_entry *start = table_start;
+ struct unwind_table_entry *end =
+ (struct unwind_table_entry *)table_end - 1;
+
+ table->name = name;
+ table->base_addr = base_addr;
+ table->gp = gp;
+ table->start = base_addr + start->region_start;
+ table->end = base_addr + end->region_end;
+ table->table = (struct unwind_table_entry *)table_start;
+ table->length = end - start + 1;
+ INIT_LIST_HEAD(&table->list);
+
+ for (; start <= end; start++) {
+ if (start < end &&
+ start->region_end > (start+1)->region_start) {
+ printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1);
+ }
+
+ start->region_start += base_addr;
+ start->region_end += base_addr;
+ }
+}
+
+static void
+unwind_table_sort(struct unwind_table_entry *start,
+ struct unwind_table_entry *finish)
+{
+ struct unwind_table_entry el, *p, *q;
+
+ for (p = start + 1; p < finish; ++p) {
+ if (p[0].region_start < p[-1].region_start) {
+ el = *p;
+ q = p;
+ do {
+ q[0] = q[-1];
+ --q;
+ } while (q > start &&
+ el.region_start < q[-1].region_start);
+ *q = el;
+ }
+ }
+}
+
+struct unwind_table *
+unwind_table_add(const char *name, unsigned long base_addr,
+ unsigned long gp,
+ void *start, void *end)
+{
+ struct unwind_table *table;
+ unsigned long flags;
+ struct unwind_table_entry *s = (struct unwind_table_entry *)start;
+ struct unwind_table_entry *e = (struct unwind_table_entry *)end;
+
+ unwind_table_sort(s, e);
+
+ table = kmalloc(sizeof(struct unwind_table), GFP_USER);
+ if (table == NULL)
+ return NULL;
+ unwind_table_init(table, name, base_addr, gp, start, end);
+ spin_lock_irqsave(&unwind_lock, flags);
+ list_add_tail(&table->list, &unwind_tables);
+ spin_unlock_irqrestore(&unwind_lock, flags);
+
+ return table;
+}
+
+void unwind_table_remove(struct unwind_table *table)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&unwind_lock, flags);
+ list_del(&table->list);
+ spin_unlock_irqrestore(&unwind_lock, flags);
+
+ kfree(table);
+}
+
+/* Called from setup_arch to import the kernel unwind info */
+static int unwind_init(void)
+{
+ long start, stop;
+ register unsigned long gp __asm__ ("r27");
+
+ start = (long)&__start___unwind[0];
+ stop = (long)&__stop___unwind[0];
+
+ spin_lock_init(&unwind_lock);
+
+ printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
+ start, stop,
+ (stop - start) / sizeof(struct unwind_table_entry));
+
+ unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
+ gp,
+ &__start___unwind[0], &__stop___unwind[0]);
+#if 0
+ {
+ int i;
+ for (i = 0; i < 10; i++)
+ {
+ printk("region 0x%x-0x%x\n",
+ __start___unwind[i].region_start,
+ __start___unwind[i].region_end);
+ }
+ }
+#endif
+ return 0;
+}
+
+static void unwind_frame_regs(struct unwind_frame_info *info)
+{
+ const struct unwind_table_entry *e;
+ unsigned long npc;
+ unsigned int insn;
+ long frame_size = 0;
+ int looking_for_rp, rpoffset = 0;
+
+ e = find_unwind_entry(info->ip);
+ if (e == NULL) {
+ unsigned long sp;
+ extern char _stext[], _etext[];
+
+ dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
+
+#ifdef CONFIG_KALLSYMS
+ /* Handle some frequent special cases.... */
+ {
+ char symname[KSYM_NAME_LEN+1];
+ char *modname;
+ unsigned long symsize, offset;
+
+ kallsyms_lookup(info->ip, &symsize, &offset,
+ &modname, symname);
+
+ dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname);
+
+ if (strcmp(symname, "_switch_to_ret") == 0) {
+ info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
+ info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
+ dbg("_switch_to_ret @ %lx - setting "
+ "prev_sp=%lx prev_ip=%lx\n",
+ info->ip, info->prev_sp,
+ info->prev_ip);
+ return;
+ } else if (strcmp(symname, "ret_from_kernel_thread") == 0 ||
+ strcmp(symname, "syscall_exit") == 0) {
+ info->prev_ip = info->prev_sp = 0;
+ return;
+ }
+ }
+#endif
+
+ /* Since we are doing the unwinding blind, we don't know if
+ we are adjusting the stack correctly or extracting the rp
+ correctly. The rp is checked to see if it belongs to the
+ kernel text section, if not we assume we don't have a
+ correct stack frame and we continue to unwind the stack.
+ This is not quite correct, and will fail for loadable
+ modules. */
+ sp = info->sp & ~63;
+ do {
+ unsigned long tmp;
+
+ info->prev_sp = sp - 64;
+ info->prev_ip = 0;
+ if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET)))
+ break;
+ info->prev_ip = tmp;
+ sp = info->prev_sp;
+ } while (info->prev_ip < (unsigned long)_stext ||
+ info->prev_ip > (unsigned long)_etext);
+
+ info->rp = 0;
+
+ dbg("analyzing func @ %lx with no unwind info, setting "
+ "prev_sp=%lx prev_ip=%lx\n", info->ip,
+ info->prev_sp, info->prev_ip);
+ } else {
+ dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
+ "Save_RP = %d, Millicode = %d size = %u\n",
+ e->region_start, e->region_end, e->Save_SP, e->Save_RP,
+ e->Millicode, e->Total_frame_size);
+
+ looking_for_rp = e->Save_RP;
+
+ for (npc = e->region_start;
+ (frame_size < (e->Total_frame_size << 3) ||
+ looking_for_rp) &&
+ npc < info->ip;
+ npc += 4) {
+
+ insn = *(unsigned int *)npc;
+
+ if ((insn & 0xffffc000) == 0x37de0000 ||
+ (insn & 0xffe00000) == 0x6fc00000) {
+ /* ldo X(sp), sp, or stwm X,D(sp) */
+ frame_size += (insn & 0x1 ? -1 << 13 : 0) |
+ ((insn & 0x3fff) >> 1);
+ dbg("analyzing func @ %lx, insn=%08x @ "
+ "%lx, frame_size = %ld\n", info->ip,
+ insn, npc, frame_size);
+ } else if ((insn & 0xffe00008) == 0x73c00008) {
+ /* std,ma X,D(sp) */
+ frame_size += (insn & 0x1 ? -1 << 13 : 0) |
+ (((insn >> 4) & 0x3ff) << 3);
+ dbg("analyzing func @ %lx, insn=%08x @ "
+ "%lx, frame_size = %ld\n", info->ip,
+ insn, npc, frame_size);
+ } else if (insn == 0x6bc23fd9) {
+ /* stw rp,-20(sp) */
+ rpoffset = 20;
+ looking_for_rp = 0;
+ dbg("analyzing func @ %lx, insn=stw rp,"
+ "-20(sp) @ %lx\n", info->ip, npc);
+ } else if (insn == 0x0fc212c1) {
+ /* std rp,-16(sr0,sp) */
+ rpoffset = 16;
+ looking_for_rp = 0;
+ dbg("analyzing func @ %lx, insn=std rp,"
+ "-16(sp) @ %lx\n", info->ip, npc);
+ }
+ }
+
+ info->prev_sp = info->sp - frame_size;
+ if (e->Millicode)
+ info->rp = info->r31;
+ else if (rpoffset)
+ info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
+ info->prev_ip = info->rp;
+ info->rp = 0;
+
+ dbg("analyzing func @ %lx, setting prev_sp=%lx "
+ "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
+ info->prev_ip, npc);
+ }
+}
+
+void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
+ struct pt_regs *regs)
+{
+ memset(info, 0, sizeof(struct unwind_frame_info));
+ info->t = t;
+ info->sp = regs->gr[30];
+ info->ip = regs->iaoq[0];
+ info->rp = regs->gr[2];
+ info->r31 = regs->gr[31];
+
+ dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
+ t ? (int)t->pid : -1, info->sp, info->ip);
+}
+
+void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
+{
+ struct pt_regs *r = &t->thread.regs;
+ struct pt_regs *r2;
+
+ r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+ if (!r2)
+ return;
+ *r2 = *r;
+ r2->gr[30] = r->ksp;
+ r2->iaoq[0] = r->kpc;
+ unwind_frame_init(info, t, r2);
+ kfree(r2);
+}
+
+void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs)
+{
+ unwind_frame_init(info, current, regs);
+}
+
+int unwind_once(struct unwind_frame_info *next_frame)
+{
+ unwind_frame_regs(next_frame);
+
+ if (next_frame->prev_sp == 0 ||
+ next_frame->prev_ip == 0)
+ return -1;
+
+ next_frame->sp = next_frame->prev_sp;
+ next_frame->ip = next_frame->prev_ip;
+ next_frame->prev_sp = 0;
+ next_frame->prev_ip = 0;
+
+ dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n",
+ next_frame->t ? (int)next_frame->t->pid : -1,
+ next_frame->sp, next_frame->ip);
+
+ return 0;
+}
+
+int unwind_to_user(struct unwind_frame_info *info)
+{
+ int ret;
+
+ do {
+ ret = unwind_once(info);
+ } while (!ret && !(info->ip & 3));
+
+ return ret;
+}
+
+module_init(unwind_init);
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..e5fac3e08c7a
--- /dev/null
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -0,0 +1,207 @@
+/* Kernel link layout for various "sections"
+ *
+ * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
+ * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
+ * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
+ * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
+ * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
+ * Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/config.h>
+#include <asm-generic/vmlinux.lds.h>
+/* needed for the processor specific cache alignment size */
+#include <asm/cache.h>
+#include <asm/page.h>
+
+/* ld script to make hppa Linux kernel */
+#ifndef CONFIG_64BIT
+OUTPUT_FORMAT("elf32-hppa-linux")
+OUTPUT_ARCH(hppa)
+#else
+OUTPUT_FORMAT("elf64-hppa-linux")
+OUTPUT_ARCH(hppa:hppa2.0w)
+#endif
+
+ENTRY(_stext)
+#ifndef CONFIG_64BIT
+jiffies = jiffies_64 + 4;
+#else
+jiffies = jiffies_64;
+#endif
+SECTIONS
+{
+
+ . = KERNEL_BINARY_TEXT_START;
+
+ _text = .; /* Text and read-only data */
+ .text ALIGN(16) : {
+ *(.text)
+ SCHED_TEXT
+ LOCK_TEXT
+ *(.text.do_softirq)
+ *(.text.sys_exit)
+ *(.text.do_sigaltstack)
+ *(.text.do_fork)
+ *(.text.*)
+ *(.fixup)
+ *(.lock.text) /* out-of-line lock text */
+ *(.gnu.warning)
+ } = 0
+
+ _etext = .; /* End of text section */
+
+ RODATA
+
+ /* writeable */
+ . = ALIGN(4096); /* Make sure this is paged aligned so
+ that we can properly leave these
+ as writable */
+ data_start = .;
+
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ __start___unwind = .; /* unwind info */
+ .PARISC.unwind : { *(.PARISC.unwind) }
+ __stop___unwind = .;
+
+ .data : { /* Data */
+ *(.data)
+ *(.data.vm0.pmd)
+ *(.data.vm0.pgd)
+ *(.data.vm0.pte)
+ CONSTRUCTORS
+ }
+
+ . = ALIGN(4096);
+ /* nosave data is really only used for software suspend...it's here
+ * just in case we ever implement it */
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(4096);
+ __nosave_end = .;
+
+ . = ALIGN(L1_CACHE_BYTES);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+ /* PA-RISC locks requires 16-byte alignment */
+ . = ALIGN(16);
+ .data.lock_aligned : { *(.data.lock_aligned) }
+
+ _edata = .; /* End of data section */
+
+ . = ALIGN(16384); /* init_task */
+ .data.init_task : { *(.data.init_task) }
+
+ /* The interrupt stack is currently partially coded, but not yet
+ * implemented */
+ . = ALIGN(16384);
+ init_istack : { *(init_istack) }
+
+#ifdef CONFIG_64BIT
+ . = ALIGN(16); /* Linkage tables */
+ .opd : { *(.opd) } PROVIDE (__gp = .);
+ .plt : { *(.plt) }
+ .dlt : { *(.dlt) }
+#endif
+
+ . = ALIGN(16384);
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ .init.data : { *(.init.data) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .init.setup : { *(.init.setup) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
+ __initcall_end = .;
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
+ SECURITY_INIT
+ /* alternate instruction replacement. This is a mechanism x86 uses
+ * to detect the CPU type and replace generic instruction sequences
+ * with CPU specific ones. We don't currently do this in PA, but
+ * it seems like a good idea... */
+ . = ALIGN(4);
+ __alt_instructions = .;
+ .altinstructions : { *(.altinstructions) }
+ __alt_instructions_end = .;
+ .altinstr_replacement : { *(.altinstr_replacement) }
+ /* .exit.text is discard at runtime, not link time, to deal with references
+ from .altinstructions and .eh_frame */
+ .exit.text : { *(.exit.text) }
+ .exit.data : { *(.exit.data) }
+ . = ALIGN(4096);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+ . = ALIGN(32);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
+ /* freed after init ends here */
+
+ __bss_start = .; /* BSS */
+ .bss : { *(.bss) *(COMMON) }
+ __bss_stop = .;
+
+ _end = . ;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exitcall.exit)
+#ifdef CONFIG_64BIT
+ /* temporary hack until binutils is fixed to not emit these
+ for static binaries */
+ *(.interp)
+ *(.dynsym)
+ *(.dynstr)
+ *(.dynamic)
+ *(.hash)
+#endif
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .note 0 : { *(.note) }
+
+}
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
new file mode 100644
index 000000000000..7bf705676297
--- /dev/null
+++ b/arch/parisc/lib/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for parisc-specific library files
+#
+
+lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
+
+obj-y := iomap.o
+
+lib-$(CONFIG_SMP) += debuglocks.o
diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c
new file mode 100644
index 000000000000..2de182f6fe8a
--- /dev/null
+++ b/arch/parisc/lib/bitops.c
@@ -0,0 +1,84 @@
+/*
+ * bitops.c: atomic operations which got too long to be inlined all over
+ * the place.
+ *
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ * Copyright 2000 Grant Grundler (grundler@cup.hp.com)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#ifdef CONFIG_SMP
+spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
+ [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+};
+#endif
+
+#ifdef __LP64__
+unsigned long __xchg64(unsigned long x, unsigned long *ptr)
+{
+ unsigned long temp, flags;
+
+ _atomic_spin_lock_irqsave(ptr, flags);
+ temp = *ptr;
+ *ptr = x;
+ _atomic_spin_unlock_irqrestore(ptr, flags);
+ return temp;
+}
+#endif
+
+unsigned long __xchg32(int x, int *ptr)
+{
+ unsigned long flags;
+ long temp;
+
+ _atomic_spin_lock_irqsave(ptr, flags);
+ temp = (long) *ptr; /* XXX - sign extension wanted? */
+ *ptr = x;
+ _atomic_spin_unlock_irqrestore(ptr, flags);
+ return (unsigned long)temp;
+}
+
+
+unsigned long __xchg8(char x, char *ptr)
+{
+ unsigned long flags;
+ long temp;
+
+ _atomic_spin_lock_irqsave(ptr, flags);
+ temp = (long) *ptr; /* XXX - sign extension wanted? */
+ *ptr = x;
+ _atomic_spin_unlock_irqrestore(ptr, flags);
+ return (unsigned long)temp;
+}
+
+
+#ifdef __LP64__
+unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new)
+{
+ unsigned long flags;
+ unsigned long prev;
+
+ _atomic_spin_lock_irqsave(ptr, flags);
+ if ((prev = *ptr) == old)
+ *ptr = new;
+ _atomic_spin_unlock_irqrestore(ptr, flags);
+ return prev;
+}
+#endif
+
+unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new)
+{
+ unsigned long flags;
+ unsigned int prev;
+
+ _atomic_spin_lock_irqsave(ptr, flags);
+ if ((prev = *ptr) == old)
+ *ptr = new;
+ _atomic_spin_unlock_irqrestore(ptr, flags);
+ return (unsigned long)prev;
+}
diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
new file mode 100644
index 000000000000..8a1e08068e7d
--- /dev/null
+++ b/arch/parisc/lib/checksum.c
@@ -0,0 +1,148 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * MIPS specific IP/TCP/UDP checksumming routines
+ *
+ * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * $Id: checksum.c,v 1.3 1997/12/01 17:57:34 ralf Exp $
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <net/checksum.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#define addc(_t,_r) \
+ __asm__ __volatile__ ( \
+" add %0, %1, %0\n" \
+" addc %0, %%r0, %0\n" \
+ : "=r"(_t) \
+ : "r"(_r), "0"(_t));
+
+static inline unsigned short from32to16(unsigned int x)
+{
+ /* 32 bits --> 16 bits + carry */
+ x = (x & 0xffff) + (x >> 16);
+ /* 16 bits + carry --> 16 bits including carry */
+ x = (x & 0xffff) + (x >> 16);
+ return (unsigned short)x;
+}
+
+static inline unsigned int do_csum(const unsigned char * buff, int len)
+{
+ int odd, count;
+ unsigned int result = 0;
+
+ if (len <= 0)
+ goto out;
+ odd = 1 & (unsigned long) buff;
+ if (odd) {
+ result = be16_to_cpu(*buff);
+ len--;
+ buff++;
+ }
+ count = len >> 1; /* nr of 16-bit words.. */
+ if (count) {
+ if (2 & (unsigned long) buff) {
+ result += *(unsigned short *) buff;
+ count--;
+ len -= 2;
+ buff += 2;
+ }
+ count >>= 1; /* nr of 32-bit words.. */
+ if (count) {
+ while (count >= 4) {
+ unsigned int r1, r2, r3, r4;
+ r1 = *(unsigned int *)(buff + 0);
+ r2 = *(unsigned int *)(buff + 4);
+ r3 = *(unsigned int *)(buff + 8);
+ r4 = *(unsigned int *)(buff + 12);
+ addc(result, r1);
+ addc(result, r2);
+ addc(result, r3);
+ addc(result, r4);
+ count -= 4;
+ buff += 16;
+ }
+ while (count) {
+ unsigned int w = *(unsigned int *) buff;
+ count--;
+ buff += 4;
+ addc(result, w);
+ }
+ result = (result & 0xffff) + (result >> 16);
+ }
+ if (len & 2) {
+ result += *(unsigned short *) buff;
+ buff += 2;
+ }
+ }
+ if (len & 1)
+ result += le16_to_cpu(*buff);
+ result = from32to16(result);
+ if (odd)
+ result = swab16(result);
+out:
+ return result;
+}
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+{
+ unsigned int result = do_csum(buff, len);
+ addc(result, sum);
+ return from32to16(result);
+}
+
+EXPORT_SYMBOL(csum_partial);
+
+/*
+ * copy while checksumming, otherwise like csum_partial
+ */
+unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
+ int len, unsigned int sum)
+{
+ /*
+ * It's 2:30 am and I don't feel like doing it real ...
+ * This is lots slower than the real thing (tm)
+ */
+ sum = csum_partial(src, len, sum);
+ memcpy(dst, src, len);
+
+ return sum;
+}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+/*
+ * Copy from userspace and compute checksum. If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
+ unsigned char *dst, int len,
+ unsigned int sum, int *err_ptr)
+{
+ int missing;
+
+ missing = copy_from_user(dst, src, len);
+ if (missing) {
+ memset(dst + len - missing, 0, missing);
+ *err_ptr = -EFAULT;
+ }
+
+ return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
diff --git a/arch/parisc/lib/debuglocks.c b/arch/parisc/lib/debuglocks.c
new file mode 100644
index 000000000000..1b33fe6e5b7a
--- /dev/null
+++ b/arch/parisc/lib/debuglocks.c
@@ -0,0 +1,277 @@
+/*
+ * Debugging versions of SMP locking primitives.
+ *
+ * Copyright (C) 2004 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * Some code stollen from alpha & sparc64 ;)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * We use pdc_printf() throughout the file for all output messages, to avoid
+ * losing messages because of disabled interrupts. Since we're using these
+ * messages for debugging purposes, it makes sense not to send them to the
+ * linux console.
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/hardirq.h> /* in_interrupt() */
+#include <asm/system.h>
+#include <asm/hardirq.h> /* in_interrupt() */
+#include <asm/pdc.h>
+
+#undef INIT_STUCK
+#define INIT_STUCK 1L << 30
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+
+
+void _dbg_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
+{
+ volatile unsigned int *a;
+ long stuck = INIT_STUCK;
+ void *inline_pc = __builtin_return_address(0);
+ unsigned long started = jiffies;
+ int printed = 0;
+ int cpu = smp_processor_id();
+
+try_again:
+
+ /* Do the actual locking */
+ /* <T-Bone> ggg: we can't get stuck on the outter loop?
+ * <ggg> T-Bone: We can hit the outer loop
+ * alot if multiple CPUs are constantly racing for a lock
+ * and the backplane is NOT fair about which CPU sees
+ * the update first. But it won't hang since every failed
+ * attempt will drop us back into the inner loop and
+ * decrement `stuck'.
+ * <ggg> K-class and some of the others are NOT fair in the HW
+ * implementation so we could see false positives.
+ * But fixing the lock contention is easier than
+ * fixing the HW to be fair.
+ * <tausq> __ldcw() returns 1 if we get the lock; otherwise we
+ * spin until the value of the lock changes, or we time out.
+ */
+ mb();
+ a = __ldcw_align(lock);
+ while (stuck && (__ldcw(a) == 0))
+ while ((*a == 0) && --stuck);
+ mb();
+
+ if (unlikely(stuck <= 0)) {
+ pdc_printf(
+ "%s:%d: spin_lock(%s/%p) stuck in %s at %p(%d)"
+ " owned by %s:%d in %s at %p(%d)\n",
+ base_file, line_no, lock->module, lock,
+ current->comm, inline_pc, cpu,
+ lock->bfile, lock->bline, lock->task->comm,
+ lock->previous, lock->oncpu);
+ stuck = INIT_STUCK;
+ printed = 1;
+ goto try_again;
+ }
+
+ /* Exiting. Got the lock. */
+ lock->oncpu = cpu;
+ lock->previous = inline_pc;
+ lock->task = current;
+ lock->bfile = (char *)base_file;
+ lock->bline = line_no;
+
+ if (unlikely(printed)) {
+ pdc_printf(
+ "%s:%d: spin_lock grabbed in %s at %p(%d) %ld ticks\n",
+ base_file, line_no, current->comm, inline_pc,
+ cpu, jiffies - started);
+ }
+}
+
+void _dbg_spin_unlock(spinlock_t * lock, const char *base_file, int line_no)
+{
+ CHECK_LOCK(lock);
+ volatile unsigned int *a;
+ mb();
+ a = __ldcw_align(lock);
+ if (unlikely((*a != 0) && lock->babble)) {
+ lock->babble--;
+ pdc_printf(
+ "%s:%d: spin_unlock(%s:%p) not locked\n",
+ base_file, line_no, lock->module, lock);
+ }
+ *a = 1;
+ mb();
+}
+
+int _dbg_spin_trylock(spinlock_t * lock, const char *base_file, int line_no)
+{
+ int ret;
+ volatile unsigned int *a;
+ mb();
+ a = __ldcw_align(lock);
+ ret = (__ldcw(a) != 0);
+ mb();
+ if (ret) {
+ lock->oncpu = smp_processor_id();
+ lock->previous = __builtin_return_address(0);
+ lock->task = current;
+ } else {
+ lock->bfile = (char *)base_file;
+ lock->bline = line_no;
+ }
+ return ret;
+}
+
+#endif /* CONFIG_DEBUG_SPINLOCK */
+
+#ifdef CONFIG_DEBUG_RWLOCK
+
+/* Interrupts trouble detailed explanation, thx Grant:
+ *
+ * o writer (wants to modify data) attempts to acquire the rwlock
+ * o He gets the write lock.
+ * o Interupts are still enabled, we take an interrupt with the
+ * write still holding the lock.
+ * o interrupt handler tries to acquire the rwlock for read.
+ * o deadlock since the writer can't release it at this point.
+ *
+ * In general, any use of spinlocks that competes between "base"
+ * level and interrupt level code will risk deadlock. Interrupts
+ * need to be disabled in the base level routines to avoid it.
+ * Or more precisely, only the IRQ the base level routine
+ * is competing with for the lock. But it's more efficient/faster
+ * to just disable all interrupts on that CPU to guarantee
+ * once it gets the lock it can release it quickly too.
+ */
+
+void _dbg_write_lock(rwlock_t *rw, const char *bfile, int bline)
+{
+ void *inline_pc = __builtin_return_address(0);
+ unsigned long started = jiffies;
+ long stuck = INIT_STUCK;
+ int printed = 0;
+ int cpu = smp_processor_id();
+
+ if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */
+ pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
+ BUG();
+ }
+
+ /* Note: if interrupts are disabled (which is most likely), the printk
+ will never show on the console. We might need a polling method to flush
+ the dmesg buffer anyhow. */
+
+retry:
+ _raw_spin_lock(&rw->lock);
+
+ if(rw->counter != 0) {
+ /* this basically never happens */
+ _raw_spin_unlock(&rw->lock);
+
+ stuck--;
+ if ((unlikely(stuck <= 0)) && (rw->counter < 0)) {
+ pdc_printf(
+ "%s:%d: write_lock stuck on writer"
+ " in %s at %p(%d) %ld ticks\n",
+ bfile, bline, current->comm, inline_pc,
+ cpu, jiffies - started);
+ stuck = INIT_STUCK;
+ printed = 1;
+ }
+ else if (unlikely(stuck <= 0)) {
+ pdc_printf(
+ "%s:%d: write_lock stuck on reader"
+ " in %s at %p(%d) %ld ticks\n",
+ bfile, bline, current->comm, inline_pc,
+ cpu, jiffies - started);
+ stuck = INIT_STUCK;
+ printed = 1;
+ }
+
+ while(rw->counter != 0);
+
+ goto retry;
+ }
+
+ /* got it. now leave without unlocking */
+ rw->counter = -1; /* remember we are locked */
+
+ if (unlikely(printed)) {
+ pdc_printf(
+ "%s:%d: write_lock grabbed in %s at %p(%d) %ld ticks\n",
+ bfile, bline, current->comm, inline_pc,
+ cpu, jiffies - started);
+ }
+}
+
+int _dbg_write_trylock(rwlock_t *rw, const char *bfile, int bline)
+{
+#if 0
+ void *inline_pc = __builtin_return_address(0);
+ int cpu = smp_processor_id();
+#endif
+
+ if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */
+ pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
+ BUG();
+ }
+
+ /* Note: if interrupts are disabled (which is most likely), the printk
+ will never show on the console. We might need a polling method to flush
+ the dmesg buffer anyhow. */
+
+ _raw_spin_lock(&rw->lock);
+
+ if(rw->counter != 0) {
+ /* this basically never happens */
+ _raw_spin_unlock(&rw->lock);
+ return 0;
+ }
+
+ /* got it. now leave without unlocking */
+ rw->counter = -1; /* remember we are locked */
+#if 0
+ pdc_printf("%s:%d: try write_lock grabbed in %s at %p(%d)\n",
+ bfile, bline, current->comm, inline_pc, cpu);
+#endif
+ return 1;
+}
+
+void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline)
+{
+#if 0
+ void *inline_pc = __builtin_return_address(0);
+ unsigned long started = jiffies;
+ int cpu = smp_processor_id();
+#endif
+ unsigned long flags;
+
+ local_irq_save(flags);
+ _raw_spin_lock(&rw->lock);
+
+ rw->counter++;
+#if 0
+ pdc_printf(
+ "%s:%d: read_lock grabbed in %s at %p(%d) %ld ticks\n",
+ bfile, bline, current->comm, inline_pc,
+ cpu, jiffies - started);
+#endif
+ _raw_spin_unlock(&rw->lock);
+ local_irq_restore(flags);
+}
+
+#endif /* CONFIG_DEBUG_RWLOCK */
diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S
new file mode 100644
index 000000000000..134f0cd240f5
--- /dev/null
+++ b/arch/parisc/lib/fixup.S
@@ -0,0 +1,89 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Copyright (C) 2004 Randolph Chung <tausq@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Fixup routines for kernel exception handling.
+ */
+#include <linux/config.h>
+#include <asm/offsets.h>
+#include <asm/assembly.h>
+#include <asm/errno.h>
+
+#ifdef CONFIG_SMP
+ .macro get_fault_ip t1 t2
+ addil LT%__per_cpu_offset,%r27
+ LDREG RT%__per_cpu_offset(%r1),\t1
+ /* t2 = smp_processor_id() */
+ mfctl 30,\t2
+ ldw TI_CPU(\t2),\t2
+#ifdef __LP64__
+ extrd,u \t2,63,32,\t2
+#endif
+ /* t2 = &__per_cpu_offset[smp_processor_id()]; */
+ LDREG,s \t2(\t1),\t2
+ addil LT%per_cpu__exception_data,%r27
+ LDREG RT%per_cpu__exception_data(%r1),\t1
+ /* t1 = &__get_cpu_var(exception_data) */
+ add,l \t1,\t2,\t1
+ /* t1 = t1->fault_ip */
+ LDREG EXCDATA_IP(\t1), \t1
+ .endm
+#else
+ .macro get_fault_ip t1 t2
+ /* t1 = &__get_cpu_var(exception_data) */
+ addil LT%per_cpu__exception_data,%r27
+ LDREG RT%per_cpu__exception_data(%r1),\t2
+ /* t1 = t2->fault_ip */
+ LDREG EXCDATA_IP(\t2), \t1
+ .endm
+#endif
+
+ .text
+ .section .fixup, "ax"
+
+ /* get_user() fixups, store -EFAULT in r8, and 0 in r9 */
+ .export fixup_get_user_skip_1
+fixup_get_user_skip_1:
+ get_fault_ip %r1,%r8
+ ldo 4(%r1), %r1
+ ldi -EFAULT, %r8
+ bv %r0(%r1)
+ copy %r0, %r9
+
+ .export fixup_get_user_skip_2
+fixup_get_user_skip_2:
+ get_fault_ip %r1,%r8
+ ldo 8(%r1), %r1
+ ldi -EFAULT, %r8
+ bv %r0(%r1)
+ copy %r0, %r9
+
+ /* put_user() fixups, store -EFAULT in r8 */
+ .export fixup_put_user_skip_1
+fixup_put_user_skip_1:
+ get_fault_ip %r1,%r8
+ ldo 4(%r1), %r1
+ bv %r0(%r1)
+ ldi -EFAULT, %r8
+
+ .export fixup_put_user_skip_2
+fixup_put_user_skip_2:
+ get_fault_ip %r1,%r8
+ ldo 8(%r1), %r1
+ bv %r0(%r1)
+ ldi -EFAULT, %r8
diff --git a/arch/parisc/lib/io.c b/arch/parisc/lib/io.c
new file mode 100644
index 000000000000..7c1406ff825e
--- /dev/null
+++ b/arch/parisc/lib/io.c
@@ -0,0 +1,488 @@
+/*
+ * arch/parisc/lib/io.c
+ *
+ * Copyright (c) Matthew Wilcox 2001 for Hewlett-Packard
+ * Copyright (c) Randolph Chung 2001 <tausq@debian.org>
+ *
+ * IO accessing functions which shouldn't be inlined because they're too big
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/* Copies a block of memory to a device in an efficient manner.
+ * Assumes the device can cope with 32-bit transfers. If it can't,
+ * don't use this function.
+ */
+void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+{
+ if (((unsigned long)dst & 3) != ((unsigned long)src & 3))
+ goto bytecopy;
+ while ((unsigned long)dst & 3) {
+ writeb(*(char *)src, dst++);
+ src++;
+ count--;
+ }
+ while (count > 3) {
+ __raw_writel(*(u32 *)src, dst);
+ src += 4;
+ dst += 4;
+ count -= 4;
+ }
+ bytecopy:
+ while (count--) {
+ writeb(*(char *)src, dst++);
+ src++;
+ }
+}
+
+/*
+** Copies a block of memory from a device in an efficient manner.
+** Assumes the device can cope with 32-bit transfers. If it can't,
+** don't use this function.
+**
+** CR16 counts on C3000 reading 256 bytes from Symbios 896 RAM:
+** 27341/64 = 427 cyc per int
+** 61311/128 = 478 cyc per short
+** 122637/256 = 479 cyc per byte
+** Ergo bus latencies dominant (not transfer size).
+** Minimize total number of transfers at cost of CPU cycles.
+** TODO: only look at src alignment and adjust the stores to dest.
+*/
+void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
+{
+ /* first compare alignment of src/dst */
+ if ( (((unsigned long)dst ^ (unsigned long)src) & 1) || (count < 2) )
+ goto bytecopy;
+
+ if ( (((unsigned long)dst ^ (unsigned long)src) & 2) || (count < 4) )
+ goto shortcopy;
+
+ /* Then check for misaligned start address */
+ if ((unsigned long)src & 1) {
+ *(u8 *)dst = readb(src);
+ src++;
+ dst++;
+ count--;
+ if (count < 2) goto bytecopy;
+ }
+
+ if ((unsigned long)src & 2) {
+ *(u16 *)dst = __raw_readw(src);
+ src += 2;
+ dst += 2;
+ count -= 2;
+ }
+
+ while (count > 3) {
+ *(u32 *)dst = __raw_readl(src);
+ dst += 4;
+ src += 4;
+ count -= 4;
+ }
+
+ shortcopy:
+ while (count > 1) {
+ *(u16 *)dst = __raw_readw(src);
+ src += 2;
+ dst += 2;
+ count -= 2;
+ }
+
+ bytecopy:
+ while (count--) {
+ *(char *)dst = readb(src);
+ src++;
+ dst++;
+ }
+}
+
+/* Sets a block of memory on a device to a given value.
+ * Assumes the device can cope with 32-bit transfers. If it can't,
+ * don't use this function.
+ */
+void memset_io(volatile void __iomem *addr, unsigned char val, int count)
+{
+ u32 val32 = (val << 24) | (val << 16) | (val << 8) | val;
+ while ((unsigned long)addr & 3) {
+ writeb(val, addr++);
+ count--;
+ }
+ while (count > 3) {
+ __raw_writel(val32, addr);
+ addr += 4;
+ count -= 4;
+ }
+ while (count--) {
+ writeb(val, addr++);
+ }
+}
+
+/*
+ * Read COUNT 8-bit bytes from port PORT into memory starting at
+ * SRC.
+ */
+void insb (unsigned long port, void *dst, unsigned long count)
+{
+ unsigned char *p;
+
+ p = (unsigned char *)dst;
+
+ while (((unsigned long)p) & 0x3) {
+ if (!count)
+ return;
+ count--;
+ *p = inb(port);
+ p++;
+ }
+
+ while (count >= 4) {
+ unsigned int w;
+ count -= 4;
+ w = inb(port) << 24;
+ w |= inb(port) << 16;
+ w |= inb(port) << 8;
+ w |= inb(port);
+ *(unsigned int *) p = w;
+ p += 4;
+ }
+
+ while (count) {
+ --count;
+ *p = inb(port);
+ p++;
+ }
+}
+
+
+/*
+ * Read COUNT 16-bit words from port PORT into memory starting at
+ * SRC. SRC must be at least short aligned. This is used by the
+ * IDE driver to read disk sectors. Performance is important, but
+ * the interfaces seems to be slow: just using the inlined version
+ * of the inw() breaks things.
+ */
+void insw (unsigned long port, void *dst, unsigned long count)
+{
+ unsigned int l = 0, l2;
+ unsigned char *p;
+
+ p = (unsigned char *)dst;
+
+ if (!count)
+ return;
+
+ switch (((unsigned long)p) & 0x3)
+ {
+ case 0x00: /* Buffer 32-bit aligned */
+ while (count>=2) {
+
+ count -= 2;
+ l = cpu_to_le16(inw(port)) << 16;
+ l |= cpu_to_le16(inw(port));
+ *(unsigned int *)p = l;
+ p += 4;
+ }
+ if (count) {
+ *(unsigned short *)p = cpu_to_le16(inw(port));
+ }
+ break;
+
+ case 0x02: /* Buffer 16-bit aligned */
+ *(unsigned short *)p = cpu_to_le16(inw(port));
+ p += 2;
+ count--;
+ while (count>=2) {
+
+ count -= 2;
+ l = cpu_to_le16(inw(port)) << 16;
+ l |= cpu_to_le16(inw(port));
+ *(unsigned int *)p = l;
+ p += 4;
+ }
+ if (count) {
+ *(unsigned short *)p = cpu_to_le16(inw(port));
+ }
+ break;
+
+ case 0x01: /* Buffer 8-bit aligned */
+ case 0x03:
+ /* I don't bother with 32bit transfers
+ * in this case, 16bit will have to do -- DE */
+ --count;
+
+ l = cpu_to_le16(inw(port));
+ *p = l >> 8;
+ p++;
+ while (count--)
+ {
+ l2 = cpu_to_le16(inw(port));
+ *(unsigned short *)p = (l & 0xff) << 8 | (l2 >> 8);
+ p += 2;
+ l = l2;
+ }
+ *p = l & 0xff;
+ break;
+ }
+}
+
+
+
+/*
+ * Read COUNT 32-bit words from port PORT into memory starting at
+ * SRC. Now works with any alignment in SRC. Performance is important,
+ * but the interfaces seems to be slow: just using the inlined version
+ * of the inl() breaks things.
+ */
+void insl (unsigned long port, void *dst, unsigned long count)
+{
+ unsigned int l = 0, l2;
+ unsigned char *p;
+
+ p = (unsigned char *)dst;
+
+ if (!count)
+ return;
+
+ switch (((unsigned long) dst) & 0x3)
+ {
+ case 0x00: /* Buffer 32-bit aligned */
+ while (count--)
+ {
+ *(unsigned int *)p = cpu_to_le32(inl(port));
+ p += 4;
+ }
+ break;
+
+ case 0x02: /* Buffer 16-bit aligned */
+ --count;
+
+ l = cpu_to_le32(inl(port));
+ *(unsigned short *)p = l >> 16;
+ p += 2;
+
+ while (count--)
+ {
+ l2 = cpu_to_le32(inl(port));
+ *(unsigned int *)p = (l & 0xffff) << 16 | (l2 >> 16);
+ p += 4;
+ l = l2;
+ }
+ *(unsigned short *)p = l & 0xffff;
+ break;
+ case 0x01: /* Buffer 8-bit aligned */
+ --count;
+
+ l = cpu_to_le32(inl(port));
+ *(unsigned char *)p = l >> 24;
+ p++;
+ *(unsigned short *)p = (l >> 8) & 0xffff;
+ p += 2;
+ while (count--)
+ {
+ l2 = cpu_to_le32(inl(port));
+ *(unsigned int *)p = (l & 0xff) << 24 | (l2 >> 8);
+ p += 4;
+ l = l2;
+ }
+ *p = l & 0xff;
+ break;
+ case 0x03: /* Buffer 8-bit aligned */
+ --count;
+
+ l = cpu_to_le32(inl(port));
+ *p = l >> 24;
+ p++;
+ while (count--)
+ {
+ l2 = cpu_to_le32(inl(port));
+ *(unsigned int *)p = (l & 0xffffff) << 8 | l2 >> 24;
+ p += 4;
+ l = l2;
+ }
+ *(unsigned short *)p = (l >> 8) & 0xffff;
+ p += 2;
+ *p = l & 0xff;
+ break;
+ }
+}
+
+
+/*
+ * Like insb but in the opposite direction.
+ * Don't worry as much about doing aligned memory transfers:
+ * doing byte reads the "slow" way isn't nearly as slow as
+ * doing byte writes the slow way (no r-m-w cycle).
+ */
+void outsb(unsigned long port, const void * src, unsigned long count)
+{
+ const unsigned char *p;
+
+ p = (const unsigned char *)src;
+ while (count) {
+ count--;
+ outb(*p, port);
+ p++;
+ }
+}
+
+/*
+ * Like insw but in the opposite direction. This is used by the IDE
+ * driver to write disk sectors. Performance is important, but the
+ * interfaces seems to be slow: just using the inlined version of the
+ * outw() breaks things.
+ */
+void outsw (unsigned long port, const void *src, unsigned long count)
+{
+ unsigned int l = 0, l2;
+ const unsigned char *p;
+
+ p = (const unsigned char *)src;
+
+ if (!count)
+ return;
+
+ switch (((unsigned long)p) & 0x3)
+ {
+ case 0x00: /* Buffer 32-bit aligned */
+ while (count>=2) {
+ count -= 2;
+ l = *(unsigned int *)p;
+ p += 4;
+ outw(le16_to_cpu(l >> 16), port);
+ outw(le16_to_cpu(l & 0xffff), port);
+ }
+ if (count) {
+ outw(le16_to_cpu(*(unsigned short*)p), port);
+ }
+ break;
+
+ case 0x02: /* Buffer 16-bit aligned */
+
+ outw(le16_to_cpu(*(unsigned short*)p), port);
+ p += 2;
+ count--;
+
+ while (count>=2) {
+ count -= 2;
+ l = *(unsigned int *)p;
+ p += 4;
+ outw(le16_to_cpu(l >> 16), port);
+ outw(le16_to_cpu(l & 0xffff), port);
+ }
+ if (count) {
+ outw(le16_to_cpu(*(unsigned short *)p), port);
+ }
+ break;
+
+ case 0x01: /* Buffer 8-bit aligned */
+ /* I don't bother with 32bit transfers
+ * in this case, 16bit will have to do -- DE */
+
+ l = *p << 8;
+ p++;
+ count--;
+ while (count)
+ {
+ count--;
+ l2 = *(unsigned short *)p;
+ p += 2;
+ outw(le16_to_cpu(l | l2 >> 8), port);
+ l = l2 << 8;
+ }
+ l2 = *(unsigned char *)p;
+ outw (le16_to_cpu(l | l2>>8), port);
+ break;
+
+ }
+}
+
+
+/*
+ * Like insl but in the opposite direction. This is used by the IDE
+ * driver to write disk sectors. Works with any alignment in SRC.
+ * Performance is important, but the interfaces seems to be slow:
+ * just using the inlined version of the outl() breaks things.
+ */
+void outsl (unsigned long port, const void *src, unsigned long count)
+{
+ unsigned int l = 0, l2;
+ const unsigned char *p;
+
+ p = (const unsigned char *)src;
+
+ if (!count)
+ return;
+
+ switch (((unsigned long)p) & 0x3)
+ {
+ case 0x00: /* Buffer 32-bit aligned */
+ while (count--)
+ {
+ outl(le32_to_cpu(*(unsigned int *)p), port);
+ p += 4;
+ }
+ break;
+
+ case 0x02: /* Buffer 16-bit aligned */
+ --count;
+
+ l = *(unsigned short *)p;
+ p += 2;
+
+ while (count--)
+ {
+ l2 = *(unsigned int *)p;
+ p += 4;
+ outl (le32_to_cpu(l << 16 | l2 >> 16), port);
+ l = l2;
+ }
+ l2 = *(unsigned short *)p;
+ outl (le32_to_cpu(l << 16 | l2), port);
+ break;
+ case 0x01: /* Buffer 8-bit aligned */
+ --count;
+
+ l = *p << 24;
+ p++;
+ l |= *(unsigned short *)p << 8;
+ p += 2;
+
+ while (count--)
+ {
+ l2 = *(unsigned int *)p;
+ p += 4;
+ outl (le32_to_cpu(l | l2 >> 24), port);
+ l = l2 << 8;
+ }
+ l2 = *p;
+ outl (le32_to_cpu(l | l2), port);
+ break;
+ case 0x03: /* Buffer 8-bit aligned */
+ --count;
+
+ l = *p << 24;
+ p++;
+
+ while (count--)
+ {
+ l2 = *(unsigned int *)p;
+ p += 4;
+ outl (le32_to_cpu(l | l2 >> 8), port);
+ l = l2 << 24;
+ }
+ l2 = *(unsigned short *)p << 16;
+ p += 2;
+ l2 |= *p;
+ outl (le32_to_cpu(l | l2), port);
+ break;
+ }
+}
+
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(outsl);
diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c
new file mode 100644
index 000000000000..290a62e7120b
--- /dev/null
+++ b/arch/parisc/lib/iomap.c
@@ -0,0 +1,422 @@
+/*
+ * iomap.c - Implement iomap interface for PA-RISC
+ * Copyright (c) 2004 Matthew Wilcox
+ */
+
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+/*
+ * The iomap space on 32-bit PA-RISC is intended to look like this:
+ * 00000000-7fffffff virtual mapped IO
+ * 80000000-8fffffff ISA/EISA port space that can't be virtually mapped
+ * 90000000-9fffffff Dino port space
+ * a0000000-afffffff Astro port space
+ * b0000000-bfffffff PAT port space
+ * c0000000-cfffffff non-swapped memory IO
+ * f0000000-ffffffff legacy IO memory pointers
+ *
+ * For the moment, here's what it looks like:
+ * 80000000-8fffffff All ISA/EISA port space
+ * f0000000-ffffffff legacy IO memory pointers
+ *
+ * On 64-bit, everything is extended, so:
+ * 8000000000000000-8fffffffffffffff All ISA/EISA port space
+ * f000000000000000-ffffffffffffffff legacy IO memory pointers
+ */
+
+/*
+ * Technically, this should be 'if (VMALLOC_START < addr < VMALLOC_END),
+ * but that's slow and we know it'll be within the first 2GB.
+ */
+#ifdef CONFIG_64BIT
+#define INDIRECT_ADDR(addr) (((unsigned long)(addr) & 1UL<<63) != 0)
+#define ADDR_TO_REGION(addr) (((unsigned long)addr >> 60) & 7)
+#define IOPORT_MAP_BASE (8UL << 60)
+#else
+#define INDIRECT_ADDR(addr) (((unsigned long)(addr) & 1UL<<31) != 0)
+#define ADDR_TO_REGION(addr) (((unsigned long)addr >> 28) & 7)
+#define IOPORT_MAP_BASE (8UL << 28)
+#endif
+
+struct iomap_ops {
+ unsigned int (*read8)(void __iomem *);
+ unsigned int (*read16)(void __iomem *);
+ unsigned int (*read32)(void __iomem *);
+ void (*write8)(u8, void __iomem *);
+ void (*write16)(u16, void __iomem *);
+ void (*write32)(u32, void __iomem *);
+ void (*read8r)(void __iomem *, void *, unsigned long);
+ void (*read16r)(void __iomem *, void *, unsigned long);
+ void (*read32r)(void __iomem *, void *, unsigned long);
+ void (*write8r)(void __iomem *, const void *, unsigned long);
+ void (*write16r)(void __iomem *, const void *, unsigned long);
+ void (*write32r)(void __iomem *, const void *, unsigned long);
+};
+
+/* Generic ioport ops. To be replaced later by specific dino/elroy/wax code */
+
+#define ADDR2PORT(addr) ((unsigned long __force)(addr) & 0xffffff)
+
+static unsigned int ioport_read8(void __iomem *addr)
+{
+ return inb(ADDR2PORT(addr));
+}
+
+static unsigned int ioport_read16(void __iomem *addr)
+{
+ return inw(ADDR2PORT(addr));
+}
+
+static unsigned int ioport_read32(void __iomem *addr)
+{
+ return inl(ADDR2PORT(addr));
+}
+
+static void ioport_write8(u8 datum, void __iomem *addr)
+{
+ outb(datum, ADDR2PORT(addr));
+}
+
+static void ioport_write16(u16 datum, void __iomem *addr)
+{
+ outw(datum, ADDR2PORT(addr));
+}
+
+static void ioport_write32(u32 datum, void __iomem *addr)
+{
+ outl(datum, ADDR2PORT(addr));
+}
+
+static void ioport_read8r(void __iomem *addr, void *dst, unsigned long count)
+{
+ insb(ADDR2PORT(addr), dst, count);
+}
+
+static void ioport_read16r(void __iomem *addr, void *dst, unsigned long count)
+{
+ insw(ADDR2PORT(addr), dst, count);
+}
+
+static void ioport_read32r(void __iomem *addr, void *dst, unsigned long count)
+{
+ insl(ADDR2PORT(addr), dst, count);
+}
+
+static void ioport_write8r(void __iomem *addr, const void *s, unsigned long n)
+{
+ outsb(ADDR2PORT(addr), s, n);
+}
+
+static void ioport_write16r(void __iomem *addr, const void *s, unsigned long n)
+{
+ outsw(ADDR2PORT(addr), s, n);
+}
+
+static void ioport_write32r(void __iomem *addr, const void *s, unsigned long n)
+{
+ outsl(ADDR2PORT(addr), s, n);
+}
+
+static const struct iomap_ops ioport_ops = {
+ ioport_read8,
+ ioport_read16,
+ ioport_read32,
+ ioport_write8,
+ ioport_write16,
+ ioport_write32,
+ ioport_read8r,
+ ioport_read16r,
+ ioport_read32r,
+ ioport_write8r,
+ ioport_write16r,
+ ioport_write32r,
+};
+
+/* Legacy I/O memory ops */
+
+static unsigned int iomem_read8(void __iomem *addr)
+{
+ return readb(addr);
+}
+
+static unsigned int iomem_read16(void __iomem *addr)
+{
+ return readw(addr);
+}
+
+static unsigned int iomem_read32(void __iomem *addr)
+{
+ return readl(addr);
+}
+
+static void iomem_write8(u8 datum, void __iomem *addr)
+{
+ writeb(datum, addr);
+}
+
+static void iomem_write16(u16 datum, void __iomem *addr)
+{
+ writew(datum, addr);
+}
+
+static void iomem_write32(u32 datum, void __iomem *addr)
+{
+ writel(datum, addr);
+}
+
+static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count)
+{
+ while (count--) {
+ *(u8 *)dst = __raw_readb(addr);
+ dst++;
+ }
+}
+
+static void iomem_read16r(void __iomem *addr, void *dst, unsigned long count)
+{
+ while (count--) {
+ *(u16 *)dst = __raw_readw(addr);
+ dst += 2;
+ }
+}
+
+static void iomem_read32r(void __iomem *addr, void *dst, unsigned long count)
+{
+ while (count--) {
+ *(u32 *)dst = __raw_readl(addr);
+ dst += 4;
+ }
+}
+
+static void iomem_write8r(void __iomem *addr, const void *s, unsigned long n)
+{
+ while (n--) {
+ __raw_writeb(*(u8 *)s, addr);
+ s++;
+ }
+}
+
+static void iomem_write16r(void __iomem *addr, const void *s, unsigned long n)
+{
+ while (n--) {
+ __raw_writew(*(u16 *)s, addr);
+ s += 2;
+ }
+}
+
+static void iomem_write32r(void __iomem *addr, const void *s, unsigned long n)
+{
+ while (n--) {
+ __raw_writel(*(u32 *)s, addr);
+ s += 4;
+ }
+}
+
+static const struct iomap_ops iomem_ops = {
+ iomem_read8,
+ iomem_read16,
+ iomem_read32,
+ iomem_write8,
+ iomem_write16,
+ iomem_write32,
+ iomem_read8r,
+ iomem_read16r,
+ iomem_read32r,
+ iomem_write8r,
+ iomem_write16r,
+ iomem_write32r,
+};
+
+const struct iomap_ops *iomap_ops[8] = {
+ [0] = &ioport_ops,
+#ifdef CONFIG_DEBUG_IOREMAP
+ [6] = &iomem_ops,
+#else
+ [7] = &iomem_ops
+#endif
+};
+
+
+unsigned int ioread8(void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr)))
+ return iomap_ops[ADDR_TO_REGION(addr)]->read8(addr);
+ return *((u8 *)addr);
+}
+
+unsigned int ioread16(void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr)))
+ return iomap_ops[ADDR_TO_REGION(addr)]->read16(addr);
+ return le16_to_cpup((u16 *)addr);
+}
+
+unsigned int ioread32(void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr)))
+ return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr);
+ return le32_to_cpup((u32 *)addr);
+}
+
+void iowrite8(u8 datum, void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->write8(datum, addr);
+ } else {
+ *((u8 *)addr) = datum;
+ }
+}
+
+void iowrite16(u16 datum, void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->write16(datum, addr);
+ } else {
+ *((u16 *)addr) = cpu_to_le16(datum);
+ }
+}
+
+void iowrite32(u32 datum, void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->write32(datum, addr);
+ } else {
+ *((u32 *)addr) = cpu_to_le32(datum);
+ }
+}
+
+/* Repeating interfaces */
+
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->read8r(addr, dst, count);
+ } else {
+ while (count--) {
+ *(u8 *)dst = *(u8 *)addr;
+ dst++;
+ }
+ }
+}
+
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->read16r(addr, dst, count);
+ } else {
+ while (count--) {
+ *(u16 *)dst = *(u16 *)addr;
+ dst += 2;
+ }
+ }
+}
+
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->read32r(addr, dst, count);
+ } else {
+ while (count--) {
+ *(u32 *)dst = *(u32 *)addr;
+ dst += 4;
+ }
+ }
+}
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->write8r(addr, src, count);
+ } else {
+ while (count--) {
+ *(u8 *)addr = *(u8 *)src;
+ src++;
+ }
+ }
+}
+
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->write16r(addr, src, count);
+ } else {
+ while (count--) {
+ *(u16 *)addr = *(u16 *)src;
+ src += 2;
+ }
+ }
+}
+
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->write32r(addr, src, count);
+ } else {
+ while (count--) {
+ *(u32 *)addr = *(u32 *)src;
+ src += 4;
+ }
+ }
+}
+
+/* Mapping interfaces */
+
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+ return (void __iomem *)(IOPORT_MAP_BASE | port);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+ if (!INDIRECT_ADDR(addr)) {
+ iounmap(addr);
+ }
+}
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+ unsigned long start = pci_resource_start(dev, bar);
+ unsigned long len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+ return NULL;
+ if (maxlen && len > maxlen)
+ len = maxlen;
+ if (flags & IORESOURCE_IO)
+ return ioport_map(start, len);
+ if (flags & IORESOURCE_MEM) {
+ if (flags & IORESOURCE_CACHEABLE)
+ return ioremap(start, len);
+ return ioremap_nocache(start, len);
+ }
+ /* What? */
+ return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+ if (!INDIRECT_ADDR(addr)) {
+ iounmap(addr);
+ }
+}
+
+EXPORT_SYMBOL(ioread8);
+EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread32);
+EXPORT_SYMBOL(iowrite8);
+EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite32);
+EXPORT_SYMBOL(ioread8_rep);
+EXPORT_SYMBOL(ioread16_rep);
+EXPORT_SYMBOL(ioread32_rep);
+EXPORT_SYMBOL(iowrite8_rep);
+EXPORT_SYMBOL(iowrite16_rep);
+EXPORT_SYMBOL(iowrite32_rep);
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S
new file mode 100644
index 000000000000..a0509855c9a7
--- /dev/null
+++ b/arch/parisc/lib/lusercopy.S
@@ -0,0 +1,193 @@
+/*
+ * User Space Access Routines
+ *
+ * Copyright (C) 2000-2002 Hewlett-Packard (John Marvin)
+ * Copyright (C) 2000 Richard Hirst <rhirst with parisc-linux.org>
+ * Copyright (C) 2001 Matthieu Delahaye <delahaym at esiee.fr>
+ * Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * These routines still have plenty of room for optimization
+ * (word & doubleword load/store, dual issue, store hints, etc.).
+ */
+
+/*
+ * The following routines assume that space register 3 (sr3) contains
+ * the space id associated with the current users address space.
+ */
+
+
+ .text
+
+#include <asm/assembly.h>
+#include <asm/errno.h>
+
+ /*
+ * get_sr gets the appropriate space value into
+ * sr1 for kernel/user space access, depending
+ * on the flag stored in the task structure.
+ */
+
+ .macro get_sr
+ mfctl %cr30,%r1
+ ldw TI_SEGMENT(%r1),%r22
+ mfsp %sr3,%r1
+ or,<> %r22,%r0,%r0
+ copy %r0,%r1
+ mtsp %r1,%sr1
+ .endm
+
+ .macro fixup_branch lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv %r0(%r1)
+ .endm
+
+ /*
+ * long lstrncpy_from_user(char *dst, const char *src, long n)
+ *
+ * Returns -EFAULT if exception before terminator,
+ * N if the entire buffer filled,
+ * otherwise strlen (i.e. excludes zero byte)
+ */
+
+ .export lstrncpy_from_user,code
+lstrncpy_from_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,= 0,%r24,$lsfu_done
+ copy %r24,%r23
+ get_sr
+1: ldbs,ma 1(%sr1,%r25),%r1
+$lsfu_loop:
+ stbs,ma %r1,1(%r26)
+ comib,=,n 0,%r1,$lsfu_done
+ addib,<>,n -1,%r24,$lsfu_loop
+2: ldbs,ma 1(%sr1,%r25),%r1
+$lsfu_done:
+ sub %r23,%r24,%r28
+$lsfu_exit:
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .section .fixup,"ax"
+3: fixup_branch $lsfu_exit
+ ldi -EFAULT,%r28
+ .previous
+
+ .section __ex_table,"aw"
+#ifdef __LP64__
+ .dword 1b,3b
+ .dword 2b,3b
+#else
+ .word 1b,3b
+ .word 2b,3b
+#endif
+ .previous
+
+ .procend
+
+ /*
+ * unsigned long lclear_user(void *to, unsigned long n)
+ *
+ * Returns 0 for success.
+ * otherwise, returns number of bytes not transferred.
+ */
+
+ .export lclear_user,code
+lclear_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,=,n 0,%r25,$lclu_done
+ get_sr
+$lclu_loop:
+ addib,<> -1,%r25,$lclu_loop
+1: stbs,ma %r0,1(%sr1,%r26)
+
+$lclu_done:
+ bv %r0(%r2)
+ copy %r25,%r28
+ .exit
+
+ .section .fixup,"ax"
+2: fixup_branch $lclu_done
+ ldo 1(%r25),%r25
+ .previous
+
+ .section __ex_table,"aw"
+#ifdef __LP64__
+ .dword 1b,2b
+#else
+ .word 1b,2b
+#endif
+ .previous
+
+ .procend
+
+ /*
+ * long lstrnlen_user(char *s, long n)
+ *
+ * Returns 0 if exception before zero byte or reaching N,
+ * N+1 if N would be exceeded,
+ * else strlen + 1 (i.e. includes zero byte).
+ */
+
+ .export lstrnlen_user,code
+lstrnlen_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,= 0,%r25,$lslen_nzero
+ copy %r26,%r24
+ get_sr
+1: ldbs,ma 1(%sr1,%r26),%r1
+$lslen_loop:
+ comib,=,n 0,%r1,$lslen_done
+ addib,<> -1,%r25,$lslen_loop
+2: ldbs,ma 1(%sr1,%r26),%r1
+$lslen_done:
+ bv %r0(%r2)
+ sub %r26,%r24,%r28
+ .exit
+
+$lslen_nzero:
+ b $lslen_done
+ ldo 1(%r26),%r26 /* special case for N == 0 */
+
+ .section .fixup,"ax"
+3: fixup_branch $lslen_done
+ copy %r24,%r26 /* reset r26 so 0 is returned on fault */
+ .previous
+
+ .section __ex_table,"aw"
+#ifdef __LP64__
+ .dword 1b,3b
+ .dword 2b,3b
+#else
+ .word 1b,3b
+ .word 2b,3b
+#endif
+ .previous
+
+ .procend
+
+ .end
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
new file mode 100644
index 000000000000..feb1b9f42c2b
--- /dev/null
+++ b/arch/parisc/lib/memcpy.c
@@ -0,0 +1,522 @@
+/*
+ * Optimized memory copy routines.
+ *
+ * Copyright (C) 2004 Randolph Chung <tausq@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Portions derived from the GNU C Library
+ * Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
+ *
+ * Several strategies are tried to try to get the best performance for various
+ * conditions. In the optimal case, we copy 64-bytes in an unrolled loop using
+ * fp regs. This is followed by loops that copy 32- or 16-bytes at a time using
+ * general registers. Unaligned copies are handled either by aligning the
+ * destination and then using shift-and-write method, or in a few cases by
+ * falling back to a byte-at-a-time copy.
+ *
+ * I chose to implement this in C because it is easier to maintain and debug,
+ * and in my experiments it appears that the C code generated by gcc (3.3/3.4
+ * at the time of writing) is fairly optimal. Unfortunately some of the
+ * semantics of the copy routine (exception handling) is difficult to express
+ * in C, so we have to play some tricks to get it to work.
+ *
+ * All the loads and stores are done via explicit asm() code in order to use
+ * the right space registers.
+ *
+ * Testing with various alignments and buffer sizes shows that this code is
+ * often >10x faster than a simple byte-at-a-time copy, even for strangely
+ * aligned operands. It is interesting to note that the glibc version
+ * of memcpy (written in C) is actually quite fast already. This routine is
+ * able to beat it by 30-40% for aligned copies because of the loop unrolling,
+ * but in some cases the glibc version is still slightly faster. This lends
+ * more credibility that gcc can generate very good code as long as we are
+ * careful.
+ *
+ * TODO:
+ * - cache prefetching needs more experimentation to get optimal settings
+ * - try not to use the post-increment address modifiers; they create additional
+ * interlocks
+ * - replace byte-copy loops with stybs sequences
+ */
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/compiler.h>
+#include <asm/uaccess.h>
+#define s_space "%%sr1"
+#define d_space "%%sr2"
+#else
+#include "memcpy.h"
+#define s_space "%%sr0"
+#define d_space "%%sr0"
+#define pa_memcpy new2_copy
+#endif
+
+DECLARE_PER_CPU(struct exception_data, exception_data);
+
+#define preserve_branch(label) do { \
+ volatile int dummy; \
+ /* The following branch is never taken, it's just here to */ \
+ /* prevent gcc from optimizing away our exception code. */ \
+ if (unlikely(dummy != dummy)) \
+ goto label; \
+} while (0)
+
+#define get_user_space() (segment_eq(get_fs(), KERNEL_DS) ? 0 : mfsp(3))
+#define get_kernel_space() (0)
+
+#define MERGE(w0, sh_1, w1, sh_2) ({ \
+ unsigned int _r; \
+ asm volatile ( \
+ "mtsar %3\n" \
+ "shrpw %1, %2, %%sar, %0\n" \
+ : "=r"(_r) \
+ : "r"(w0), "r"(w1), "r"(sh_2) \
+ ); \
+ _r; \
+})
+#define THRESHOLD 16
+
+#ifdef DEBUG_MEMCPY
+#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+#ifndef __LP64__
+#define EXC_WORD ".word"
+#else
+#define EXC_WORD ".dword"
+#endif
+
+#define def_load_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e) \
+ __asm__ __volatile__ ( \
+ "1:\t" #_insn ",ma " #_sz "(" _s ",%1), %0\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t" EXC_WORD "\t1b\n" \
+ "\t" EXC_WORD "\t" #_e "\n" \
+ "\t.previous\n" \
+ : _tt(_t), "+r"(_a) \
+ : \
+ : "r8")
+
+#define def_store_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e) \
+ __asm__ __volatile__ ( \
+ "1:\t" #_insn ",ma %1, " #_sz "(" _s ",%0)\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t" EXC_WORD "\t1b\n" \
+ "\t" EXC_WORD "\t" #_e "\n" \
+ "\t.previous\n" \
+ : "+r"(_a) \
+ : _tt(_t) \
+ : "r8")
+
+#define ldbma(_s, _a, _t, _e) def_load_ai_insn(ldbs,1,"=r",_s,_a,_t,_e)
+#define stbma(_s, _t, _a, _e) def_store_ai_insn(stbs,1,"r",_s,_a,_t,_e)
+#define ldwma(_s, _a, _t, _e) def_load_ai_insn(ldw,4,"=r",_s,_a,_t,_e)
+#define stwma(_s, _t, _a, _e) def_store_ai_insn(stw,4,"r",_s,_a,_t,_e)
+#define flddma(_s, _a, _t, _e) def_load_ai_insn(fldd,8,"=f",_s,_a,_t,_e)
+#define fstdma(_s, _t, _a, _e) def_store_ai_insn(fstd,8,"f",_s,_a,_t,_e)
+
+#define def_load_insn(_insn,_tt,_s,_o,_a,_t,_e) \
+ __asm__ __volatile__ ( \
+ "1:\t" #_insn " " #_o "(" _s ",%1), %0\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t" EXC_WORD "\t1b\n" \
+ "\t" EXC_WORD "\t" #_e "\n" \
+ "\t.previous\n" \
+ : _tt(_t) \
+ : "r"(_a) \
+ : "r8")
+
+#define def_store_insn(_insn,_tt,_s,_t,_o,_a,_e) \
+ __asm__ __volatile__ ( \
+ "1:\t" #_insn " %0, " #_o "(" _s ",%1)\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t" EXC_WORD "\t1b\n" \
+ "\t" EXC_WORD "\t" #_e "\n" \
+ "\t.previous\n" \
+ : \
+ : _tt(_t), "r"(_a) \
+ : "r8")
+
+#define ldw(_s,_o,_a,_t,_e) def_load_insn(ldw,"=r",_s,_o,_a,_t,_e)
+#define stw(_s,_t,_o,_a,_e) def_store_insn(stw,"r",_s,_t,_o,_a,_e)
+
+#ifdef CONFIG_PREFETCH
+extern inline void prefetch_src(const void *addr)
+{
+ __asm__("ldw 0(" s_space ",%0), %%r0" : : "r" (addr));
+}
+
+extern inline void prefetch_dst(const void *addr)
+{
+ __asm__("ldd 0(" d_space ",%0), %%r0" : : "r" (addr));
+}
+#else
+#define prefetch_src(addr)
+#define prefetch_dst(addr)
+#endif
+
+/* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
+ * per loop. This code is derived from glibc.
+ */
+static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src, unsigned long len, unsigned long o_dst, unsigned long o_src, unsigned long o_len)
+{
+ /* gcc complains that a2 and a3 may be uninitialized, but actually
+ * they cannot be. Initialize a2/a3 to shut gcc up.
+ */
+ register unsigned int a0, a1, a2 = 0, a3 = 0;
+ int sh_1, sh_2;
+ struct exception_data *d;
+
+ /* prefetch_src((const void *)src); */
+
+ /* Calculate how to shift a word read at the memory operation
+ aligned srcp to make it aligned for copy. */
+ sh_1 = 8 * (src % sizeof(unsigned int));
+ sh_2 = 8 * sizeof(unsigned int) - sh_1;
+
+ /* Make src aligned by rounding it down. */
+ src &= -sizeof(unsigned int);
+
+ switch (len % 4)
+ {
+ case 2:
+ /* a1 = ((unsigned int *) src)[0];
+ a2 = ((unsigned int *) src)[1]; */
+ ldw(s_space, 0, src, a1, cda_ldw_exc);
+ ldw(s_space, 4, src, a2, cda_ldw_exc);
+ src -= 1 * sizeof(unsigned int);
+ dst -= 3 * sizeof(unsigned int);
+ len += 2;
+ goto do1;
+ case 3:
+ /* a0 = ((unsigned int *) src)[0];
+ a1 = ((unsigned int *) src)[1]; */
+ ldw(s_space, 0, src, a0, cda_ldw_exc);
+ ldw(s_space, 4, src, a1, cda_ldw_exc);
+ src -= 0 * sizeof(unsigned int);
+ dst -= 2 * sizeof(unsigned int);
+ len += 1;
+ goto do2;
+ case 0:
+ if (len == 0)
+ return 0;
+ /* a3 = ((unsigned int *) src)[0];
+ a0 = ((unsigned int *) src)[1]; */
+ ldw(s_space, 0, src, a3, cda_ldw_exc);
+ ldw(s_space, 4, src, a0, cda_ldw_exc);
+ src -=-1 * sizeof(unsigned int);
+ dst -= 1 * sizeof(unsigned int);
+ len += 0;
+ goto do3;
+ case 1:
+ /* a2 = ((unsigned int *) src)[0];
+ a3 = ((unsigned int *) src)[1]; */
+ ldw(s_space, 0, src, a2, cda_ldw_exc);
+ ldw(s_space, 4, src, a3, cda_ldw_exc);
+ src -=-2 * sizeof(unsigned int);
+ dst -= 0 * sizeof(unsigned int);
+ len -= 1;
+ if (len == 0)
+ goto do0;
+ goto do4; /* No-op. */
+ }
+
+ do
+ {
+ /* prefetch_src((const void *)(src + 4 * sizeof(unsigned int))); */
+do4:
+ /* a0 = ((unsigned int *) src)[0]; */
+ ldw(s_space, 0, src, a0, cda_ldw_exc);
+ /* ((unsigned int *) dst)[0] = MERGE (a2, sh_1, a3, sh_2); */
+ stw(d_space, MERGE (a2, sh_1, a3, sh_2), 0, dst, cda_stw_exc);
+do3:
+ /* a1 = ((unsigned int *) src)[1]; */
+ ldw(s_space, 4, src, a1, cda_ldw_exc);
+ /* ((unsigned int *) dst)[1] = MERGE (a3, sh_1, a0, sh_2); */
+ stw(d_space, MERGE (a3, sh_1, a0, sh_2), 4, dst, cda_stw_exc);
+do2:
+ /* a2 = ((unsigned int *) src)[2]; */
+ ldw(s_space, 8, src, a2, cda_ldw_exc);
+ /* ((unsigned int *) dst)[2] = MERGE (a0, sh_1, a1, sh_2); */
+ stw(d_space, MERGE (a0, sh_1, a1, sh_2), 8, dst, cda_stw_exc);
+do1:
+ /* a3 = ((unsigned int *) src)[3]; */
+ ldw(s_space, 12, src, a3, cda_ldw_exc);
+ /* ((unsigned int *) dst)[3] = MERGE (a1, sh_1, a2, sh_2); */
+ stw(d_space, MERGE (a1, sh_1, a2, sh_2), 12, dst, cda_stw_exc);
+
+ src += 4 * sizeof(unsigned int);
+ dst += 4 * sizeof(unsigned int);
+ len -= 4;
+ }
+ while (len != 0);
+
+do0:
+ /* ((unsigned int *) dst)[0] = MERGE (a2, sh_1, a3, sh_2); */
+ stw(d_space, MERGE (a2, sh_1, a3, sh_2), 0, dst, cda_stw_exc);
+
+ preserve_branch(handle_load_error);
+ preserve_branch(handle_store_error);
+
+ return 0;
+
+handle_load_error:
+ __asm__ __volatile__ ("cda_ldw_exc:\n");
+ d = &__get_cpu_var(exception_data);
+ DPRINTF("cda_ldw_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
+ o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
+ return o_len * 4 - d->fault_addr + o_src;
+
+handle_store_error:
+ __asm__ __volatile__ ("cda_stw_exc:\n");
+ d = &__get_cpu_var(exception_data);
+ DPRINTF("cda_stw_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
+ o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
+ return o_len * 4 - d->fault_addr + o_dst;
+}
+
+
+/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
+unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
+{
+ register unsigned long src, dst, t1, t2, t3;
+ register unsigned char *pcs, *pcd;
+ register unsigned int *pws, *pwd;
+ register double *pds, *pdd;
+ unsigned long ret = 0;
+ unsigned long o_dst, o_src, o_len;
+ struct exception_data *d;
+
+ src = (unsigned long)srcp;
+ dst = (unsigned long)dstp;
+ pcs = (unsigned char *)srcp;
+ pcd = (unsigned char *)dstp;
+
+ o_dst = dst; o_src = src; o_len = len;
+
+ /* prefetch_src((const void *)srcp); */
+
+ if (len < THRESHOLD)
+ goto byte_copy;
+
+ /* Check alignment */
+ t1 = (src ^ dst);
+ if (unlikely(t1 & (sizeof(double)-1)))
+ goto unaligned_copy;
+
+ /* src and dst have same alignment. */
+
+ /* Copy bytes till we are double-aligned. */
+ t2 = src & (sizeof(double) - 1);
+ if (unlikely(t2 != 0)) {
+ t2 = sizeof(double) - t2;
+ while (t2 && len) {
+ /* *pcd++ = *pcs++; */
+ ldbma(s_space, pcs, t3, pmc_load_exc);
+ len--;
+ stbma(d_space, t3, pcd, pmc_store_exc);
+ t2--;
+ }
+ }
+
+ pds = (double *)pcs;
+ pdd = (double *)pcd;
+
+ /* Copy 8 doubles at a time */
+ while (len >= 8*sizeof(double)) {
+ register double r1, r2, r3, r4, r5, r6, r7, r8;
+ /* prefetch_src((char *)pds + L1_CACHE_BYTES); */
+ flddma(s_space, pds, r1, pmc_load_exc);
+ flddma(s_space, pds, r2, pmc_load_exc);
+ flddma(s_space, pds, r3, pmc_load_exc);
+ flddma(s_space, pds, r4, pmc_load_exc);
+ fstdma(d_space, r1, pdd, pmc_store_exc);
+ fstdma(d_space, r2, pdd, pmc_store_exc);
+ fstdma(d_space, r3, pdd, pmc_store_exc);
+ fstdma(d_space, r4, pdd, pmc_store_exc);
+
+#if 0
+ if (L1_CACHE_BYTES <= 32)
+ prefetch_src((char *)pds + L1_CACHE_BYTES);
+#endif
+ flddma(s_space, pds, r5, pmc_load_exc);
+ flddma(s_space, pds, r6, pmc_load_exc);
+ flddma(s_space, pds, r7, pmc_load_exc);
+ flddma(s_space, pds, r8, pmc_load_exc);
+ fstdma(d_space, r5, pdd, pmc_store_exc);
+ fstdma(d_space, r6, pdd, pmc_store_exc);
+ fstdma(d_space, r7, pdd, pmc_store_exc);
+ fstdma(d_space, r8, pdd, pmc_store_exc);
+ len -= 8*sizeof(double);
+ }
+
+ pws = (unsigned int *)pds;
+ pwd = (unsigned int *)pdd;
+
+word_copy:
+ while (len >= 8*sizeof(unsigned int)) {
+ register unsigned int r1,r2,r3,r4,r5,r6,r7,r8;
+ /* prefetch_src((char *)pws + L1_CACHE_BYTES); */
+ ldwma(s_space, pws, r1, pmc_load_exc);
+ ldwma(s_space, pws, r2, pmc_load_exc);
+ ldwma(s_space, pws, r3, pmc_load_exc);
+ ldwma(s_space, pws, r4, pmc_load_exc);
+ stwma(d_space, r1, pwd, pmc_store_exc);
+ stwma(d_space, r2, pwd, pmc_store_exc);
+ stwma(d_space, r3, pwd, pmc_store_exc);
+ stwma(d_space, r4, pwd, pmc_store_exc);
+
+ ldwma(s_space, pws, r5, pmc_load_exc);
+ ldwma(s_space, pws, r6, pmc_load_exc);
+ ldwma(s_space, pws, r7, pmc_load_exc);
+ ldwma(s_space, pws, r8, pmc_load_exc);
+ stwma(d_space, r5, pwd, pmc_store_exc);
+ stwma(d_space, r6, pwd, pmc_store_exc);
+ stwma(d_space, r7, pwd, pmc_store_exc);
+ stwma(d_space, r8, pwd, pmc_store_exc);
+ len -= 8*sizeof(unsigned int);
+ }
+
+ while (len >= 4*sizeof(unsigned int)) {
+ register unsigned int r1,r2,r3,r4;
+ ldwma(s_space, pws, r1, pmc_load_exc);
+ ldwma(s_space, pws, r2, pmc_load_exc);
+ ldwma(s_space, pws, r3, pmc_load_exc);
+ ldwma(s_space, pws, r4, pmc_load_exc);
+ stwma(d_space, r1, pwd, pmc_store_exc);
+ stwma(d_space, r2, pwd, pmc_store_exc);
+ stwma(d_space, r3, pwd, pmc_store_exc);
+ stwma(d_space, r4, pwd, pmc_store_exc);
+ len -= 4*sizeof(unsigned int);
+ }
+
+ pcs = (unsigned char *)pws;
+ pcd = (unsigned char *)pwd;
+
+byte_copy:
+ while (len) {
+ /* *pcd++ = *pcs++; */
+ ldbma(s_space, pcs, t3, pmc_load_exc);
+ stbma(d_space, t3, pcd, pmc_store_exc);
+ len--;
+ }
+
+ return 0;
+
+unaligned_copy:
+ /* possibly we are aligned on a word, but not on a double... */
+ if (likely(t1 & (sizeof(unsigned int)-1)) == 0) {
+ t2 = src & (sizeof(unsigned int) - 1);
+
+ if (unlikely(t2 != 0)) {
+ t2 = sizeof(unsigned int) - t2;
+ while (t2) {
+ /* *pcd++ = *pcs++; */
+ ldbma(s_space, pcs, t3, pmc_load_exc);
+ stbma(d_space, t3, pcd, pmc_store_exc);
+ len--;
+ t2--;
+ }
+ }
+
+ pws = (unsigned int *)pcs;
+ pwd = (unsigned int *)pcd;
+ goto word_copy;
+ }
+
+ /* Align the destination. */
+ if (unlikely((dst & (sizeof(unsigned int) - 1)) != 0)) {
+ t2 = sizeof(unsigned int) - (dst & (sizeof(unsigned int) - 1));
+ while (t2) {
+ /* *pcd++ = *pcs++; */
+ ldbma(s_space, pcs, t3, pmc_load_exc);
+ stbma(d_space, t3, pcd, pmc_store_exc);
+ len--;
+ t2--;
+ }
+ dst = (unsigned long)pcd;
+ src = (unsigned long)pcs;
+ }
+
+ ret = copy_dstaligned(dst, src, len / sizeof(unsigned int),
+ o_dst, o_src, o_len);
+ if (ret)
+ return ret;
+
+ pcs += (len & -sizeof(unsigned int));
+ pcd += (len & -sizeof(unsigned int));
+ len %= sizeof(unsigned int);
+
+ preserve_branch(handle_load_error);
+ preserve_branch(handle_store_error);
+
+ goto byte_copy;
+
+handle_load_error:
+ __asm__ __volatile__ ("pmc_load_exc:\n");
+ d = &__get_cpu_var(exception_data);
+ DPRINTF("pmc_load_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
+ o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
+ return o_len - d->fault_addr + o_src;
+
+handle_store_error:
+ __asm__ __volatile__ ("pmc_store_exc:\n");
+ d = &__get_cpu_var(exception_data);
+ DPRINTF("pmc_store_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
+ o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
+ return o_len - d->fault_addr + o_dst;
+}
+
+#ifdef __KERNEL__
+unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len)
+{
+ mtsp(get_kernel_space(), 1);
+ mtsp(get_user_space(), 2);
+ return pa_memcpy((void __force *)dst, src, len);
+}
+
+unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len)
+{
+ mtsp(get_user_space(), 1);
+ mtsp(get_kernel_space(), 2);
+ return pa_memcpy(dst, (void __force *)src, len);
+}
+
+unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len)
+{
+ mtsp(get_user_space(), 1);
+ mtsp(get_user_space(), 2);
+ return pa_memcpy((void __force *)dst, (void __force *)src, len);
+}
+
+
+void * memcpy(void * dst,const void *src, size_t count)
+{
+ mtsp(get_kernel_space(), 1);
+ mtsp(get_kernel_space(), 2);
+ pa_memcpy(dst, src, count);
+ return dst;
+}
+
+EXPORT_SYMBOL(copy_to_user);
+EXPORT_SYMBOL(copy_from_user);
+EXPORT_SYMBOL(copy_in_user);
+EXPORT_SYMBOL(memcpy);
+#endif
diff --git a/arch/parisc/lib/memset.c b/arch/parisc/lib/memset.c
new file mode 100644
index 000000000000..1d7929bd7642
--- /dev/null
+++ b/arch/parisc/lib/memset.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Slight modifications for pa-risc linux - Paul Bame <bame@debian.org> */
+
+#include <linux/types.h>
+#include <asm/string.h>
+
+#define OPSIZ (BITS_PER_LONG/8)
+typedef unsigned long op_t;
+
+void *
+memset (void *dstpp, int sc, size_t len)
+{
+ unsigned int c = sc;
+ long int dstp = (long int) dstpp;
+
+ if (len >= 8)
+ {
+ size_t xlen;
+ op_t cccc;
+
+ cccc = (unsigned char) c;
+ cccc |= cccc << 8;
+ cccc |= cccc << 16;
+ if (OPSIZ > 4)
+ /* Do the shift in two steps to avoid warning if long has 32 bits. */
+ cccc |= (cccc << 16) << 16;
+
+ /* There are at least some bytes to set.
+ No need to test for LEN == 0 in this alignment loop. */
+ while (dstp % OPSIZ != 0)
+ {
+ ((unsigned char *) dstp)[0] = c;
+ dstp += 1;
+ len -= 1;
+ }
+
+ /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */
+ xlen = len / (OPSIZ * 8);
+ while (xlen > 0)
+ {
+ ((op_t *) dstp)[0] = cccc;
+ ((op_t *) dstp)[1] = cccc;
+ ((op_t *) dstp)[2] = cccc;
+ ((op_t *) dstp)[3] = cccc;
+ ((op_t *) dstp)[4] = cccc;
+ ((op_t *) dstp)[5] = cccc;
+ ((op_t *) dstp)[6] = cccc;
+ ((op_t *) dstp)[7] = cccc;
+ dstp += 8 * OPSIZ;
+ xlen -= 1;
+ }
+ len %= OPSIZ * 8;
+
+ /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */
+ xlen = len / OPSIZ;
+ while (xlen > 0)
+ {
+ ((op_t *) dstp)[0] = cccc;
+ dstp += OPSIZ;
+ xlen -= 1;
+ }
+ len %= OPSIZ;
+ }
+
+ /* Write the last few bytes. */
+ while (len > 0)
+ {
+ ((unsigned char *) dstp)[0] = c;
+ dstp += 1;
+ len -= 1;
+ }
+
+ return dstpp;
+}
diff --git a/arch/parisc/math-emu/Makefile b/arch/parisc/math-emu/Makefile
new file mode 100644
index 000000000000..affd4c80e3b7
--- /dev/null
+++ b/arch/parisc/math-emu/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the linux/parisc floating point code
+#
+
+# See arch/parisc/math-emu/README
+CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \
+ -Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \
+ -Wno-implicit-int
+
+obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \
+ dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \
+ sfadd.o dfsub.o sfsub.o fcnvfxt.o fcnvff.o fcnvxf.o \
+ fcnvfx.o fcnvuf.o fcnvfu.o fcnvfut.o dfdiv.o sfdiv.o \
+ dfrem.o sfrem.o dfcmp.o sfcmp.o
+
+# Math emulation code beyond the FRND is required for 712/80i and
+# other very old or stripped-down PA-RISC CPUs -- not currently supported
+
+obj-$(CONFIG_MATH_EMULATION) += unimplemented-math-emulation.o
diff --git a/arch/parisc/math-emu/README b/arch/parisc/math-emu/README
new file mode 100644
index 000000000000..1a0124ef02f2
--- /dev/null
+++ b/arch/parisc/math-emu/README
@@ -0,0 +1,11 @@
+All files except driver.c are snapshots from the HP-UX kernel. They've
+been modified as little as possible. Even though they don't fit the
+Linux coding style, please leave them in their funny format just in case
+someone in the future, with access to HP-UX source code, is generous
+enough to update our copies with later changes from HP-UX -- it'll
+make their 'diff' job easier if our code is relatively unmodified.
+
+Required Disclaimer: Hewlett-Packard makes no implied or expressed
+warranties about this code nor any promises to maintain or test it
+in any way. This copy of this snapshot is no longer the property
+of Hewlett-Packard.
diff --git a/arch/parisc/math-emu/cnv_float.h b/arch/parisc/math-emu/cnv_float.h
new file mode 100644
index 000000000000..9071e093164a
--- /dev/null
+++ b/arch/parisc/math-emu/cnv_float.h
@@ -0,0 +1,377 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef __NO_PA_HDRS
+ PA header file -- do not include this header file for non-PA builds.
+#endif
+
+/*
+ * Some more constants
+ */
+#define SGL_FX_MAX_EXP 30
+#define DBL_FX_MAX_EXP 62
+#define QUAD_FX_MAX_EXP 126
+
+#define Dintp1(object) (object)
+#define Dintp2(object) (object)
+
+#define Duintp1(object) (object)
+#define Duintp2(object) (object)
+
+#define Qintp0(object) (object)
+#define Qintp1(object) (object)
+#define Qintp2(object) (object)
+#define Qintp3(object) (object)
+
+
+/*
+ * These macros will be used specifically by the convert instructions.
+ *
+ *
+ * Single format macros
+ */
+
+#define Sgl_to_dbl_exponent(src_exponent,dest) \
+ Deposit_dexponent(dest,src_exponent+(DBL_BIAS-SGL_BIAS))
+
+#define Sgl_to_dbl_mantissa(src_mantissa,destA,destB) \
+ Deposit_dmantissap1(destA,src_mantissa>>3); \
+ Dmantissap2(destB) = src_mantissa << 29
+
+#define Sgl_isinexact_to_fix(sgl_value,exponent) \
+ ((exponent < (SGL_P - 1)) ? \
+ (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE)
+
+#define Int_isinexact_to_sgl(int_value) (int_value << 33 - SGL_EXP_LENGTH)
+
+#define Sgl_roundnearest_from_int(int_value,sgl_value) \
+ if (int_value & 1<<(SGL_EXP_LENGTH - 2)) /* round bit */ \
+ if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value)) \
+ Sall(sgl_value)++
+
+#define Dint_isinexact_to_sgl(dint_valueA,dint_valueB) \
+ ((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB))
+
+#define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value) \
+ if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2)) \
+ if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) || \
+ Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
+
+#define Dint_isinexact_to_dbl(dint_value) \
+ (Dintp2(dint_value) << 33 - DBL_EXP_LENGTH)
+
+#define Dbl_roundnearest_from_dint(dint_opndB,dbl_opndA,dbl_opndB) \
+ if (Dintp2(dint_opndB) & 1<<(DBL_EXP_LENGTH - 2)) \
+ if ((Dintp2(dint_opndB) << 34 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \
+ if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
+
+#define Sgl_isone_roundbit(sgl_value,exponent) \
+ ((Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) >> 31)
+
+#define Sgl_isone_stickybit(sgl_value,exponent) \
+ (exponent < (SGL_P - 2) ? \
+ Sall(sgl_value) << (SGL_EXP_LENGTH + 2 + exponent) : FALSE)
+
+
+/*
+ * Double format macros
+ */
+
+#define Dbl_to_sgl_exponent(src_exponent,dest) \
+ dest = src_exponent + (SGL_BIAS - DBL_BIAS)
+
+#define Dbl_to_sgl_mantissa(srcA,srcB,dest,inexact,guard,sticky,odd) \
+ Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \
+ guard = Dbit3p2(srcB); \
+ sticky = Dallp2(srcB)<<4; \
+ inexact = guard | sticky; \
+ odd = Dbit2p2(srcB)
+
+#define Dbl_to_sgl_denormalized(srcA,srcB,exp,dest,inexact,guard,sticky,odd,tiny) \
+ Deposit_dexponent(srcA,1); \
+ tiny = TRUE; \
+ if (exp >= -2) { \
+ if (exp == 0) { \
+ inexact = Dallp2(srcB) << 3; \
+ guard = inexact >> 31; \
+ sticky = inexact << 1; \
+ Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \
+ odd = dest << 31; \
+ if (inexact) { \
+ switch(Rounding_mode()) { \
+ case ROUNDPLUS: \
+ if (Dbl_iszero_sign(srcA)) { \
+ dest++; \
+ if (Sgl_isone_hidden(dest)) \
+ tiny = FALSE; \
+ dest--; \
+ } \
+ break; \
+ case ROUNDMINUS: \
+ if (Dbl_isone_sign(srcA)) { \
+ dest++; \
+ if (Sgl_isone_hidden(dest)) \
+ tiny = FALSE; \
+ dest--; \
+ } \
+ break; \
+ case ROUNDNEAREST: \
+ if (guard && (sticky || odd)) { \
+ dest++; \
+ if (Sgl_isone_hidden(dest)) \
+ tiny = FALSE; \
+ dest--; \
+ } \
+ break; \
+ } \
+ } \
+ /* shift right by one to get correct result */ \
+ guard = odd; \
+ sticky = inexact; \
+ inexact |= guard; \
+ dest >>= 1; \
+ Deposit_dsign(srcA,0); \
+ Shiftdouble(Dallp1(srcA),Dallp2(srcB),30,dest); \
+ odd = dest << 31; \
+ } \
+ else { \
+ inexact = Dallp2(srcB) << (2 + exp); \
+ guard = inexact >> 31; \
+ sticky = inexact << 1; \
+ Deposit_dsign(srcA,0); \
+ if (exp == -2) dest = Dallp1(srcA); \
+ else Variable_shift_double(Dallp1(srcA),Dallp2(srcB),30-exp,dest); \
+ odd = dest << 31; \
+ } \
+ } \
+ else { \
+ Deposit_dsign(srcA,0); \
+ if (exp > (1 - SGL_P)) { \
+ dest = Dallp1(srcA) >> (- 2 - exp); \
+ inexact = Dallp1(srcA) << (34 + exp); \
+ guard = inexact >> 31; \
+ sticky = (inexact << 1) | Dallp2(srcB); \
+ inexact |= Dallp2(srcB); \
+ odd = dest << 31; \
+ } \
+ else { \
+ dest = 0; \
+ inexact = Dallp1(srcA) | Dallp2(srcB); \
+ if (exp == (1 - SGL_P)) { \
+ guard = Dhidden(srcA); \
+ sticky = Dmantissap1(srcA) | Dallp2(srcB); \
+ } \
+ else { \
+ guard = 0; \
+ sticky = inexact; \
+ } \
+ odd = 0; \
+ } \
+ } \
+ exp = 0
+
+#define Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) \
+ (exponent < (DBL_P-33) ? \
+ Dallp2(dbl_valueB) || Dallp1(dbl_valueA) << (DBL_EXP_LENGTH+1+exponent) : \
+ (exponent < (DBL_P-1) ? Dallp2(dbl_valueB) << (exponent + (33-DBL_P)) : \
+ FALSE))
+
+#define Dbl_isoverflow_to_int(exponent,dbl_valueA,dbl_valueB) \
+ ((exponent > SGL_FX_MAX_EXP + 1) || Dsign(dbl_valueA)==0 || \
+ Dmantissap1(dbl_valueA)!=0 || (Dallp2(dbl_valueB)>>21)!=0 )
+
+#define Dbl_isone_roundbit(dbl_valueA,dbl_valueB,exponent) \
+ ((exponent < (DBL_P - 33) ? \
+ Dallp1(dbl_valueA) >> ((30 - DBL_EXP_LENGTH) - exponent) : \
+ Dallp2(dbl_valueB) >> ((DBL_P - 2) - exponent)) & 1)
+
+#define Dbl_isone_stickybit(dbl_valueA,dbl_valueB,exponent) \
+ (exponent < (DBL_P-34) ? \
+ (Dallp2(dbl_valueB) || Dallp1(dbl_valueA)<<(DBL_EXP_LENGTH+2+exponent)) : \
+ (exponent<(DBL_P-2) ? (Dallp2(dbl_valueB) << (exponent + (34-DBL_P))) : \
+ FALSE))
+
+
+/* Int macros */
+
+#define Int_from_sgl_mantissa(sgl_value,exponent) \
+ Sall(sgl_value) = \
+ (unsigned)(Sall(sgl_value) << SGL_EXP_LENGTH)>>(31 - exponent)
+
+#define Int_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),22,Dallp1(dbl_valueA)); \
+ if (exponent < 31) Dallp1(dbl_valueA) >>= 30 - exponent; \
+ else Dallp1(dbl_valueA) <<= 1
+
+#define Int_negate(int_value) int_value = -int_value
+
+
+/* Dint macros */
+
+#define Dint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \
+ {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \
+ if (exponent <= 31) { \
+ Dintp1(dresultA) = 0; \
+ Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
+ } \
+ else { \
+ Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \
+ Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \
+ }}
+
+
+#define Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
+ {if (exponent < 32) { \
+ Dintp1(destA) = 0; \
+ if (exponent <= 20) \
+ Dintp2(destB) = Dallp1(dbl_valueA) >> 20-exponent; \
+ else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
+ 52-exponent,Dintp2(destB)); \
+ } \
+ else { \
+ if (exponent <= 52) { \
+ Dintp1(destA) = Dallp1(dbl_valueA) >> 52-exponent; \
+ if (exponent == 52) Dintp2(destB) = Dallp2(dbl_valueB); \
+ else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
+ 52-exponent,Dintp2(destB)); \
+ } \
+ else { \
+ Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
+ 84-exponent,Dintp1(destA)); \
+ Dintp2(destB) = Dallp2(dbl_valueB) << exponent-52; \
+ } \
+ }}
+
+#define Dint_setzero(dresultA,dresultB) \
+ Dintp1(dresultA) = 0; \
+ Dintp2(dresultB) = 0
+
+#define Dint_setone_sign(dresultA,dresultB) \
+ Dintp1(dresultA) = ~Dintp1(dresultA); \
+ if ((Dintp2(dresultB) = -Dintp2(dresultB)) == 0) Dintp1(dresultA)++
+
+#define Dint_set_minint(dresultA,dresultB) \
+ Dintp1(dresultA) = (unsigned int)1<<31; \
+ Dintp2(dresultB) = 0
+
+#define Dint_isone_lowp2(dresultB) (Dintp2(dresultB) & 01)
+
+#define Dint_increment(dresultA,dresultB) \
+ if ((++Dintp2(dresultB))==0) Dintp1(dresultA)++
+
+#define Dint_decrement(dresultA,dresultB) \
+ if ((Dintp2(dresultB)--)==0) Dintp1(dresultA)--
+
+#define Dint_negate(dresultA,dresultB) \
+ Dintp1(dresultA) = ~Dintp1(dresultA); \
+ if ((Dintp2(dresultB) = -Dintp2(dresultB))==0) Dintp1(dresultA)++
+
+#define Dint_copyfromptr(src,destA,destB) \
+ Dintp1(destA) = src->wd0; \
+ Dintp2(destB) = src->wd1
+#define Dint_copytoptr(srcA,srcB,dest) \
+ dest->wd0 = Dintp1(srcA); \
+ dest->wd1 = Dintp2(srcB)
+
+
+/* other macros */
+
+#define Find_ms_one_bit(value, position) \
+ { \
+ int var; \
+ for (var=8; var >=1; var >>= 1) { \
+ if (value >> 32 - position) \
+ position -= var; \
+ else position += var; \
+ } \
+ if ((value >> 32 - position) == 0) \
+ position--; \
+ else position -= 2; \
+ }
+
+
+/*
+ * Unsigned int macros
+ */
+#define Duint_copyfromptr(src,destA,destB) \
+ Dint_copyfromptr(src,destA,destB)
+#define Duint_copytoptr(srcA,srcB,dest) \
+ Dint_copytoptr(srcA,srcB,dest)
+
+#define Suint_isinexact_to_sgl(int_value) \
+ (int_value << 32 - SGL_EXP_LENGTH)
+
+#define Sgl_roundnearest_from_suint(suint_value,sgl_value) \
+ if (suint_value & 1<<(SGL_EXP_LENGTH - 1)) /* round bit */ \
+ if ((suint_value << 33 - SGL_EXP_LENGTH) || Slow(sgl_value)) \
+ Sall(sgl_value)++
+
+#define Duint_isinexact_to_sgl(duint_valueA,duint_valueB) \
+ ((Duintp1(duint_valueA) << 32 - SGL_EXP_LENGTH) || Duintp2(duint_valueB))
+
+#define Sgl_roundnearest_from_duint(duint_valueA,duint_valueB,sgl_value) \
+ if (Duintp1(duint_valueA) & 1<<(SGL_EXP_LENGTH - 1)) \
+ if ((Duintp1(duint_valueA) << 33 - SGL_EXP_LENGTH) || \
+ Duintp2(duint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
+
+#define Duint_isinexact_to_dbl(duint_value) \
+ (Duintp2(duint_value) << 32 - DBL_EXP_LENGTH)
+
+#define Dbl_roundnearest_from_duint(duint_opndB,dbl_opndA,dbl_opndB) \
+ if (Duintp2(duint_opndB) & 1<<(DBL_EXP_LENGTH - 1)) \
+ if ((Duintp2(duint_opndB) << 33 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \
+ if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
+
+#define Suint_from_sgl_mantissa(src,exponent,result) \
+ Sall(result) = (unsigned)(Sall(src) << SGL_EXP_LENGTH)>>(31 - exponent)
+
+#define Sgl_isinexact_to_unsigned(sgl_value,exponent) \
+ Sgl_isinexact_to_fix(sgl_value,exponent)
+
+#define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \
+ {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \
+ if (exponent <= 31) { \
+ Dintp1(dresultA) = 0; \
+ Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
+ } \
+ else { \
+ Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \
+ Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \
+ } \
+ Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \
+ }
+
+#define Duint_setzero(dresultA,dresultB) \
+ Dint_setzero(dresultA,dresultB)
+
+#define Duint_increment(dresultA,dresultB) Dint_increment(dresultA,dresultB)
+
+#define Duint_isone_lowp2(dresultB) Dint_isone_lowp2(dresultB)
+
+#define Suint_from_dbl_mantissa(srcA,srcB,exponent,dest) \
+ Shiftdouble(Dallp1(srcA),Dallp2(srcB),21,dest); \
+ dest = (unsigned)dest >> 31 - exponent
+
+#define Dbl_isinexact_to_unsigned(dbl_valueA,dbl_valueB,exponent) \
+ Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent)
+
+#define Duint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
+ Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB)
diff --git a/arch/parisc/math-emu/dbl_float.h b/arch/parisc/math-emu/dbl_float.h
new file mode 100644
index 000000000000..1570e2e0a327
--- /dev/null
+++ b/arch/parisc/math-emu/dbl_float.h
@@ -0,0 +1,847 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifdef __NO_PA_HDRS
+ PA header file -- do not include this header file for non-PA builds.
+#endif
+
+/* 32-bit word grabing functions */
+#define Dbl_firstword(value) Dallp1(value)
+#define Dbl_secondword(value) Dallp2(value)
+#define Dbl_thirdword(value) dummy_location
+#define Dbl_fourthword(value) dummy_location
+
+#define Dbl_sign(object) Dsign(object)
+#define Dbl_exponent(object) Dexponent(object)
+#define Dbl_signexponent(object) Dsignexponent(object)
+#define Dbl_mantissap1(object) Dmantissap1(object)
+#define Dbl_mantissap2(object) Dmantissap2(object)
+#define Dbl_exponentmantissap1(object) Dexponentmantissap1(object)
+#define Dbl_allp1(object) Dallp1(object)
+#define Dbl_allp2(object) Dallp2(object)
+
+/* dbl_and_signs ands the sign bits of each argument and puts the result
+ * into the first argument. dbl_or_signs ors those same sign bits */
+#define Dbl_and_signs( src1dst, src2) \
+ Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst)
+#define Dbl_or_signs( src1dst, src2) \
+ Dallp1(src1dst) = (Dallp1(src2)&((unsigned int)1<<31)) | Dallp1(src1dst)
+
+/* The hidden bit is always the low bit of the exponent */
+#define Dbl_clear_exponent_set_hidden(srcdst) Deposit_dexponent(srcdst,1)
+#define Dbl_clear_signexponent_set_hidden(srcdst) \
+ Deposit_dsignexponent(srcdst,1)
+#define Dbl_clear_sign(srcdst) Dallp1(srcdst) &= ~((unsigned int)1<<31)
+#define Dbl_clear_signexponent(srcdst) \
+ Dallp1(srcdst) &= Dmantissap1((unsigned int)-1)
+
+/* Exponent field for doubles has already been cleared and may be
+ * included in the shift. Here we need to generate two double width
+ * variable shifts. The insignificant bits can be ignored.
+ * MTSAR f(varamount)
+ * VSHD srcdst.high,srcdst.low => srcdst.low
+ * VSHD 0,srcdst.high => srcdst.high
+ * This is very difficult to model with C expressions since the shift amount
+ * could exceed 32. */
+/* varamount must be less than 64 */
+#define Dbl_rightshift(srcdstA, srcdstB, varamount) \
+ {if((varamount) >= 32) { \
+ Dallp2(srcdstB) = Dallp1(srcdstA) >> (varamount-32); \
+ Dallp1(srcdstA)=0; \
+ } \
+ else if(varamount > 0) { \
+ Variable_shift_double(Dallp1(srcdstA), Dallp2(srcdstB), \
+ (varamount), Dallp2(srcdstB)); \
+ Dallp1(srcdstA) >>= varamount; \
+ } }
+/* varamount must be less than 64 */
+#define Dbl_rightshift_exponentmantissa(srcdstA, srcdstB, varamount) \
+ {if((varamount) >= 32) { \
+ Dallp2(srcdstB) = Dexponentmantissap1(srcdstA) >> (varamount-32); \
+ Dallp1(srcdstA) &= ((unsigned int)1<<31); /* clear expmant field */ \
+ } \
+ else if(varamount > 0) { \
+ Variable_shift_double(Dexponentmantissap1(srcdstA), Dallp2(srcdstB), \
+ (varamount), Dallp2(srcdstB)); \
+ Deposit_dexponentmantissap1(srcdstA, \
+ (Dexponentmantissap1(srcdstA)>>varamount)); \
+ } }
+/* varamount must be less than 64 */
+#define Dbl_leftshift(srcdstA, srcdstB, varamount) \
+ {if((varamount) >= 32) { \
+ Dallp1(srcdstA) = Dallp2(srcdstB) << (varamount-32); \
+ Dallp2(srcdstB)=0; \
+ } \
+ else { \
+ if ((varamount) > 0) { \
+ Dallp1(srcdstA) = (Dallp1(srcdstA) << (varamount)) | \
+ (Dallp2(srcdstB) >> (32-(varamount))); \
+ Dallp2(srcdstB) <<= varamount; \
+ } \
+ } }
+#define Dbl_leftshiftby1_withextent(lefta,leftb,right,resulta,resultb) \
+ Shiftdouble(Dallp1(lefta), Dallp2(leftb), 31, Dallp1(resulta)); \
+ Shiftdouble(Dallp2(leftb), Extall(right), 31, Dallp2(resultb))
+
+#define Dbl_rightshiftby1_withextent(leftb,right,dst) \
+ Extall(dst) = (Dallp2(leftb) << 31) | ((unsigned int)Extall(right) >> 1) | \
+ Extlow(right)
+
+#define Dbl_arithrightshiftby1(srcdstA,srcdstB) \
+ Shiftdouble(Dallp1(srcdstA),Dallp2(srcdstB),1,Dallp2(srcdstB));\
+ Dallp1(srcdstA) = (int)Dallp1(srcdstA) >> 1
+
+/* Sign extend the sign bit with an integer destination */
+#define Dbl_signextendedsign(value) Dsignedsign(value)
+
+#define Dbl_isone_hidden(dbl_value) (Is_dhidden(dbl_value)!=0)
+/* Singles and doubles may include the sign and exponent fields. The
+ * hidden bit and the hidden overflow must be included. */
+#define Dbl_increment(dbl_valueA,dbl_valueB) \
+ if( (Dallp2(dbl_valueB) += 1) == 0 ) Dallp1(dbl_valueA) += 1
+#define Dbl_increment_mantissa(dbl_valueA,dbl_valueB) \
+ if( (Dmantissap2(dbl_valueB) += 1) == 0 ) \
+ Deposit_dmantissap1(dbl_valueA,dbl_valueA+1)
+#define Dbl_decrement(dbl_valueA,dbl_valueB) \
+ if( Dallp2(dbl_valueB) == 0 ) Dallp1(dbl_valueA) -= 1; \
+ Dallp2(dbl_valueB) -= 1
+
+#define Dbl_isone_sign(dbl_value) (Is_dsign(dbl_value)!=0)
+#define Dbl_isone_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)!=0)
+#define Dbl_isone_lowmantissap1(dbl_valueA) (Is_dlowp1(dbl_valueA)!=0)
+#define Dbl_isone_lowmantissap2(dbl_valueB) (Is_dlowp2(dbl_valueB)!=0)
+#define Dbl_isone_signaling(dbl_value) (Is_dsignaling(dbl_value)!=0)
+#define Dbl_is_signalingnan(dbl_value) (Dsignalingnan(dbl_value)==0xfff)
+#define Dbl_isnotzero(dbl_valueA,dbl_valueB) \
+ (Dallp1(dbl_valueA) || Dallp2(dbl_valueB))
+#define Dbl_isnotzero_hiddenhigh7mantissa(dbl_value) \
+ (Dhiddenhigh7mantissa(dbl_value)!=0)
+#define Dbl_isnotzero_exponent(dbl_value) (Dexponent(dbl_value)!=0)
+#define Dbl_isnotzero_mantissa(dbl_valueA,dbl_valueB) \
+ (Dmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB))
+#define Dbl_isnotzero_mantissap1(dbl_valueA) (Dmantissap1(dbl_valueA)!=0)
+#define Dbl_isnotzero_mantissap2(dbl_valueB) (Dmantissap2(dbl_valueB)!=0)
+#define Dbl_isnotzero_exponentmantissa(dbl_valueA,dbl_valueB) \
+ (Dexponentmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB))
+#define Dbl_isnotzero_low4p2(dbl_value) (Dlow4p2(dbl_value)!=0)
+#define Dbl_iszero(dbl_valueA,dbl_valueB) (Dallp1(dbl_valueA)==0 && \
+ Dallp2(dbl_valueB)==0)
+#define Dbl_iszero_allp1(dbl_value) (Dallp1(dbl_value)==0)
+#define Dbl_iszero_allp2(dbl_value) (Dallp2(dbl_value)==0)
+#define Dbl_iszero_hidden(dbl_value) (Is_dhidden(dbl_value)==0)
+#define Dbl_iszero_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)==0)
+#define Dbl_iszero_hiddenhigh3mantissa(dbl_value) \
+ (Dhiddenhigh3mantissa(dbl_value)==0)
+#define Dbl_iszero_hiddenhigh7mantissa(dbl_value) \
+ (Dhiddenhigh7mantissa(dbl_value)==0)
+#define Dbl_iszero_sign(dbl_value) (Is_dsign(dbl_value)==0)
+#define Dbl_iszero_exponent(dbl_value) (Dexponent(dbl_value)==0)
+#define Dbl_iszero_mantissa(dbl_valueA,dbl_valueB) \
+ (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
+#define Dbl_iszero_exponentmantissa(dbl_valueA,dbl_valueB) \
+ (Dexponentmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
+#define Dbl_isinfinity_exponent(dbl_value) \
+ (Dexponent(dbl_value)==DBL_INFINITY_EXPONENT)
+#define Dbl_isnotinfinity_exponent(dbl_value) \
+ (Dexponent(dbl_value)!=DBL_INFINITY_EXPONENT)
+#define Dbl_isinfinity(dbl_valueA,dbl_valueB) \
+ (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \
+ Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
+#define Dbl_isnan(dbl_valueA,dbl_valueB) \
+ (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \
+ (Dmantissap1(dbl_valueA)!=0 || Dmantissap2(dbl_valueB)!=0))
+#define Dbl_isnotnan(dbl_valueA,dbl_valueB) \
+ (Dexponent(dbl_valueA)!=DBL_INFINITY_EXPONENT || \
+ (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0))
+
+#define Dbl_islessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
+ (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \
+ (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
+ Dallp2(dbl_op1b) < Dallp2(dbl_op2b)))
+#define Dbl_isgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
+ (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \
+ (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
+ Dallp2(dbl_op1b) > Dallp2(dbl_op2b)))
+#define Dbl_isnotlessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
+ (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \
+ (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
+ Dallp2(dbl_op1b) >= Dallp2(dbl_op2b)))
+#define Dbl_isnotgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
+ (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \
+ (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
+ Dallp2(dbl_op1b) <= Dallp2(dbl_op2b)))
+#define Dbl_isequal(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
+ ((Dallp1(dbl_op1a) == Dallp1(dbl_op2a)) && \
+ (Dallp2(dbl_op1b) == Dallp2(dbl_op2b)))
+
+#define Dbl_leftshiftby8(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),24,Dallp1(dbl_valueA)); \
+ Dallp2(dbl_valueB) <<= 8
+#define Dbl_leftshiftby7(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),25,Dallp1(dbl_valueA)); \
+ Dallp2(dbl_valueB) <<= 7
+#define Dbl_leftshiftby4(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),28,Dallp1(dbl_valueA)); \
+ Dallp2(dbl_valueB) <<= 4
+#define Dbl_leftshiftby3(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),29,Dallp1(dbl_valueA)); \
+ Dallp2(dbl_valueB) <<= 3
+#define Dbl_leftshiftby2(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),30,Dallp1(dbl_valueA)); \
+ Dallp2(dbl_valueB) <<= 2
+#define Dbl_leftshiftby1(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),31,Dallp1(dbl_valueA)); \
+ Dallp2(dbl_valueB) <<= 1
+
+#define Dbl_rightshiftby8(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),8,Dallp2(dbl_valueB)); \
+ Dallp1(dbl_valueA) >>= 8
+#define Dbl_rightshiftby4(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),4,Dallp2(dbl_valueB)); \
+ Dallp1(dbl_valueA) >>= 4
+#define Dbl_rightshiftby2(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),2,Dallp2(dbl_valueB)); \
+ Dallp1(dbl_valueA) >>= 2
+#define Dbl_rightshiftby1(dbl_valueA,dbl_valueB) \
+ Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),1,Dallp2(dbl_valueB)); \
+ Dallp1(dbl_valueA) >>= 1
+
+/* This magnitude comparison uses the signless first words and
+ * the regular part2 words. The comparison is graphically:
+ *
+ * 1st greater? -------------
+ * |
+ * 1st less?-----------------+---------
+ * | |
+ * 2nd greater or equal----->| |
+ * False True
+ */
+#define Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \
+ ((signlessleft <= signlessright) && \
+ ( (signlessleft < signlessright) || (Dallp2(leftB)<Dallp2(rightB)) ))
+
+#define Dbl_copytoint_exponentmantissap1(src,dest) \
+ dest = Dexponentmantissap1(src)
+
+/* A quiet NaN has the high mantissa bit clear and at least on other (in this
+ * case the adjacent bit) bit set. */
+#define Dbl_set_quiet(dbl_value) Deposit_dhigh2mantissa(dbl_value,1)
+#define Dbl_set_exponent(dbl_value, exp) Deposit_dexponent(dbl_value,exp)
+
+#define Dbl_set_mantissa(desta,destb,valuea,valueb) \
+ Deposit_dmantissap1(desta,valuea); \
+ Dmantissap2(destb) = Dmantissap2(valueb)
+#define Dbl_set_mantissap1(desta,valuea) \
+ Deposit_dmantissap1(desta,valuea)
+#define Dbl_set_mantissap2(destb,valueb) \
+ Dmantissap2(destb) = Dmantissap2(valueb)
+
+#define Dbl_set_exponentmantissa(desta,destb,valuea,valueb) \
+ Deposit_dexponentmantissap1(desta,valuea); \
+ Dmantissap2(destb) = Dmantissap2(valueb)
+#define Dbl_set_exponentmantissap1(dest,value) \
+ Deposit_dexponentmantissap1(dest,value)
+
+#define Dbl_copyfromptr(src,desta,destb) \
+ Dallp1(desta) = src->wd0; \
+ Dallp2(destb) = src->wd1
+#define Dbl_copytoptr(srca,srcb,dest) \
+ dest->wd0 = Dallp1(srca); \
+ dest->wd1 = Dallp2(srcb)
+
+/* An infinity is represented with the max exponent and a zero mantissa */
+#define Dbl_setinfinity_exponent(dbl_value) \
+ Deposit_dexponent(dbl_value,DBL_INFINITY_EXPONENT)
+#define Dbl_setinfinity_exponentmantissa(dbl_valueA,dbl_valueB) \
+ Deposit_dexponentmantissap1(dbl_valueA, \
+ (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)))); \
+ Dmantissap2(dbl_valueB) = 0
+#define Dbl_setinfinitypositive(dbl_valueA,dbl_valueB) \
+ Dallp1(dbl_valueA) \
+ = (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
+ Dmantissap2(dbl_valueB) = 0
+#define Dbl_setinfinitynegative(dbl_valueA,dbl_valueB) \
+ Dallp1(dbl_valueA) = ((unsigned int)1<<31) | \
+ (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
+ Dmantissap2(dbl_valueB) = 0
+#define Dbl_setinfinity(dbl_valueA,dbl_valueB,sign) \
+ Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \
+ (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
+ Dmantissap2(dbl_valueB) = 0
+
+#define Dbl_sethigh4bits(dbl_value, extsign) Deposit_dhigh4p1(dbl_value,extsign)
+#define Dbl_set_sign(dbl_value,sign) Deposit_dsign(dbl_value,sign)
+#define Dbl_invert_sign(dbl_value) Deposit_dsign(dbl_value,~Dsign(dbl_value))
+#define Dbl_setone_sign(dbl_value) Deposit_dsign(dbl_value,1)
+#define Dbl_setone_lowmantissap2(dbl_value) Deposit_dlowp2(dbl_value,1)
+#define Dbl_setzero_sign(dbl_value) Dallp1(dbl_value) &= 0x7fffffff
+#define Dbl_setzero_exponent(dbl_value) \
+ Dallp1(dbl_value) &= 0x800fffff
+#define Dbl_setzero_mantissa(dbl_valueA,dbl_valueB) \
+ Dallp1(dbl_valueA) &= 0xfff00000; \
+ Dallp2(dbl_valueB) = 0
+#define Dbl_setzero_mantissap1(dbl_value) Dallp1(dbl_value) &= 0xfff00000
+#define Dbl_setzero_mantissap2(dbl_value) Dallp2(dbl_value) = 0
+#define Dbl_setzero_exponentmantissa(dbl_valueA,dbl_valueB) \
+ Dallp1(dbl_valueA) &= 0x80000000; \
+ Dallp2(dbl_valueB) = 0
+#define Dbl_setzero_exponentmantissap1(dbl_valueA) \
+ Dallp1(dbl_valueA) &= 0x80000000
+#define Dbl_setzero(dbl_valueA,dbl_valueB) \
+ Dallp1(dbl_valueA) = 0; Dallp2(dbl_valueB) = 0
+#define Dbl_setzerop1(dbl_value) Dallp1(dbl_value) = 0
+#define Dbl_setzerop2(dbl_value) Dallp2(dbl_value) = 0
+#define Dbl_setnegativezero(dbl_value) \
+ Dallp1(dbl_value) = (unsigned int)1 << 31; Dallp2(dbl_value) = 0
+#define Dbl_setnegativezerop1(dbl_value) Dallp1(dbl_value) = (unsigned int)1<<31
+
+/* Use the following macro for both overflow & underflow conditions */
+#define ovfl -
+#define unfl +
+#define Dbl_setwrapped_exponent(dbl_value,exponent,op) \
+ Deposit_dexponent(dbl_value,(exponent op DBL_WRAP))
+
+#define Dbl_setlargestpositive(dbl_valueA,dbl_valueB) \
+ Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
+ | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ); \
+ Dallp2(dbl_valueB) = 0xFFFFFFFF
+#define Dbl_setlargestnegative(dbl_valueA,dbl_valueB) \
+ Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
+ | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ) \
+ | ((unsigned int)1<<31); \
+ Dallp2(dbl_valueB) = 0xFFFFFFFF
+#define Dbl_setlargest_exponentmantissa(dbl_valueA,dbl_valueB) \
+ Deposit_dexponentmantissap1(dbl_valueA, \
+ (((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
+ | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ))); \
+ Dallp2(dbl_valueB) = 0xFFFFFFFF
+
+#define Dbl_setnegativeinfinity(dbl_valueA,dbl_valueB) \
+ Dallp1(dbl_valueA) = ((1<<DBL_EXP_LENGTH) | DBL_INFINITY_EXPONENT) \
+ << (32-(1+DBL_EXP_LENGTH)) ; \
+ Dallp2(dbl_valueB) = 0
+#define Dbl_setlargest(dbl_valueA,dbl_valueB,sign) \
+ Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \
+ ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) | \
+ ((1 << (32-(1+DBL_EXP_LENGTH))) - 1 ); \
+ Dallp2(dbl_valueB) = 0xFFFFFFFF
+
+
+/* The high bit is always zero so arithmetic or logical shifts will work. */
+#define Dbl_right_align(srcdstA,srcdstB,shift,extent) \
+ if( shift >= 32 ) \
+ { \
+ /* Big shift requires examining the portion shift off \
+ the end to properly set inexact. */ \
+ if(shift < 64) \
+ { \
+ if(shift > 32) \
+ { \
+ Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB), \
+ shift-32, Extall(extent)); \
+ if(Dallp2(srcdstB) << 64 - (shift)) Ext_setone_low(extent); \
+ } \
+ else Extall(extent) = Dallp2(srcdstB); \
+ Dallp2(srcdstB) = Dallp1(srcdstA) >> (shift - 32); \
+ } \
+ else \
+ { \
+ Extall(extent) = Dallp1(srcdstA); \
+ if(Dallp2(srcdstB)) Ext_setone_low(extent); \
+ Dallp2(srcdstB) = 0; \
+ } \
+ Dallp1(srcdstA) = 0; \
+ } \
+ else \
+ { \
+ /* Small alignment is simpler. Extension is easily set. */ \
+ if (shift > 0) \
+ { \
+ Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \
+ Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB),shift, \
+ Dallp2(srcdstB)); \
+ Dallp1(srcdstA) >>= shift; \
+ } \
+ else Extall(extent) = 0; \
+ }
+
+/*
+ * Here we need to shift the result right to correct for an overshift
+ * (due to the exponent becoming negative) during normalization.
+ */
+#define Dbl_fix_overshift(srcdstA,srcdstB,shift,extent) \
+ Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \
+ Dallp2(srcdstB) = (Dallp1(srcdstA) << 32 - (shift)) | \
+ (Dallp2(srcdstB) >> (shift)); \
+ Dallp1(srcdstA) = Dallp1(srcdstA) >> shift
+
+#define Dbl_hiddenhigh3mantissa(dbl_value) Dhiddenhigh3mantissa(dbl_value)
+#define Dbl_hidden(dbl_value) Dhidden(dbl_value)
+#define Dbl_lowmantissap2(dbl_value) Dlowp2(dbl_value)
+
+/* The left argument is never smaller than the right argument */
+#define Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb) \
+ if( Dallp2(rightb) > Dallp2(leftb) ) Dallp1(lefta)--; \
+ Dallp2(resultb) = Dallp2(leftb) - Dallp2(rightb); \
+ Dallp1(resulta) = Dallp1(lefta) - Dallp1(righta)
+
+/* Subtract right augmented with extension from left augmented with zeros and
+ * store into result and extension. */
+#define Dbl_subtract_withextension(lefta,leftb,righta,rightb,extent,resulta,resultb) \
+ Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb); \
+ if( (Extall(extent) = 0-Extall(extent)) ) \
+ { \
+ if((Dallp2(resultb)--) == 0) Dallp1(resulta)--; \
+ }
+
+#define Dbl_addition(lefta,leftb,righta,rightb,resulta,resultb) \
+ /* If the sum of the low words is less than either source, then \
+ * an overflow into the next word occurred. */ \
+ Dallp1(resulta) = Dallp1(lefta) + Dallp1(righta); \
+ if((Dallp2(resultb) = Dallp2(leftb) + Dallp2(rightb)) < Dallp2(rightb)) \
+ Dallp1(resulta)++
+
+#define Dbl_xortointp1(left,right,result) \
+ result = Dallp1(left) XOR Dallp1(right)
+
+#define Dbl_xorfromintp1(left,right,result) \
+ Dallp1(result) = left XOR Dallp1(right)
+
+#define Dbl_swap_lower(left,right) \
+ Dallp2(left) = Dallp2(left) XOR Dallp2(right); \
+ Dallp2(right) = Dallp2(left) XOR Dallp2(right); \
+ Dallp2(left) = Dallp2(left) XOR Dallp2(right)
+
+/* Need to Initialize */
+#define Dbl_makequietnan(desta,destb) \
+ Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \
+ | (1<<(32-(1+DBL_EXP_LENGTH+2))); \
+ Dallp2(destb) = 0
+#define Dbl_makesignalingnan(desta,destb) \
+ Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \
+ | (1<<(32-(1+DBL_EXP_LENGTH+1))); \
+ Dallp2(destb) = 0
+
+#define Dbl_normalize(dbl_opndA,dbl_opndB,exponent) \
+ while(Dbl_iszero_hiddenhigh7mantissa(dbl_opndA)) { \
+ Dbl_leftshiftby8(dbl_opndA,dbl_opndB); \
+ exponent -= 8; \
+ } \
+ if(Dbl_iszero_hiddenhigh3mantissa(dbl_opndA)) { \
+ Dbl_leftshiftby4(dbl_opndA,dbl_opndB); \
+ exponent -= 4; \
+ } \
+ while(Dbl_iszero_hidden(dbl_opndA)) { \
+ Dbl_leftshiftby1(dbl_opndA,dbl_opndB); \
+ exponent -= 1; \
+ }
+
+#define Twoword_add(src1dstA,src1dstB,src2A,src2B) \
+ /* \
+ * want this macro to generate: \
+ * ADD src1dstB,src2B,src1dstB; \
+ * ADDC src1dstA,src2A,src1dstA; \
+ */ \
+ if ((src1dstB) + (src2B) < (src1dstB)) Dallp1(src1dstA)++; \
+ Dallp1(src1dstA) += (src2A); \
+ Dallp2(src1dstB) += (src2B)
+
+#define Twoword_subtract(src1dstA,src1dstB,src2A,src2B) \
+ /* \
+ * want this macro to generate: \
+ * SUB src1dstB,src2B,src1dstB; \
+ * SUBB src1dstA,src2A,src1dstA; \
+ */ \
+ if ((src1dstB) < (src2B)) Dallp1(src1dstA)--; \
+ Dallp1(src1dstA) -= (src2A); \
+ Dallp2(src1dstB) -= (src2B)
+
+#define Dbl_setoverflow(resultA,resultB) \
+ /* set result to infinity or largest number */ \
+ switch (Rounding_mode()) { \
+ case ROUNDPLUS: \
+ if (Dbl_isone_sign(resultA)) { \
+ Dbl_setlargestnegative(resultA,resultB); \
+ } \
+ else { \
+ Dbl_setinfinitypositive(resultA,resultB); \
+ } \
+ break; \
+ case ROUNDMINUS: \
+ if (Dbl_iszero_sign(resultA)) { \
+ Dbl_setlargestpositive(resultA,resultB); \
+ } \
+ else { \
+ Dbl_setinfinitynegative(resultA,resultB); \
+ } \
+ break; \
+ case ROUNDNEAREST: \
+ Dbl_setinfinity_exponentmantissa(resultA,resultB); \
+ break; \
+ case ROUNDZERO: \
+ Dbl_setlargest_exponentmantissa(resultA,resultB); \
+ }
+
+#define Dbl_denormalize(opndp1,opndp2,exponent,guard,sticky,inexact) \
+ Dbl_clear_signexponent_set_hidden(opndp1); \
+ if (exponent >= (1-DBL_P)) { \
+ if (exponent >= -31) { \
+ guard = (Dallp2(opndp2) >> -exponent) & 1; \
+ if (exponent < 0) sticky |= Dallp2(opndp2) << (32+exponent); \
+ if (exponent > -31) { \
+ Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \
+ Dallp1(opndp1) >>= 1-exponent; \
+ } \
+ else { \
+ Dallp2(opndp2) = Dallp1(opndp1); \
+ Dbl_setzerop1(opndp1); \
+ } \
+ } \
+ else { \
+ guard = (Dallp1(opndp1) >> -32-exponent) & 1; \
+ if (exponent == -32) sticky |= Dallp2(opndp2); \
+ else sticky |= (Dallp2(opndp2) | Dallp1(opndp1) << 64+exponent); \
+ Dallp2(opndp2) = Dallp1(opndp1) >> -31-exponent; \
+ Dbl_setzerop1(opndp1); \
+ } \
+ inexact = guard | sticky; \
+ } \
+ else { \
+ guard = 0; \
+ sticky |= (Dallp1(opndp1) | Dallp2(opndp2)); \
+ Dbl_setzero(opndp1,opndp2); \
+ inexact = sticky; \
+ }
+
+/*
+ * The fused multiply add instructions requires a double extended format,
+ * with 106 bits of mantissa.
+ */
+#define DBLEXT_THRESHOLD 106
+
+#define Dblext_setzero(valA,valB,valC,valD) \
+ Dextallp1(valA) = 0; Dextallp2(valB) = 0; \
+ Dextallp3(valC) = 0; Dextallp4(valD) = 0
+
+
+#define Dblext_isnotzero_mantissap3(valC) (Dextallp3(valC)!=0)
+#define Dblext_isnotzero_mantissap4(valD) (Dextallp3(valD)!=0)
+#define Dblext_isone_lowp2(val) (Dextlowp2(val)!=0)
+#define Dblext_isone_highp3(val) (Dexthighp3(val)!=0)
+#define Dblext_isnotzero_low31p3(val) (Dextlow31p3(val)!=0)
+#define Dblext_iszero(valA,valB,valC,valD) (Dextallp1(valA)==0 && \
+ Dextallp2(valB)==0 && Dextallp3(valC)==0 && Dextallp4(valD)==0)
+
+#define Dblext_copy(srca,srcb,srcc,srcd,desta,destb,destc,destd) \
+ Dextallp1(desta) = Dextallp4(srca); \
+ Dextallp2(destb) = Dextallp4(srcb); \
+ Dextallp3(destc) = Dextallp4(srcc); \
+ Dextallp4(destd) = Dextallp4(srcd)
+
+#define Dblext_swap_lower(leftp2,leftp3,leftp4,rightp2,rightp3,rightp4) \
+ Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
+ Dextallp2(rightp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
+ Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
+ Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
+ Dextallp3(rightp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
+ Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
+ Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \
+ Dextallp4(rightp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \
+ Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4)
+
+#define Dblext_setone_lowmantissap4(dbl_value) Deposit_dextlowp4(dbl_value,1)
+
+/* The high bit is always zero so arithmetic or logical shifts will work. */
+#define Dblext_right_align(srcdstA,srcdstB,srcdstC,srcdstD,shift) \
+ {int shiftamt, sticky; \
+ shiftamt = shift % 32; \
+ sticky = 0; \
+ switch (shift/32) { \
+ case 0: if (shiftamt > 0) { \
+ sticky = Dextallp4(srcdstD) << 32 - (shiftamt); \
+ Variable_shift_double(Dextallp3(srcdstC), \
+ Dextallp4(srcdstD),shiftamt,Dextallp4(srcdstD)); \
+ Variable_shift_double(Dextallp2(srcdstB), \
+ Dextallp3(srcdstC),shiftamt,Dextallp3(srcdstC)); \
+ Variable_shift_double(Dextallp1(srcdstA), \
+ Dextallp2(srcdstB),shiftamt,Dextallp2(srcdstB)); \
+ Dextallp1(srcdstA) >>= shiftamt; \
+ } \
+ break; \
+ case 1: if (shiftamt > 0) { \
+ sticky = (Dextallp3(srcdstC) << 31 - shiftamt) | \
+ Dextallp4(srcdstD); \
+ Variable_shift_double(Dextallp2(srcdstB), \
+ Dextallp3(srcdstC),shiftamt,Dextallp4(srcdstD)); \
+ Variable_shift_double(Dextallp1(srcdstA), \
+ Dextallp2(srcdstB),shiftamt,Dextallp3(srcdstC)); \
+ } \
+ else { \
+ sticky = Dextallp4(srcdstD); \
+ Dextallp4(srcdstD) = Dextallp3(srcdstC); \
+ Dextallp3(srcdstC) = Dextallp2(srcdstB); \
+ } \
+ Dextallp2(srcdstB) = Dextallp1(srcdstA) >> shiftamt; \
+ Dextallp1(srcdstA) = 0; \
+ break; \
+ case 2: if (shiftamt > 0) { \
+ sticky = (Dextallp2(srcdstB) << 31 - shiftamt) | \
+ Dextallp3(srcdstC) | Dextallp4(srcdstD); \
+ Variable_shift_double(Dextallp1(srcdstA), \
+ Dextallp2(srcdstB),shiftamt,Dextallp4(srcdstD)); \
+ } \
+ else { \
+ sticky = Dextallp3(srcdstC) | Dextallp4(srcdstD); \
+ Dextallp4(srcdstD) = Dextallp2(srcdstB); \
+ } \
+ Dextallp3(srcdstC) = Dextallp1(srcdstA) >> shiftamt; \
+ Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \
+ break; \
+ case 3: if (shiftamt > 0) { \
+ sticky = (Dextallp1(srcdstA) << 31 - shiftamt) | \
+ Dextallp2(srcdstB) | Dextallp3(srcdstC) | \
+ Dextallp4(srcdstD); \
+ } \
+ else { \
+ sticky = Dextallp2(srcdstB) | Dextallp3(srcdstC) | \
+ Dextallp4(srcdstD); \
+ } \
+ Dextallp4(srcdstD) = Dextallp1(srcdstA) >> shiftamt; \
+ Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \
+ Dextallp3(srcdstC) = 0; \
+ break; \
+ } \
+ if (sticky) Dblext_setone_lowmantissap4(srcdstD); \
+ }
+
+/* The left argument is never smaller than the right argument */
+#define Dblext_subtract(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \
+ if( Dextallp4(rightd) > Dextallp4(leftd) ) \
+ if( (Dextallp3(leftc)--) == 0) \
+ if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \
+ Dextallp4(resultd) = Dextallp4(leftd) - Dextallp4(rightd); \
+ if( Dextallp3(rightc) > Dextallp3(leftc) ) \
+ if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \
+ Dextallp3(resultc) = Dextallp3(leftc) - Dextallp3(rightc); \
+ if( Dextallp2(rightb) > Dextallp2(leftb) ) Dextallp1(lefta)--; \
+ Dextallp2(resultb) = Dextallp2(leftb) - Dextallp2(rightb); \
+ Dextallp1(resulta) = Dextallp1(lefta) - Dextallp1(righta)
+
+#define Dblext_addition(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \
+ /* If the sum of the low words is less than either source, then \
+ * an overflow into the next word occurred. */ \
+ if ((Dextallp4(resultd) = Dextallp4(leftd)+Dextallp4(rightd)) < \
+ Dextallp4(rightd)) \
+ if((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)+1) <= \
+ Dextallp3(rightc)) \
+ if((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \
+ <= Dextallp2(rightb)) \
+ Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
+ else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
+ else \
+ if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \
+ Dextallp2(rightb)) \
+ Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
+ else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
+ else \
+ if ((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)) < \
+ Dextallp3(rightc)) \
+ if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \
+ <= Dextallp2(rightb)) \
+ Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
+ else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
+ else \
+ if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \
+ Dextallp2(rightb)) \
+ Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
+ else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)
+
+
+#define Dblext_arithrightshiftby1(srcdstA,srcdstB,srcdstC,srcdstD) \
+ Shiftdouble(Dextallp3(srcdstC),Dextallp4(srcdstD),1,Dextallp4(srcdstD)); \
+ Shiftdouble(Dextallp2(srcdstB),Dextallp3(srcdstC),1,Dextallp3(srcdstC)); \
+ Shiftdouble(Dextallp1(srcdstA),Dextallp2(srcdstB),1,Dextallp2(srcdstB)); \
+ Dextallp1(srcdstA) = (int)Dextallp1(srcdstA) >> 1
+
+#define Dblext_leftshiftby8(valA,valB,valC,valD) \
+ Shiftdouble(Dextallp1(valA),Dextallp2(valB),24,Dextallp1(valA)); \
+ Shiftdouble(Dextallp2(valB),Dextallp3(valC),24,Dextallp2(valB)); \
+ Shiftdouble(Dextallp3(valC),Dextallp4(valD),24,Dextallp3(valC)); \
+ Dextallp4(valD) <<= 8
+#define Dblext_leftshiftby4(valA,valB,valC,valD) \
+ Shiftdouble(Dextallp1(valA),Dextallp2(valB),28,Dextallp1(valA)); \
+ Shiftdouble(Dextallp2(valB),Dextallp3(valC),28,Dextallp2(valB)); \
+ Shiftdouble(Dextallp3(valC),Dextallp4(valD),28,Dextallp3(valC)); \
+ Dextallp4(valD) <<= 4
+#define Dblext_leftshiftby3(valA,valB,valC,valD) \
+ Shiftdouble(Dextallp1(valA),Dextallp2(valB),29,Dextallp1(valA)); \
+ Shiftdouble(Dextallp2(valB),Dextallp3(valC),29,Dextallp2(valB)); \
+ Shiftdouble(Dextallp3(valC),Dextallp4(valD),29,Dextallp3(valC)); \
+ Dextallp4(valD) <<= 3
+#define Dblext_leftshiftby2(valA,valB,valC,valD) \
+ Shiftdouble(Dextallp1(valA),Dextallp2(valB),30,Dextallp1(valA)); \
+ Shiftdouble(Dextallp2(valB),Dextallp3(valC),30,Dextallp2(valB)); \
+ Shiftdouble(Dextallp3(valC),Dextallp4(valD),30,Dextallp3(valC)); \
+ Dextallp4(valD) <<= 2
+#define Dblext_leftshiftby1(valA,valB,valC,valD) \
+ Shiftdouble(Dextallp1(valA),Dextallp2(valB),31,Dextallp1(valA)); \
+ Shiftdouble(Dextallp2(valB),Dextallp3(valC),31,Dextallp2(valB)); \
+ Shiftdouble(Dextallp3(valC),Dextallp4(valD),31,Dextallp3(valC)); \
+ Dextallp4(valD) <<= 1
+
+#define Dblext_rightshiftby4(valueA,valueB,valueC,valueD) \
+ Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),4,Dextallp4(valueD)); \
+ Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),4,Dextallp3(valueC)); \
+ Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),4,Dextallp2(valueB)); \
+ Dextallp1(valueA) >>= 4
+#define Dblext_rightshiftby1(valueA,valueB,valueC,valueD) \
+ Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),1,Dextallp4(valueD)); \
+ Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),1,Dextallp3(valueC)); \
+ Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),1,Dextallp2(valueB)); \
+ Dextallp1(valueA) >>= 1
+
+#define Dblext_xortointp1(left,right,result) Dbl_xortointp1(left,right,result)
+
+#define Dblext_xorfromintp1(left,right,result) \
+ Dbl_xorfromintp1(left,right,result)
+
+#define Dblext_copytoint_exponentmantissap1(src,dest) \
+ Dbl_copytoint_exponentmantissap1(src,dest)
+
+#define Dblext_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \
+ Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright)
+
+#define Dbl_copyto_dblext(src1,src2,dest1,dest2,dest3,dest4) \
+ Dextallp1(dest1) = Dallp1(src1); Dextallp2(dest2) = Dallp2(src2); \
+ Dextallp3(dest3) = 0; Dextallp4(dest4) = 0
+
+#define Dblext_set_sign(dbl_value,sign) Dbl_set_sign(dbl_value,sign)
+#define Dblext_clear_signexponent_set_hidden(srcdst) \
+ Dbl_clear_signexponent_set_hidden(srcdst)
+#define Dblext_clear_signexponent(srcdst) Dbl_clear_signexponent(srcdst)
+#define Dblext_clear_sign(srcdst) Dbl_clear_sign(srcdst)
+#define Dblext_isone_hidden(dbl_value) Dbl_isone_hidden(dbl_value)
+
+/*
+ * The Fourword_add() macro assumes that integers are 4 bytes in size.
+ * It will break if this is not the case.
+ */
+
+#define Fourword_add(src1dstA,src1dstB,src1dstC,src1dstD,src2A,src2B,src2C,src2D) \
+ /* \
+ * want this macro to generate: \
+ * ADD src1dstD,src2D,src1dstD; \
+ * ADDC src1dstC,src2C,src1dstC; \
+ * ADDC src1dstB,src2B,src1dstB; \
+ * ADDC src1dstA,src2A,src1dstA; \
+ */ \
+ if ((unsigned int)(src1dstD += (src2D)) < (unsigned int)(src2D)) { \
+ if ((unsigned int)(src1dstC += (src2C) + 1) <= \
+ (unsigned int)(src2C)) { \
+ if ((unsigned int)(src1dstB += (src2B) + 1) <= \
+ (unsigned int)(src2B)) src1dstA++; \
+ } \
+ else if ((unsigned int)(src1dstB += (src2B)) < \
+ (unsigned int)(src2B)) src1dstA++; \
+ } \
+ else { \
+ if ((unsigned int)(src1dstC += (src2C)) < \
+ (unsigned int)(src2C)) { \
+ if ((unsigned int)(src1dstB += (src2B) + 1) <= \
+ (unsigned int)(src2B)) src1dstA++; \
+ } \
+ else if ((unsigned int)(src1dstB += (src2B)) < \
+ (unsigned int)(src2B)) src1dstA++; \
+ } \
+ src1dstA += (src2A)
+
+#define Dblext_denormalize(opndp1,opndp2,opndp3,opndp4,exponent,is_tiny) \
+ {int shiftamt, sticky; \
+ is_tiny = TRUE; \
+ if (exponent == 0 && (Dextallp3(opndp3) || Dextallp4(opndp4))) { \
+ switch (Rounding_mode()) { \
+ case ROUNDPLUS: \
+ if (Dbl_iszero_sign(opndp1)) { \
+ Dbl_increment(opndp1,opndp2); \
+ if (Dbl_isone_hiddenoverflow(opndp1)) \
+ is_tiny = FALSE; \
+ Dbl_decrement(opndp1,opndp2); \
+ } \
+ break; \
+ case ROUNDMINUS: \
+ if (Dbl_isone_sign(opndp1)) { \
+ Dbl_increment(opndp1,opndp2); \
+ if (Dbl_isone_hiddenoverflow(opndp1)) \
+ is_tiny = FALSE; \
+ Dbl_decrement(opndp1,opndp2); \
+ } \
+ break; \
+ case ROUNDNEAREST: \
+ if (Dblext_isone_highp3(opndp3) && \
+ (Dblext_isone_lowp2(opndp2) || \
+ Dblext_isnotzero_low31p3(opndp3))) { \
+ Dbl_increment(opndp1,opndp2); \
+ if (Dbl_isone_hiddenoverflow(opndp1)) \
+ is_tiny = FALSE; \
+ Dbl_decrement(opndp1,opndp2); \
+ } \
+ break; \
+ } \
+ } \
+ Dblext_clear_signexponent_set_hidden(opndp1); \
+ if (exponent >= (1-QUAD_P)) { \
+ shiftamt = (1-exponent) % 32; \
+ switch((1-exponent)/32) { \
+ case 0: sticky = Dextallp4(opndp4) << 32-(shiftamt); \
+ Variableshiftdouble(opndp3,opndp4,shiftamt,opndp4); \
+ Variableshiftdouble(opndp2,opndp3,shiftamt,opndp3); \
+ Variableshiftdouble(opndp1,opndp2,shiftamt,opndp2); \
+ Dextallp1(opndp1) >>= shiftamt; \
+ break; \
+ case 1: sticky = (Dextallp3(opndp3) << 32-(shiftamt)) | \
+ Dextallp4(opndp4); \
+ Variableshiftdouble(opndp2,opndp3,shiftamt,opndp4); \
+ Variableshiftdouble(opndp1,opndp2,shiftamt,opndp3); \
+ Dextallp2(opndp2) = Dextallp1(opndp1) >> shiftamt; \
+ Dextallp1(opndp1) = 0; \
+ break; \
+ case 2: sticky = (Dextallp2(opndp2) << 32-(shiftamt)) | \
+ Dextallp3(opndp3) | Dextallp4(opndp4); \
+ Variableshiftdouble(opndp1,opndp2,shiftamt,opndp4); \
+ Dextallp3(opndp3) = Dextallp1(opndp1) >> shiftamt; \
+ Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \
+ break; \
+ case 3: sticky = (Dextallp1(opndp1) << 32-(shiftamt)) | \
+ Dextallp2(opndp2) | Dextallp3(opndp3) | \
+ Dextallp4(opndp4); \
+ Dextallp4(opndp4) = Dextallp1(opndp1) >> shiftamt; \
+ Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \
+ Dextallp3(opndp3) = 0; \
+ break; \
+ } \
+ } \
+ else { \
+ sticky = Dextallp1(opndp1) | Dextallp2(opndp2) | \
+ Dextallp3(opndp3) | Dextallp4(opndp4); \
+ Dblext_setzero(opndp1,opndp2,opndp3,opndp4); \
+ } \
+ if (sticky) Dblext_setone_lowmantissap4(opndp4); \
+ exponent = 0; \
+ }
diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c
new file mode 100644
index 000000000000..f84f2586672b
--- /dev/null
+++ b/arch/parisc/math-emu/decode_exc.c
@@ -0,0 +1,368 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/fp/decode_exc.c $ Revision: $
+ *
+ * Purpose:
+ * <<please update with a synopsis of the functionality provided by this file>>
+ *
+ * External Interfaces:
+ * <<the following list was autogenerated, please review>>
+ * decode_fpu(Fpu_register, trap_counts)
+ *
+ * Internal Interfaces:
+ * <<please update>>
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+/* #include "types.h" */
+#include <asm/signal.h>
+#include <asm/siginfo.h>
+/* #include <machine/sys/mdep_private.h> */
+
+#undef Fpustatus_register
+#define Fpustatus_register Fpu_register[0]
+
+/* General definitions */
+#define DOESTRAP 1
+#define NOTRAP 0
+#define SIGNALCODE(signal, code) ((signal) << 24 | (code));
+#define copropbit 1<<31-2 /* bit position 2 */
+#define opclass 9 /* bits 21 & 22 */
+#define fmt 11 /* bits 19 & 20 */
+#define df 13 /* bits 17 & 18 */
+#define twobits 3 /* mask low-order 2 bits */
+#define fivebits 31 /* mask low-order 5 bits */
+#define MAX_EXCP_REG 7 /* number of excpeption registers to check */
+
+/* Exception register definitions */
+#define Excp_type(index) Exceptiontype(Fpu_register[index])
+#define Excp_instr(index) Instructionfield(Fpu_register[index])
+#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
+#define Excp_format() \
+ (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)
+
+/* Miscellaneous definitions */
+#define Fpu_sgl(index) Fpu_register[index*2]
+
+#define Fpu_dblp1(index) Fpu_register[index*2]
+#define Fpu_dblp2(index) Fpu_register[(index*2)+1]
+
+#define Fpu_quadp1(index) Fpu_register[index*2]
+#define Fpu_quadp2(index) Fpu_register[(index*2)+1]
+#define Fpu_quadp3(index) Fpu_register[(index*2)+2]
+#define Fpu_quadp4(index) Fpu_register[(index*2)+3]
+
+/* Single precision floating-point definitions */
+#ifndef Sgl_decrement
+# define Sgl_decrement(sgl_value) Sall(sgl_value)--
+#endif
+
+/* Double precision floating-point definitions */
+#ifndef Dbl_decrement
+# define Dbl_decrement(dbl_valuep1,dbl_valuep2) \
+ if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)--
+#endif
+
+
+#define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) { \
+ aflags=(Fpu_register[0])>>27; /* assumes zero fill. 32 bit */ \
+ Fpu_register[0] |= bflags; \
+}
+
+u_int
+decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[])
+{
+ unsigned int current_ir, excp;
+ int target, exception_index = 1;
+ boolean inexact;
+ unsigned int aflags;
+ unsigned int bflags;
+ unsigned int excptype;
+
+
+ /* Keep stats on how many floating point exceptions (based on type)
+ * that happen. Want to keep this overhead low, but still provide
+ * some information to the customer. All exits from this routine
+ * need to restore Fpu_register[0]
+ */
+
+ bflags=(Fpu_register[0] & 0xf8000000);
+ Fpu_register[0] &= 0x07ffffff;
+
+ /* exception_index is used to index the exception register queue. It
+ * always points at the last register that contains a valid exception. A
+ * zero value implies no exceptions (also the initialized value). Setting
+ * the T-bit resets the exception_index to zero.
+ */
+
+ /*
+ * Check for reserved-op exception. A reserved-op exception does not
+ * set any exception registers nor does it set the T-bit. If the T-bit
+ * is not set then a reserved-op exception occurred.
+ *
+ * At some point, we may want to report reserved op exceptions as
+ * illegal instructions.
+ */
+
+ if (!Is_tbit_set()) {
+ update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+ return SIGNALCODE(SIGILL, ILL_COPROC);
+ }
+
+ /*
+ * Is a coprocessor op.
+ *
+ * Now we need to determine what type of exception occurred.
+ */
+ for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {
+ current_ir = Excp_instr(exception_index);
+ /*
+ * On PA89: there are 5 different unimplemented exception
+ * codes: 0x1, 0x9, 0xb, 0x3, and 0x23. PA-RISC 2.0 adds
+ * another, 0x2b. Only these have the low order bit set.
+ */
+ excptype = Excp_type(exception_index);
+ if (excptype & UNIMPLEMENTEDEXCEPTION) {
+ /*
+ * Clear T-bit and exception register so that
+ * we can tell if a trap really occurs while
+ * emulating the instruction.
+ */
+ Clear_tbit();
+ Clear_excp_register(exception_index);
+ /*
+ * Now emulate this instruction. If a trap occurs,
+ * fpudispatch will return a non-zero number
+ */
+ excp = fpudispatch(current_ir,excptype,0,Fpu_register);
+ /* accumulate the status flags, don't lose them as in hpux */
+ if (excp) {
+ /*
+ * We now need to make sure that the T-bit and the
+ * exception register contain the correct values
+ * before continuing.
+ */
+ /*
+ * Set t-bit since it might still be needed for a
+ * subsequent real trap (I don't understand fully -PB)
+ */
+ Set_tbit();
+ /* some of the following code uses
+ * Excp_type(exception_index) so fix that up */
+ Set_exceptiontype_and_instr_field(excp,current_ir,
+ Fpu_register[exception_index]);
+ if (excp == UNIMPLEMENTEDEXCEPTION) {
+ /*
+ * it is really unimplemented, so restore the
+ * TIMEX extended unimplemented exception code
+ */
+ excp = excptype;
+ update_trap_counts(Fpu_register, aflags, bflags,
+ trap_counts);
+ return SIGNALCODE(SIGILL, ILL_COPROC);
+ }
+ /* some of the following code uses excptype, so
+ * fix that up too */
+ excptype = excp;
+ }
+ /* handle exceptions other than the real UNIMPLIMENTED the
+ * same way as if the hardware had caused them */
+ if (excp == NOEXCEPTION)
+ /* For now use 'break', should technically be 'continue' */
+ break;
+ }
+
+ /*
+ * In PA89, the underflow exception has been extended to encode
+ * additional information. The exception looks like pp01x0,
+ * where x is 1 if inexact and pp represent the inexact bit (I)
+ * and the round away bit (RA)
+ */
+ if (excptype & UNDERFLOWEXCEPTION) {
+ /* check for underflow trap enabled */
+ if (Is_underflowtrap_enabled()) {
+ update_trap_counts(Fpu_register, aflags, bflags,
+ trap_counts);
+ return SIGNALCODE(SIGFPE, FPE_FLTUND);
+ } else {
+ /*
+ * Isn't a real trap; we need to
+ * return the default value.
+ */
+ target = current_ir & fivebits;
+#ifndef lint
+ if (Ibit(Fpu_register[exception_index])) inexact = TRUE;
+ else inexact = FALSE;
+#endif
+ switch (Excp_format()) {
+ case SGL:
+ /*
+ * If ra (round-away) is set, will
+ * want to undo the rounding done
+ * by the hardware.
+ */
+ if (Rabit(Fpu_register[exception_index]))
+ Sgl_decrement(Fpu_sgl(target));
+
+ /* now denormalize */
+ sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());
+ break;
+ case DBL:
+ /*
+ * If ra (round-away) is set, will
+ * want to undo the rounding done
+ * by the hardware.
+ */
+ if (Rabit(Fpu_register[exception_index]))
+ Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));
+
+ /* now denormalize */
+ dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),
+ &inexact,Rounding_mode());
+ break;
+ }
+ if (inexact) Set_underflowflag();
+ /*
+ * Underflow can generate an inexact
+ * exception. If inexact trap is enabled,
+ * want to do an inexact trap, otherwise
+ * set inexact flag.
+ */
+ if (inexact && Is_inexacttrap_enabled()) {
+ /*
+ * Set exception field of exception register
+ * to inexact, parm field to zero.
+ * Underflow bit should be cleared.
+ */
+ Set_exceptiontype(Fpu_register[exception_index],
+ INEXACTEXCEPTION);
+ Set_parmfield(Fpu_register[exception_index],0);
+ update_trap_counts(Fpu_register, aflags, bflags,
+ trap_counts);
+ return SIGNALCODE(SIGFPE, FPE_FLTRES);
+ }
+ else {
+ /*
+ * Exception register needs to be cleared.
+ * Inexact flag needs to be set if inexact.
+ */
+ Clear_excp_register(exception_index);
+ if (inexact) Set_inexactflag();
+ }
+ }
+ continue;
+ }
+ switch(Excp_type(exception_index)) {
+ case OVERFLOWEXCEPTION:
+ case OVERFLOWEXCEPTION | INEXACTEXCEPTION:
+ /* check for overflow trap enabled */
+ update_trap_counts(Fpu_register, aflags, bflags,
+ trap_counts);
+ if (Is_overflowtrap_enabled()) {
+ update_trap_counts(Fpu_register, aflags, bflags,
+ trap_counts);
+ return SIGNALCODE(SIGFPE, FPE_FLTOVF);
+ } else {
+ /*
+ * Isn't a real trap; we need to
+ * return the default value.
+ */
+ target = current_ir & fivebits;
+ switch (Excp_format()) {
+ case SGL:
+ Sgl_setoverflow(Fpu_sgl(target));
+ break;
+ case DBL:
+ Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));
+ break;
+ }
+ Set_overflowflag();
+ /*
+ * Overflow always generates an inexact
+ * exception. If inexact trap is enabled,
+ * want to do an inexact trap, otherwise
+ * set inexact flag.
+ */
+ if (Is_inexacttrap_enabled()) {
+ /*
+ * Set exception field of exception
+ * register to inexact. Overflow
+ * bit should be cleared.
+ */
+ Set_exceptiontype(Fpu_register[exception_index],
+ INEXACTEXCEPTION);
+ update_trap_counts(Fpu_register, aflags, bflags,
+ trap_counts);
+ return SIGNALCODE(SIGFPE, FPE_FLTRES);
+ }
+ else {
+ /*
+ * Exception register needs to be cleared.
+ * Inexact flag needs to be set.
+ */
+ Clear_excp_register(exception_index);
+ Set_inexactflag();
+ }
+ }
+ break;
+ case INVALIDEXCEPTION:
+ update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+ return SIGNALCODE(SIGFPE, FPE_FLTINV);
+ case DIVISIONBYZEROEXCEPTION:
+ update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+ return SIGNALCODE(SIGFPE, FPE_FLTDIV);
+ case INEXACTEXCEPTION:
+ update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+ return SIGNALCODE(SIGFPE, FPE_FLTRES);
+ default:
+ update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+ printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__,
+ __LINE__, Excp_type(exception_index));
+ return SIGNALCODE(SIGILL, ILL_COPROC);
+ case NOEXCEPTION: /* no exception */
+ /*
+ * Clear exception register in case
+ * other fields are non-zero.
+ */
+ Clear_excp_register(exception_index);
+ break;
+ }
+ }
+ /*
+ * No real exceptions occurred.
+ */
+ Clear_tbit();
+ update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+ return(NOTRAP);
+}
diff --git a/arch/parisc/math-emu/denormal.c b/arch/parisc/math-emu/denormal.c
new file mode 100644
index 000000000000..60687e13c34f
--- /dev/null
+++ b/arch/parisc/math-emu/denormal.c
@@ -0,0 +1,135 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/fp/denormal.c $ Revision: $
+ *
+ * Purpose:
+ * <<please update with a synopsis of the functionality provided by this file>>
+ *
+ * External Interfaces:
+ * <<the following list was autogenerated, please review>>
+ * dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
+ * sgl_denormalize(sgl_opnd,inexactflag,rmode)
+ *
+ * Internal Interfaces:
+ * <<please update>>
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "hppa.h"
+#include <linux/kernel.h>
+/* #include <machine/sys/mdep_private.h> */
+
+#undef Fpustatus_register
+#define Fpustatus_register Fpu_register[0]
+
+void
+sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
+{
+ unsigned int opnd;
+ int sign, exponent;
+ boolean guardbit = FALSE, stickybit, inexact;
+
+ opnd = *sgl_opnd;
+ stickybit = *inexactflag;
+ exponent = Sgl_exponent(opnd) - SGL_WRAP;
+ sign = Sgl_sign(opnd);
+ Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
+ if (inexact) {
+ switch (rmode) {
+ case ROUNDPLUS:
+ if (sign == 0) {
+ Sgl_increment(opnd);
+ }
+ break;
+ case ROUNDMINUS:
+ if (sign != 0) {
+ Sgl_increment(opnd);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Sgl_isone_lowmantissa(opnd))) {
+ Sgl_increment(opnd);
+ }
+ break;
+ }
+ }
+ Sgl_set_sign(opnd,sign);
+ *sgl_opnd = opnd;
+ *inexactflag = inexact;
+ return;
+}
+
+void
+dbl_denormalize(unsigned int *dbl_opndp1,
+ unsigned int * dbl_opndp2,
+ boolean *inexactflag,
+ int rmode)
+{
+ unsigned int opndp1, opndp2;
+ int sign, exponent;
+ boolean guardbit = FALSE, stickybit, inexact;
+
+ opndp1 = *dbl_opndp1;
+ opndp2 = *dbl_opndp2;
+ stickybit = *inexactflag;
+ exponent = Dbl_exponent(opndp1) - DBL_WRAP;
+ sign = Dbl_sign(opndp1);
+ Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
+ if (inexact) {
+ switch (rmode) {
+ case ROUNDPLUS:
+ if (sign == 0) {
+ Dbl_increment(opndp1,opndp2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (sign != 0) {
+ Dbl_increment(opndp1,opndp2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Dbl_isone_lowmantissap2(opndp2))) {
+ Dbl_increment(opndp1,opndp2);
+ }
+ break;
+ }
+ }
+ Dbl_set_sign(opndp1,sign);
+ *dbl_opndp1 = opndp1;
+ *dbl_opndp2 = opndp2;
+ *inexactflag = inexact;
+ return;
+}
diff --git a/arch/parisc/math-emu/dfadd.c b/arch/parisc/math-emu/dfadd.c
new file mode 100644
index 000000000000..e147d7d3b0f4
--- /dev/null
+++ b/arch/parisc/math-emu/dfadd.c
@@ -0,0 +1,524 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/dfadd.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Double_add: add two double precision values.
+ *
+ * External Interfaces:
+ * dbl_fadd(leftptr, rightptr, dstptr, status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * Double_add: add two double precision values.
+ */
+dbl_fadd(
+ dbl_floating_point *leftptr,
+ dbl_floating_point *rightptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int signless_upper_left, signless_upper_right, save;
+ register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
+ register unsigned int resultp1 = 0, resultp2 = 0;
+
+ register int result_exponent, right_exponent, diff_exponent;
+ register int sign_save, jumpsize;
+ register boolean inexact = FALSE;
+ register boolean underflowtrap;
+
+ /* Create local copies of the numbers */
+ Dbl_copyfromptr(leftptr,leftp1,leftp2);
+ Dbl_copyfromptr(rightptr,rightp1,rightp2);
+
+ /* A zero "save" helps discover equal operands (for later), *
+ * and is used in swapping operands (if needed). */
+ Dbl_xortointp1(leftp1,rightp1,/*to*/save);
+
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
+ {
+ if (Dbl_iszero_mantissa(leftp1,leftp2))
+ {
+ if (Dbl_isnotnan(rightp1,rightp2))
+ {
+ if (Dbl_isinfinity(rightp1,rightp2) && save!=0)
+ {
+ /*
+ * invalid since operands are opposite signed infinity's
+ */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ Dbl_copytoptr(leftp1,leftp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else
+ {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(leftp1))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(leftp1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(rightp1))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(rightp1);
+ Dbl_copytoptr(rightp1,rightp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(leftp1,leftp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ } /* End left NaN or Infinity processing */
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(rightp1))
+ {
+ if (Dbl_iszero_mantissa(rightp1,rightp2))
+ {
+ /* return infinity */
+ Dbl_copytoptr(rightp1,rightp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(rightp1))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(rightp1);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(rightp1,rightp2,dstptr);
+ return(NOEXCEPTION);
+ } /* End right NaN or Infinity processing */
+
+ /* Invariant: Must be dealing with finite numbers */
+
+ /* Compare operands by removing the sign */
+ Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
+ Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
+
+ /* sign difference selects add or sub operation. */
+ if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
+ {
+ /* Set the left operand to the larger one by XOR swap *
+ * First finish the first word using "save" */
+ Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
+ Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
+ Dbl_swap_lower(leftp2,rightp2);
+ result_exponent = Dbl_exponent(leftp1);
+ }
+ /* Invariant: left is not smaller than right. */
+
+ if((right_exponent = Dbl_exponent(rightp1)) == 0)
+ {
+ /* Denormalized operands. First look for zeroes */
+ if(Dbl_iszero_mantissa(rightp1,rightp2))
+ {
+ /* right is zero */
+ if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
+ {
+ /* Both operands are zeros */
+ if(Is_rounding_mode(ROUNDMINUS))
+ {
+ Dbl_or_signs(leftp1,/*with*/rightp1);
+ }
+ else
+ {
+ Dbl_and_signs(leftp1,/*with*/rightp1);
+ }
+ }
+ else
+ {
+ /* Left is not a zero and must be the result. Trapped
+ * underflows are signaled if left is denormalized. Result
+ * is always exact. */
+ if( (result_exponent == 0) && Is_underflowtrap_enabled() )
+ {
+ /* need to normalize results mantissa */
+ sign_save = Dbl_signextendedsign(leftp1);
+ Dbl_leftshiftby1(leftp1,leftp2);
+ Dbl_normalize(leftp1,leftp2,result_exponent);
+ Dbl_set_sign(leftp1,/*using*/sign_save);
+ Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
+ Dbl_copytoptr(leftp1,leftp2,dstptr);
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ }
+ Dbl_copytoptr(leftp1,leftp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /* Neither are zeroes */
+ Dbl_clear_sign(rightp1); /* Exponent is already cleared */
+ if(result_exponent == 0 )
+ {
+ /* Both operands are denormalized. The result must be exact
+ * and is simply calculated. A sum could become normalized and a
+ * difference could cancel to a true zero. */
+ if( (/*signed*/int) save < 0 )
+ {
+ Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
+ /*into*/resultp1,resultp2);
+ if(Dbl_iszero_mantissa(resultp1,resultp2))
+ {
+ if(Is_rounding_mode(ROUNDMINUS))
+ {
+ Dbl_setone_sign(resultp1);
+ }
+ else
+ {
+ Dbl_setzero_sign(resultp1);
+ }
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else
+ {
+ Dbl_addition(leftp1,leftp2,rightp1,rightp2,
+ /*into*/resultp1,resultp2);
+ if(Dbl_isone_hidden(resultp1))
+ {
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ if(Is_underflowtrap_enabled())
+ {
+ /* need to normalize result */
+ sign_save = Dbl_signextendedsign(resultp1);
+ Dbl_leftshiftby1(resultp1,resultp2);
+ Dbl_normalize(resultp1,resultp2,result_exponent);
+ Dbl_set_sign(resultp1,/*using*/sign_save);
+ Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ right_exponent = 1; /* Set exponent to reflect different bias
+ * with denomalized numbers. */
+ }
+ else
+ {
+ Dbl_clear_signexponent_set_hidden(rightp1);
+ }
+ Dbl_clear_exponent_set_hidden(leftp1);
+ diff_exponent = result_exponent - right_exponent;
+
+ /*
+ * Special case alignment of operands that would force alignment
+ * beyond the extent of the extension. A further optimization
+ * could special case this but only reduces the path length for this
+ * infrequent case.
+ */
+ if(diff_exponent > DBL_THRESHOLD)
+ {
+ diff_exponent = DBL_THRESHOLD;
+ }
+
+ /* Align right operand by shifting to right */
+ Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
+ /*and lower to*/extent);
+
+ /* Treat sum and difference of the operands separately. */
+ if( (/*signed*/int) save < 0 )
+ {
+ /*
+ * Difference of the two operands. Their can be no overflow. A
+ * borrow can occur out of the hidden bit and force a post
+ * normalization phase.
+ */
+ Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
+ /*with*/extent,/*into*/resultp1,resultp2);
+ if(Dbl_iszero_hidden(resultp1))
+ {
+ /* Handle normalization */
+ /* A straight foward algorithm would now shift the result
+ * and extension left until the hidden bit becomes one. Not
+ * all of the extension bits need participate in the shift.
+ * Only the two most significant bits (round and guard) are
+ * needed. If only a single shift is needed then the guard
+ * bit becomes a significant low order bit and the extension
+ * must participate in the rounding. If more than a single
+ * shift is needed, then all bits to the right of the guard
+ * bit are zeros, and the guard bit may or may not be zero. */
+ sign_save = Dbl_signextendedsign(resultp1);
+ Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
+
+ /* Need to check for a zero result. The sign and exponent
+ * fields have already been zeroed. The more efficient test
+ * of the full object can be used.
+ */
+ if(Dbl_iszero(resultp1,resultp2))
+ /* Must have been "x-x" or "x+(-x)". */
+ {
+ if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ result_exponent--;
+ /* Look to see if normalization is finished. */
+ if(Dbl_isone_hidden(resultp1))
+ {
+ if(result_exponent==0)
+ {
+ /* Denormalized, exponent should be zero. Left operand *
+ * was normalized, so extent (guard, round) was zero */
+ goto underflow;
+ }
+ else
+ {
+ /* No further normalization is needed. */
+ Dbl_set_sign(resultp1,/*using*/sign_save);
+ Ext_leftshiftby1(extent);
+ goto round;
+ }
+ }
+
+ /* Check for denormalized, exponent should be zero. Left *
+ * operand was normalized, so extent (guard, round) was zero */
+ if(!(underflowtrap = Is_underflowtrap_enabled()) &&
+ result_exponent==0) goto underflow;
+
+ /* Shift extension to complete one bit of normalization and
+ * update exponent. */
+ Ext_leftshiftby1(extent);
+
+ /* Discover first one bit to determine shift amount. Use a
+ * modified binary search. We have already shifted the result
+ * one position right and still not found a one so the remainder
+ * of the extension must be zero and simplifies rounding. */
+ /* Scan bytes */
+ while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
+ {
+ Dbl_leftshiftby8(resultp1,resultp2);
+ if((result_exponent -= 8) <= 0 && !underflowtrap)
+ goto underflow;
+ }
+ /* Now narrow it down to the nibble */
+ if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
+ {
+ /* The lower nibble contains the normalizing one */
+ Dbl_leftshiftby4(resultp1,resultp2);
+ if((result_exponent -= 4) <= 0 && !underflowtrap)
+ goto underflow;
+ }
+ /* Select case were first bit is set (already normalized)
+ * otherwise select the proper shift. */
+ if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
+ {
+ /* Already normalized */
+ if(result_exponent <= 0) goto underflow;
+ Dbl_set_sign(resultp1,/*using*/sign_save);
+ Dbl_set_exponent(resultp1,/*using*/result_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ Dbl_sethigh4bits(resultp1,/*using*/sign_save);
+ switch(jumpsize)
+ {
+ case 1:
+ {
+ Dbl_leftshiftby3(resultp1,resultp2);
+ result_exponent -= 3;
+ break;
+ }
+ case 2:
+ case 3:
+ {
+ Dbl_leftshiftby2(resultp1,resultp2);
+ result_exponent -= 2;
+ break;
+ }
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ {
+ Dbl_leftshiftby1(resultp1,resultp2);
+ result_exponent -= 1;
+ break;
+ }
+ }
+ if(result_exponent > 0)
+ {
+ Dbl_set_exponent(resultp1,/*using*/result_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION); /* Sign bit is already set */
+ }
+ /* Fixup potential underflows */
+ underflow:
+ if(Is_underflowtrap_enabled())
+ {
+ Dbl_set_sign(resultp1,sign_save);
+ Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ /*
+ * Since we cannot get an inexact denormalized result,
+ * we can now return.
+ */
+ Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
+ Dbl_clear_signexponent(resultp1);
+ Dbl_set_sign(resultp1,sign_save);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ } /* end if(hidden...)... */
+ /* Fall through and round */
+ } /* end if(save < 0)... */
+ else
+ {
+ /* Add magnitudes */
+ Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
+ if(Dbl_isone_hiddenoverflow(resultp1))
+ {
+ /* Prenormalization required. */
+ Dbl_rightshiftby1_withextent(resultp2,extent,extent);
+ Dbl_arithrightshiftby1(resultp1,resultp2);
+ result_exponent++;
+ } /* end if hiddenoverflow... */
+ } /* end else ...add magnitudes... */
+
+ /* Round the result. If the extension is all zeros,then the result is
+ * exact. Otherwise round in the correct direction. No underflow is
+ * possible. If a postnormalization is necessary, then the mantissa is
+ * all zeros so no shift is needed. */
+ round:
+ if(Ext_isnotzero(extent))
+ {
+ inexact = TRUE;
+ switch(Rounding_mode())
+ {
+ case ROUNDNEAREST: /* The default. */
+ if(Ext_isone_sign(extent))
+ {
+ /* at least 1/2 ulp */
+ if(Ext_isnotzero_lower(extent) ||
+ Dbl_isone_lowmantissap2(resultp2))
+ {
+ /* either exactly half way and odd or more than 1/2ulp */
+ Dbl_increment(resultp1,resultp2);
+ }
+ }
+ break;
+
+ case ROUNDPLUS:
+ if(Dbl_iszero_sign(resultp1))
+ {
+ /* Round up positive results */
+ Dbl_increment(resultp1,resultp2);
+ }
+ break;
+
+ case ROUNDMINUS:
+ if(Dbl_isone_sign(resultp1))
+ {
+ /* Round down negative results */
+ Dbl_increment(resultp1,resultp2);
+ }
+
+ case ROUNDZERO:;
+ /* truncate is simple */
+ } /* end switch... */
+ if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
+ }
+ if(result_exponent == DBL_INFINITY_EXPONENT)
+ {
+ /* Overflow */
+ if(Is_overflowtrap_enabled())
+ {
+ Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OVERFLOWEXCEPTION);
+ }
+ else
+ {
+ inexact = TRUE;
+ Set_overflowflag();
+ Dbl_setoverflow(resultp1,resultp2);
+ }
+ }
+ else Dbl_set_exponent(resultp1,result_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if(inexact)
+ if(Is_inexacttrap_enabled())
+ return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/dfcmp.c b/arch/parisc/math-emu/dfcmp.c
new file mode 100644
index 000000000000..59521267ffcc
--- /dev/null
+++ b/arch/parisc/math-emu/dfcmp.c
@@ -0,0 +1,181 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/dfcmp.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * dbl_cmp: compare two values
+ *
+ * External Interfaces:
+ * dbl_fcmp(leftptr, rightptr, cond, status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * dbl_cmp: compare two values
+ */
+int
+dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr,
+ unsigned int cond, unsigned int *status)
+
+ /* The predicate to be tested */
+
+ {
+ register unsigned int leftp1, leftp2, rightp1, rightp2;
+ register int xorresult;
+
+ /* Create local copies of the numbers */
+ Dbl_copyfromptr(leftptr,leftp1,leftp2);
+ Dbl_copyfromptr(rightptr,rightp1,rightp2);
+ /*
+ * Test for NaN
+ */
+ if( (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
+ || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) )
+ {
+ /* Check if a NaN is involved. Signal an invalid exception when
+ * comparing a signaling NaN or when comparing quiet NaNs and the
+ * low bit of the condition is set */
+ if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
+ && Dbl_isnotzero_mantissa(leftp1,leftp2)
+ && (Exception(cond) || Dbl_isone_signaling(leftp1)))
+ ||
+ ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
+ && Dbl_isnotzero_mantissa(rightp1,rightp2)
+ && (Exception(cond) || Dbl_isone_signaling(rightp1))) )
+ {
+ if( Is_invalidtrap_enabled() ) {
+ Set_status_cbit(Unordered(cond));
+ return(INVALIDEXCEPTION);
+ }
+ else Set_invalidflag();
+ Set_status_cbit(Unordered(cond));
+ return(NOEXCEPTION);
+ }
+ /* All the exceptional conditions are handled, now special case
+ NaN compares */
+ else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
+ && Dbl_isnotzero_mantissa(leftp1,leftp2))
+ ||
+ ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
+ && Dbl_isnotzero_mantissa(rightp1,rightp2)) )
+ {
+ /* NaNs always compare unordered. */
+ Set_status_cbit(Unordered(cond));
+ return(NOEXCEPTION);
+ }
+ /* infinities will drop down to the normal compare mechanisms */
+ }
+ /* First compare for unequal signs => less or greater or
+ * special equal case */
+ Dbl_xortointp1(leftp1,rightp1,xorresult);
+ if( xorresult < 0 )
+ {
+ /* left negative => less, left positive => greater.
+ * equal is possible if both operands are zeros. */
+ if( Dbl_iszero_exponentmantissa(leftp1,leftp2)
+ && Dbl_iszero_exponentmantissa(rightp1,rightp2) )
+ {
+ Set_status_cbit(Equal(cond));
+ }
+ else if( Dbl_isone_sign(leftp1) )
+ {
+ Set_status_cbit(Lessthan(cond));
+ }
+ else
+ {
+ Set_status_cbit(Greaterthan(cond));
+ }
+ }
+ /* Signs are the same. Treat negative numbers separately
+ * from the positives because of the reversed sense. */
+ else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2))
+ {
+ Set_status_cbit(Equal(cond));
+ }
+ else if( Dbl_iszero_sign(leftp1) )
+ {
+ /* Positive compare */
+ if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
+ {
+ Set_status_cbit(Lessthan(cond));
+ }
+ else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
+ {
+ Set_status_cbit(Greaterthan(cond));
+ }
+ else
+ {
+ /* Equal first parts. Now we must use unsigned compares to
+ * resolve the two possibilities. */
+ if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) )
+ {
+ Set_status_cbit(Lessthan(cond));
+ }
+ else
+ {
+ Set_status_cbit(Greaterthan(cond));
+ }
+ }
+ }
+ else
+ {
+ /* Negative compare. Signed or unsigned compares
+ * both work the same. That distinction is only
+ * important when the sign bits differ. */
+ if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
+ {
+ Set_status_cbit(Lessthan(cond));
+ }
+ else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
+ {
+ Set_status_cbit(Greaterthan(cond));
+ }
+ else
+ {
+ /* Equal first parts. Now we must use unsigned compares to
+ * resolve the two possibilities. */
+ if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) )
+ {
+ Set_status_cbit(Lessthan(cond));
+ }
+ else
+ {
+ Set_status_cbit(Greaterthan(cond));
+ }
+ }
+ }
+ return(NOEXCEPTION);
+ }
diff --git a/arch/parisc/math-emu/dfdiv.c b/arch/parisc/math-emu/dfdiv.c
new file mode 100644
index 000000000000..d7d4bec0e76f
--- /dev/null
+++ b/arch/parisc/math-emu/dfdiv.c
@@ -0,0 +1,400 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/dfdiv.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Double Precision Floating-point Divide
+ *
+ * External Interfaces:
+ * dbl_fdiv(srcptr1,srcptr2,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * Double Precision Floating-point Divide
+ */
+
+int
+dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
+ dbl_floating_point * dstptr, unsigned int *status)
+{
+ register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
+ register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
+ register int dest_exponent, count;
+ register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+ boolean is_tiny;
+
+ Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
+ Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
+ /*
+ * set sign bit of result
+ */
+ if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
+ Dbl_setnegativezerop1(resultp1);
+ else Dbl_setzerop1(resultp1);
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd1p1)) {
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
+ if (Dbl_isinfinity(opnd2p1,opnd2p2)) {
+ /*
+ * invalid since both operands
+ * are infinity
+ */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd1p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd1p1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd2p1)) {
+ if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+ /*
+ * return zero
+ */
+ Dbl_setzero_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * check for division by zero
+ */
+ if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+ if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
+ /* invalid since both operands are zero */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ if (Is_divisionbyzerotrap_enabled())
+ return(DIVISIONBYZEROEXCEPTION);
+ Set_divisionbyzeroflag();
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate exponent
+ */
+ dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS;
+
+ /*
+ * Generate mantissa
+ */
+ if (Dbl_isnotzero_exponent(opnd1p1)) {
+ /* set hidden bit */
+ Dbl_clear_signexponent_set_hidden(opnd1p1);
+ }
+ else {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ Dbl_setzero_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized, want to normalize */
+ Dbl_clear_signexponent(opnd1p1);
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
+ }
+ /* opnd2 needs to have hidden bit set with msb in hidden bit */
+ if (Dbl_isnotzero_exponent(opnd2p1)) {
+ Dbl_clear_signexponent_set_hidden(opnd2p1);
+ }
+ else {
+ /* is denormalized; want to normalize */
+ Dbl_clear_signexponent(opnd2p1);
+ Dbl_leftshiftby1(opnd2p1,opnd2p2);
+ while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) {
+ dest_exponent+=8;
+ Dbl_leftshiftby8(opnd2p1,opnd2p2);
+ }
+ if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) {
+ dest_exponent+=4;
+ Dbl_leftshiftby4(opnd2p1,opnd2p2);
+ }
+ while (Dbl_iszero_hidden(opnd2p1)) {
+ dest_exponent++;
+ Dbl_leftshiftby1(opnd2p1,opnd2p2);
+ }
+ }
+
+ /* Divide the source mantissas */
+
+ /*
+ * A non-restoring divide algorithm is used.
+ */
+ Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
+ Dbl_setzero(opnd3p1,opnd3p2);
+ for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) {
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ if (Dbl_iszero_sign(opnd1p1)) {
+ Dbl_setone_lowmantissap2(opnd3p2);
+ Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
+ }
+ else {
+ Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2);
+ }
+ }
+ if (count <= DBL_P) {
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ Dbl_setone_lowmantissap2(opnd3p2);
+ Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count));
+ if (Dbl_iszero_hidden(opnd3p1)) {
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ dest_exponent--;
+ }
+ }
+ else {
+ if (Dbl_iszero_hidden(opnd3p1)) {
+ /* need to get one more bit of result */
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ if (Dbl_iszero_sign(opnd1p1)) {
+ Dbl_setone_lowmantissap2(opnd3p2);
+ Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
+ }
+ else {
+ Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
+ }
+ dest_exponent--;
+ }
+ if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE;
+ stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2);
+ }
+ inexact = guardbit | stickybit;
+
+ /*
+ * round result
+ */
+ if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
+ Dbl_clear_signexponent(opnd3p1);
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1))
+ Dbl_increment(opnd3p1,opnd3p2);
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1))
+ Dbl_increment(opnd3p1,opnd3p2);
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Dbl_isone_lowmantissap2(opnd3p2))) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ }
+ }
+ if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
+ }
+ Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
+
+ /*
+ * Test for overflow
+ */
+ if (dest_exponent >= DBL_INFINITY_EXPONENT) {
+ /* trap if OVERFLOWTRAP enabled */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OVERFLOWEXCEPTION);
+ }
+ Set_overflowflag();
+ /* set result to infinity or largest number */
+ Dbl_setoverflow(resultp1,resultp2);
+ inexact = TRUE;
+ }
+ /*
+ * Test for underflow
+ */
+ else if (dest_exponent <= 0) {
+ /* trap if UNDERFLOWTRAP enabled */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(UNDERFLOWEXCEPTION);
+ }
+
+ /* Determine if should set underflow flag */
+ is_tiny = TRUE;
+ if (dest_exponent == 0 && inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1)) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ if (Dbl_isone_hiddenoverflow(opnd3p1))
+ is_tiny = FALSE;
+ Dbl_decrement(opnd3p1,opnd3p2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1)) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ if (Dbl_isone_hiddenoverflow(opnd3p1))
+ is_tiny = FALSE;
+ Dbl_decrement(opnd3p1,opnd3p2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Dbl_isone_lowmantissap2(opnd3p2))) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ if (Dbl_isone_hiddenoverflow(opnd3p1))
+ is_tiny = FALSE;
+ Dbl_decrement(opnd3p1,opnd3p2);
+ }
+ break;
+ }
+ }
+
+ /*
+ * denormalize result or set to signed zero
+ */
+ stickybit = inexact;
+ Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
+ stickybit,inexact);
+
+ /* return rounded number */
+ if (inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1)) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1)) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Dbl_isone_lowmantissap2(opnd3p2))) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ }
+ break;
+ }
+ if (is_tiny) Set_underflowflag();
+ }
+ Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
+ }
+ else Dbl_set_exponent(resultp1,dest_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/dfmpy.c b/arch/parisc/math-emu/dfmpy.c
new file mode 100644
index 000000000000..4380f5a62ad1
--- /dev/null
+++ b/arch/parisc/math-emu/dfmpy.c
@@ -0,0 +1,394 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/dfmpy.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Double Precision Floating-point Multiply
+ *
+ * External Interfaces:
+ * dbl_fmpy(srcptr1,srcptr2,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * Double Precision Floating-point Multiply
+ */
+
+int
+dbl_fmpy(
+ dbl_floating_point *srcptr1,
+ dbl_floating_point *srcptr2,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
+ register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
+ register int dest_exponent, count;
+ register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+ boolean is_tiny;
+
+ Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
+ Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
+
+ /*
+ * set sign bit of result
+ */
+ if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
+ Dbl_setnegativezerop1(resultp1);
+ else Dbl_setzerop1(resultp1);
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd1p1)) {
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
+ if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+ /*
+ * invalid since operands are infinity
+ * and zero
+ */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd1p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd1p1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd2p1)) {
+ if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+ if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
+ /* invalid since operands are zero & infinity */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(opnd2p1,opnd2p2);
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate exponent
+ */
+ dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS;
+
+ /*
+ * Generate mantissa
+ */
+ if (Dbl_isnotzero_exponent(opnd1p1)) {
+ /* set hidden bit */
+ Dbl_clear_signexponent_set_hidden(opnd1p1);
+ }
+ else {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ Dbl_setzero_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized, adjust exponent */
+ Dbl_clear_signexponent(opnd1p1);
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
+ }
+ /* opnd2 needs to have hidden bit set with msb in hidden bit */
+ if (Dbl_isnotzero_exponent(opnd2p1)) {
+ Dbl_clear_signexponent_set_hidden(opnd2p1);
+ }
+ else {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+ Dbl_setzero_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized; want to normalize */
+ Dbl_clear_signexponent(opnd2p1);
+ Dbl_leftshiftby1(opnd2p1,opnd2p2);
+ Dbl_normalize(opnd2p1,opnd2p2,dest_exponent);
+ }
+
+ /* Multiply two source mantissas together */
+
+ /* make room for guard bits */
+ Dbl_leftshiftby7(opnd2p1,opnd2p2);
+ Dbl_setzero(opnd3p1,opnd3p2);
+ /*
+ * Four bits at a time are inspected in each loop, and a
+ * simple shift and add multiply algorithm is used.
+ */
+ for (count=1;count<=DBL_P;count+=4) {
+ stickybit |= Dlow4p2(opnd3p2);
+ Dbl_rightshiftby4(opnd3p1,opnd3p2);
+ if (Dbit28p2(opnd1p2)) {
+ /* Twoword_add should be an ADDC followed by an ADD. */
+ Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29,
+ opnd2p2<<3);
+ }
+ if (Dbit29p2(opnd1p2)) {
+ Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30,
+ opnd2p2<<2);
+ }
+ if (Dbit30p2(opnd1p2)) {
+ Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31,
+ opnd2p2<<1);
+ }
+ if (Dbit31p2(opnd1p2)) {
+ Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2);
+ }
+ Dbl_rightshiftby4(opnd1p1,opnd1p2);
+ }
+ if (Dbit3p1(opnd3p1)==0) {
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ }
+ else {
+ /* result mantissa >= 2. */
+ dest_exponent++;
+ }
+ /* check for denormalized result */
+ while (Dbit3p1(opnd3p1)==0) {
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ dest_exponent--;
+ }
+ /*
+ * check for guard, sticky and inexact bits
+ */
+ stickybit |= Dallp2(opnd3p2) << 25;
+ guardbit = (Dallp2(opnd3p2) << 24) >> 31;
+ inexact = guardbit | stickybit;
+
+ /* align result mantissa */
+ Dbl_rightshiftby8(opnd3p1,opnd3p2);
+
+ /*
+ * round result
+ */
+ if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
+ Dbl_clear_signexponent(opnd3p1);
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1))
+ Dbl_increment(opnd3p1,opnd3p2);
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1))
+ Dbl_increment(opnd3p1,opnd3p2);
+ break;
+ case ROUNDNEAREST:
+ if (guardbit) {
+ if (stickybit || Dbl_isone_lowmantissap2(opnd3p2))
+ Dbl_increment(opnd3p1,opnd3p2);
+ }
+ }
+ if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
+ }
+ Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
+
+ /*
+ * Test for overflow
+ */
+ if (dest_exponent >= DBL_INFINITY_EXPONENT) {
+ /* trap if OVERFLOWTRAP enabled */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return (OVERFLOWEXCEPTION);
+ }
+ inexact = TRUE;
+ Set_overflowflag();
+ /* set result to infinity or largest number */
+ Dbl_setoverflow(resultp1,resultp2);
+ }
+ /*
+ * Test for underflow
+ */
+ else if (dest_exponent <= 0) {
+ /* trap if UNDERFLOWTRAP enabled */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return (UNDERFLOWEXCEPTION);
+ }
+
+ /* Determine if should set underflow flag */
+ is_tiny = TRUE;
+ if (dest_exponent == 0 && inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1)) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ if (Dbl_isone_hiddenoverflow(opnd3p1))
+ is_tiny = FALSE;
+ Dbl_decrement(opnd3p1,opnd3p2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1)) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ if (Dbl_isone_hiddenoverflow(opnd3p1))
+ is_tiny = FALSE;
+ Dbl_decrement(opnd3p1,opnd3p2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Dbl_isone_lowmantissap2(opnd3p2))) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ if (Dbl_isone_hiddenoverflow(opnd3p1))
+ is_tiny = FALSE;
+ Dbl_decrement(opnd3p1,opnd3p2);
+ }
+ break;
+ }
+ }
+
+ /*
+ * denormalize result or set to signed zero
+ */
+ stickybit = inexact;
+ Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
+ stickybit,inexact);
+
+ /* return zero or smallest number */
+ if (inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1)) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1)) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Dbl_isone_lowmantissap2(opnd3p2))) {
+ Dbl_increment(opnd3p1,opnd3p2);
+ }
+ break;
+ }
+ if (is_tiny) Set_underflowflag();
+ }
+ Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
+ }
+ else Dbl_set_exponent(resultp1,dest_exponent);
+ /* check for inexact */
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/dfrem.c b/arch/parisc/math-emu/dfrem.c
new file mode 100644
index 000000000000..b98378534677
--- /dev/null
+++ b/arch/parisc/math-emu/dfrem.c
@@ -0,0 +1,297 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/dfrem.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Double Precision Floating-point Remainder
+ *
+ * External Interfaces:
+ * dbl_frem(srcptr1,srcptr2,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * Double Precision Floating-point Remainder
+ */
+
+int
+dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
+ dbl_floating_point * dstptr, unsigned int *status)
+{
+ register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
+ register unsigned int resultp1, resultp2;
+ register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
+ register boolean roundup = FALSE;
+
+ Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
+ Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
+ /* invalid since first operand is infinity */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd1p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd1p1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
+ if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+ /*
+ * return first operand
+ */
+ Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * check second operand for zero
+ */
+ if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+ /* invalid since second operand is zero */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * get sign of result
+ */
+ resultp1 = opnd1p1;
+
+ /*
+ * check for denormalized operands
+ */
+ if (opnd1_exponent == 0) {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* normalize, then continue */
+ opnd1_exponent = 1;
+ Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
+ }
+ else {
+ Dbl_clear_signexponent_set_hidden(opnd1p1);
+ }
+ if (opnd2_exponent == 0) {
+ /* normalize, then continue */
+ opnd2_exponent = 1;
+ Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
+ }
+ else {
+ Dbl_clear_signexponent_set_hidden(opnd2p1);
+ }
+
+ /* find result exponent and divide step loop count */
+ dest_exponent = opnd2_exponent - 1;
+ stepcount = opnd1_exponent - opnd2_exponent;
+
+ /*
+ * check for opnd1/opnd2 < 1
+ */
+ if (stepcount < 0) {
+ /*
+ * check for opnd1/opnd2 > 1/2
+ *
+ * In this case n will round to 1, so
+ * r = opnd1 - opnd2
+ */
+ if (stepcount == -1 &&
+ Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
+ /* set sign */
+ Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
+ /* align opnd2 with opnd1 */
+ Dbl_leftshiftby1(opnd2p1,opnd2p2);
+ Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
+ opnd2p1,opnd2p2);
+ /* now normalize */
+ while (Dbl_iszero_hidden(opnd2p1)) {
+ Dbl_leftshiftby1(opnd2p1,opnd2p2);
+ dest_exponent--;
+ }
+ Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
+ goto testforunderflow;
+ }
+ /*
+ * opnd1/opnd2 <= 1/2
+ *
+ * In this case n will round to zero, so
+ * r = opnd1
+ */
+ Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
+ dest_exponent = opnd1_exponent;
+ goto testforunderflow;
+ }
+
+ /*
+ * Generate result
+ *
+ * Do iterative subtract until remainder is less than operand 2.
+ */
+ while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
+ if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
+ Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
+ }
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ }
+ /*
+ * Do last subtract, then determine which way to round if remainder
+ * is exactly 1/2 of opnd2
+ */
+ if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
+ Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
+ roundup = TRUE;
+ }
+ if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
+ /* division is exact, remainder is zero */
+ Dbl_setzero_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Check for cases where opnd1/opnd2 < n
+ *
+ * In this case the result's sign will be opposite that of
+ * opnd1. The mantissa also needs some correction.
+ */
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
+ Dbl_invert_sign(resultp1);
+ Dbl_leftshiftby1(opnd2p1,opnd2p2);
+ Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
+ }
+ /* check for remainder being exactly 1/2 of opnd2 */
+ else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
+ Dbl_invert_sign(resultp1);
+ }
+
+ /* normalize result's mantissa */
+ while (Dbl_iszero_hidden(opnd1p1)) {
+ dest_exponent--;
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ }
+ Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
+
+ /*
+ * Test for underflow
+ */
+ testforunderflow:
+ if (dest_exponent <= 0) {
+ /* trap if UNDERFLOWTRAP enabled */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
+ /* frem is always exact */
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(UNDERFLOWEXCEPTION);
+ }
+ /*
+ * denormalize result or set to signed zero
+ */
+ if (dest_exponent >= (1 - DBL_P)) {
+ Dbl_rightshift_exponentmantissa(resultp1,resultp2,
+ 1-dest_exponent);
+ }
+ else {
+ Dbl_setzero_exponentmantissa(resultp1,resultp2);
+ }
+ }
+ else Dbl_set_exponent(resultp1,dest_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/dfsqrt.c b/arch/parisc/math-emu/dfsqrt.c
new file mode 100644
index 000000000000..b6ed1066f1e4
--- /dev/null
+++ b/arch/parisc/math-emu/dfsqrt.c
@@ -0,0 +1,195 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/dfsqrt.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Double Floating-point Square Root
+ *
+ * External Interfaces:
+ * dbl_fsqrt(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * Double Floating-point Square Root
+ */
+
+/*ARGSUSED*/
+unsigned int
+dbl_fsqrt(
+ dbl_floating_point *srcptr,
+ unsigned int *nullptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int srcp1, srcp2, resultp1, resultp2;
+ register unsigned int newbitp1, newbitp2, sump1, sump2;
+ register int src_exponent;
+ register boolean guardbit = FALSE, even_exponent;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ /*
+ * check source operand for NaN or infinity
+ */
+ if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
+ /*
+ * is signaling NaN?
+ */
+ if (Dbl_isone_signaling(srcp1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(srcp1);
+ }
+ /*
+ * Return quiet NaN or positive infinity.
+ * Fall thru to negative test if negative infinity.
+ */
+ if (Dbl_iszero_sign(srcp1) ||
+ Dbl_isnotzero_mantissa(srcp1,srcp2)) {
+ Dbl_copytoptr(srcp1,srcp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check for zero source operand
+ */
+ if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) {
+ Dbl_copytoptr(srcp1,srcp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * check for negative source operand
+ */
+ if (Dbl_isone_sign(srcp1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_makequietnan(srcp1,srcp2);
+ Dbl_copytoptr(srcp1,srcp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Generate result
+ */
+ if (src_exponent > 0) {
+ even_exponent = Dbl_hidden(srcp1);
+ Dbl_clear_signexponent_set_hidden(srcp1);
+ }
+ else {
+ /* normalize operand */
+ Dbl_clear_signexponent(srcp1);
+ src_exponent++;
+ Dbl_normalize(srcp1,srcp2,src_exponent);
+ even_exponent = src_exponent & 1;
+ }
+ if (even_exponent) {
+ /* exponent is even */
+ /* Add comment here. Explain why odd exponent needs correction */
+ Dbl_leftshiftby1(srcp1,srcp2);
+ }
+ /*
+ * Add comment here. Explain following algorithm.
+ *
+ * Trust me, it works.
+ *
+ */
+ Dbl_setzero(resultp1,resultp2);
+ Dbl_allp1(newbitp1) = 1 << (DBL_P - 32);
+ Dbl_setzero_mantissap2(newbitp2);
+ while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) {
+ Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2);
+ if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) {
+ Dbl_leftshiftby1(newbitp1,newbitp2);
+ /* update result */
+ Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,
+ resultp1,resultp2);
+ Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2);
+ Dbl_rightshiftby2(newbitp1,newbitp2);
+ }
+ else {
+ Dbl_rightshiftby1(newbitp1,newbitp2);
+ }
+ Dbl_leftshiftby1(srcp1,srcp2);
+ }
+ /* correct exponent for pre-shift */
+ if (even_exponent) {
+ Dbl_rightshiftby1(resultp1,resultp2);
+ }
+
+ /* check for inexact */
+ if (Dbl_isnotzero(srcp1,srcp2)) {
+ if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) {
+ Dbl_increment(resultp1,resultp2);
+ }
+ guardbit = Dbl_lowmantissap2(resultp2);
+ Dbl_rightshiftby1(resultp1,resultp2);
+
+ /* now round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ Dbl_increment(resultp1,resultp2);
+ break;
+ case ROUNDNEAREST:
+ /* stickybit is always true, so guardbit
+ * is enough to determine rounding */
+ if (guardbit) {
+ Dbl_increment(resultp1,resultp2);
+ }
+ break;
+ }
+ /* increment result exponent by 1 if mantissa overflowed */
+ if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2;
+
+ if (Is_inexacttrap_enabled()) {
+ Dbl_set_exponent(resultp1,
+ ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(INEXACTEXCEPTION);
+ }
+ else Set_inexactflag();
+ }
+ else {
+ Dbl_rightshiftby1(resultp1,resultp2);
+ }
+ Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/dfsub.c b/arch/parisc/math-emu/dfsub.c
new file mode 100644
index 000000000000..87ebc60d465b
--- /dev/null
+++ b/arch/parisc/math-emu/dfsub.c
@@ -0,0 +1,526 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/dfsub.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Double_subtract: subtract two double precision values.
+ *
+ * External Interfaces:
+ * dbl_fsub(leftptr, rightptr, dstptr, status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * Double_subtract: subtract two double precision values.
+ */
+int
+dbl_fsub(
+ dbl_floating_point *leftptr,
+ dbl_floating_point *rightptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+ {
+ register unsigned int signless_upper_left, signless_upper_right, save;
+ register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
+ register unsigned int resultp1 = 0, resultp2 = 0;
+
+ register int result_exponent, right_exponent, diff_exponent;
+ register int sign_save, jumpsize;
+ register boolean inexact = FALSE, underflowtrap;
+
+ /* Create local copies of the numbers */
+ Dbl_copyfromptr(leftptr,leftp1,leftp2);
+ Dbl_copyfromptr(rightptr,rightp1,rightp2);
+
+ /* A zero "save" helps discover equal operands (for later), *
+ * and is used in swapping operands (if needed). */
+ Dbl_xortointp1(leftp1,rightp1,/*to*/save);
+
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
+ {
+ if (Dbl_iszero_mantissa(leftp1,leftp2))
+ {
+ if (Dbl_isnotnan(rightp1,rightp2))
+ {
+ if (Dbl_isinfinity(rightp1,rightp2) && save==0)
+ {
+ /*
+ * invalid since operands are same signed infinity's
+ */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ Dbl_copytoptr(leftp1,leftp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else
+ {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(leftp1))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(leftp1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(rightp1))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(rightp1);
+ Dbl_copytoptr(rightp1,rightp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(leftp1,leftp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ } /* End left NaN or Infinity processing */
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(rightp1))
+ {
+ if (Dbl_iszero_mantissa(rightp1,rightp2))
+ {
+ /* return infinity */
+ Dbl_invert_sign(rightp1);
+ Dbl_copytoptr(rightp1,rightp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(rightp1))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(rightp1);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(rightp1,rightp2,dstptr);
+ return(NOEXCEPTION);
+ } /* End right NaN or Infinity processing */
+
+ /* Invariant: Must be dealing with finite numbers */
+
+ /* Compare operands by removing the sign */
+ Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
+ Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
+
+ /* sign difference selects add or sub operation. */
+ if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
+ {
+ /* Set the left operand to the larger one by XOR swap *
+ * First finish the first word using "save" */
+ Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
+ Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
+ Dbl_swap_lower(leftp2,rightp2);
+ result_exponent = Dbl_exponent(leftp1);
+ Dbl_invert_sign(leftp1);
+ }
+ /* Invariant: left is not smaller than right. */
+
+ if((right_exponent = Dbl_exponent(rightp1)) == 0)
+ {
+ /* Denormalized operands. First look for zeroes */
+ if(Dbl_iszero_mantissa(rightp1,rightp2))
+ {
+ /* right is zero */
+ if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
+ {
+ /* Both operands are zeros */
+ Dbl_invert_sign(rightp1);
+ if(Is_rounding_mode(ROUNDMINUS))
+ {
+ Dbl_or_signs(leftp1,/*with*/rightp1);
+ }
+ else
+ {
+ Dbl_and_signs(leftp1,/*with*/rightp1);
+ }
+ }
+ else
+ {
+ /* Left is not a zero and must be the result. Trapped
+ * underflows are signaled if left is denormalized. Result
+ * is always exact. */
+ if( (result_exponent == 0) && Is_underflowtrap_enabled() )
+ {
+ /* need to normalize results mantissa */
+ sign_save = Dbl_signextendedsign(leftp1);
+ Dbl_leftshiftby1(leftp1,leftp2);
+ Dbl_normalize(leftp1,leftp2,result_exponent);
+ Dbl_set_sign(leftp1,/*using*/sign_save);
+ Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
+ Dbl_copytoptr(leftp1,leftp2,dstptr);
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ }
+ Dbl_copytoptr(leftp1,leftp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /* Neither are zeroes */
+ Dbl_clear_sign(rightp1); /* Exponent is already cleared */
+ if(result_exponent == 0 )
+ {
+ /* Both operands are denormalized. The result must be exact
+ * and is simply calculated. A sum could become normalized and a
+ * difference could cancel to a true zero. */
+ if( (/*signed*/int) save >= 0 )
+ {
+ Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
+ /*into*/resultp1,resultp2);
+ if(Dbl_iszero_mantissa(resultp1,resultp2))
+ {
+ if(Is_rounding_mode(ROUNDMINUS))
+ {
+ Dbl_setone_sign(resultp1);
+ }
+ else
+ {
+ Dbl_setzero_sign(resultp1);
+ }
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else
+ {
+ Dbl_addition(leftp1,leftp2,rightp1,rightp2,
+ /*into*/resultp1,resultp2);
+ if(Dbl_isone_hidden(resultp1))
+ {
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ if(Is_underflowtrap_enabled())
+ {
+ /* need to normalize result */
+ sign_save = Dbl_signextendedsign(resultp1);
+ Dbl_leftshiftby1(resultp1,resultp2);
+ Dbl_normalize(resultp1,resultp2,result_exponent);
+ Dbl_set_sign(resultp1,/*using*/sign_save);
+ Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ right_exponent = 1; /* Set exponent to reflect different bias
+ * with denomalized numbers. */
+ }
+ else
+ {
+ Dbl_clear_signexponent_set_hidden(rightp1);
+ }
+ Dbl_clear_exponent_set_hidden(leftp1);
+ diff_exponent = result_exponent - right_exponent;
+
+ /*
+ * Special case alignment of operands that would force alignment
+ * beyond the extent of the extension. A further optimization
+ * could special case this but only reduces the path length for this
+ * infrequent case.
+ */
+ if(diff_exponent > DBL_THRESHOLD)
+ {
+ diff_exponent = DBL_THRESHOLD;
+ }
+
+ /* Align right operand by shifting to right */
+ Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
+ /*and lower to*/extent);
+
+ /* Treat sum and difference of the operands separately. */
+ if( (/*signed*/int) save >= 0 )
+ {
+ /*
+ * Difference of the two operands. Their can be no overflow. A
+ * borrow can occur out of the hidden bit and force a post
+ * normalization phase.
+ */
+ Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
+ /*with*/extent,/*into*/resultp1,resultp2);
+ if(Dbl_iszero_hidden(resultp1))
+ {
+ /* Handle normalization */
+ /* A straight foward algorithm would now shift the result
+ * and extension left until the hidden bit becomes one. Not
+ * all of the extension bits need participate in the shift.
+ * Only the two most significant bits (round and guard) are
+ * needed. If only a single shift is needed then the guard
+ * bit becomes a significant low order bit and the extension
+ * must participate in the rounding. If more than a single
+ * shift is needed, then all bits to the right of the guard
+ * bit are zeros, and the guard bit may or may not be zero. */
+ sign_save = Dbl_signextendedsign(resultp1);
+ Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
+
+ /* Need to check for a zero result. The sign and exponent
+ * fields have already been zeroed. The more efficient test
+ * of the full object can be used.
+ */
+ if(Dbl_iszero(resultp1,resultp2))
+ /* Must have been "x-x" or "x+(-x)". */
+ {
+ if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ result_exponent--;
+ /* Look to see if normalization is finished. */
+ if(Dbl_isone_hidden(resultp1))
+ {
+ if(result_exponent==0)
+ {
+ /* Denormalized, exponent should be zero. Left operand *
+ * was normalized, so extent (guard, round) was zero */
+ goto underflow;
+ }
+ else
+ {
+ /* No further normalization is needed. */
+ Dbl_set_sign(resultp1,/*using*/sign_save);
+ Ext_leftshiftby1(extent);
+ goto round;
+ }
+ }
+
+ /* Check for denormalized, exponent should be zero. Left *
+ * operand was normalized, so extent (guard, round) was zero */
+ if(!(underflowtrap = Is_underflowtrap_enabled()) &&
+ result_exponent==0) goto underflow;
+
+ /* Shift extension to complete one bit of normalization and
+ * update exponent. */
+ Ext_leftshiftby1(extent);
+
+ /* Discover first one bit to determine shift amount. Use a
+ * modified binary search. We have already shifted the result
+ * one position right and still not found a one so the remainder
+ * of the extension must be zero and simplifies rounding. */
+ /* Scan bytes */
+ while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
+ {
+ Dbl_leftshiftby8(resultp1,resultp2);
+ if((result_exponent -= 8) <= 0 && !underflowtrap)
+ goto underflow;
+ }
+ /* Now narrow it down to the nibble */
+ if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
+ {
+ /* The lower nibble contains the normalizing one */
+ Dbl_leftshiftby4(resultp1,resultp2);
+ if((result_exponent -= 4) <= 0 && !underflowtrap)
+ goto underflow;
+ }
+ /* Select case were first bit is set (already normalized)
+ * otherwise select the proper shift. */
+ if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
+ {
+ /* Already normalized */
+ if(result_exponent <= 0) goto underflow;
+ Dbl_set_sign(resultp1,/*using*/sign_save);
+ Dbl_set_exponent(resultp1,/*using*/result_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ Dbl_sethigh4bits(resultp1,/*using*/sign_save);
+ switch(jumpsize)
+ {
+ case 1:
+ {
+ Dbl_leftshiftby3(resultp1,resultp2);
+ result_exponent -= 3;
+ break;
+ }
+ case 2:
+ case 3:
+ {
+ Dbl_leftshiftby2(resultp1,resultp2);
+ result_exponent -= 2;
+ break;
+ }
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ {
+ Dbl_leftshiftby1(resultp1,resultp2);
+ result_exponent -= 1;
+ break;
+ }
+ }
+ if(result_exponent > 0)
+ {
+ Dbl_set_exponent(resultp1,/*using*/result_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION); /* Sign bit is already set */
+ }
+ /* Fixup potential underflows */
+ underflow:
+ if(Is_underflowtrap_enabled())
+ {
+ Dbl_set_sign(resultp1,sign_save);
+ Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ /*
+ * Since we cannot get an inexact denormalized result,
+ * we can now return.
+ */
+ Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
+ Dbl_clear_signexponent(resultp1);
+ Dbl_set_sign(resultp1,sign_save);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ } /* end if(hidden...)... */
+ /* Fall through and round */
+ } /* end if(save >= 0)... */
+ else
+ {
+ /* Subtract magnitudes */
+ Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
+ if(Dbl_isone_hiddenoverflow(resultp1))
+ {
+ /* Prenormalization required. */
+ Dbl_rightshiftby1_withextent(resultp2,extent,extent);
+ Dbl_arithrightshiftby1(resultp1,resultp2);
+ result_exponent++;
+ } /* end if hiddenoverflow... */
+ } /* end else ...subtract magnitudes... */
+
+ /* Round the result. If the extension is all zeros,then the result is
+ * exact. Otherwise round in the correct direction. No underflow is
+ * possible. If a postnormalization is necessary, then the mantissa is
+ * all zeros so no shift is needed. */
+ round:
+ if(Ext_isnotzero(extent))
+ {
+ inexact = TRUE;
+ switch(Rounding_mode())
+ {
+ case ROUNDNEAREST: /* The default. */
+ if(Ext_isone_sign(extent))
+ {
+ /* at least 1/2 ulp */
+ if(Ext_isnotzero_lower(extent) ||
+ Dbl_isone_lowmantissap2(resultp2))
+ {
+ /* either exactly half way and odd or more than 1/2ulp */
+ Dbl_increment(resultp1,resultp2);
+ }
+ }
+ break;
+
+ case ROUNDPLUS:
+ if(Dbl_iszero_sign(resultp1))
+ {
+ /* Round up positive results */
+ Dbl_increment(resultp1,resultp2);
+ }
+ break;
+
+ case ROUNDMINUS:
+ if(Dbl_isone_sign(resultp1))
+ {
+ /* Round down negative results */
+ Dbl_increment(resultp1,resultp2);
+ }
+
+ case ROUNDZERO:;
+ /* truncate is simple */
+ } /* end switch... */
+ if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
+ }
+ if(result_exponent == DBL_INFINITY_EXPONENT)
+ {
+ /* Overflow */
+ if(Is_overflowtrap_enabled())
+ {
+ Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OVERFLOWEXCEPTION);
+ }
+ else
+ {
+ inexact = TRUE;
+ Set_overflowflag();
+ Dbl_setoverflow(resultp1,resultp2);
+ }
+ }
+ else Dbl_set_exponent(resultp1,result_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if(inexact)
+ if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+ }
diff --git a/arch/parisc/math-emu/driver.c b/arch/parisc/math-emu/driver.c
new file mode 100644
index 000000000000..09ef4136c693
--- /dev/null
+++ b/arch/parisc/math-emu/driver.c
@@ -0,0 +1,128 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * linux/arch/math-emu/driver.c.c
+ *
+ * decodes and dispatches unimplemented FPU instructions
+ *
+ * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2001 Hewlett-Packard <bame@debian.org>
+ */
+
+#include <linux/sched.h>
+#include "float.h"
+#include "math-emu.h"
+
+
+#define fptpos 31
+#define fpr1pos 10
+#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
+
+#define FPUDEBUG 0
+
+/* Format of the floating-point exception registers. */
+struct exc_reg {
+ unsigned int exception : 6;
+ unsigned int ei : 26;
+};
+
+/* Macros for grabbing bits of the instruction format from the 'ei'
+ field above. */
+/* Major opcode 0c and 0e */
+#define FP0CE_UID(i) (((i) >> 6) & 3)
+#define FP0CE_CLASS(i) (((i) >> 9) & 3)
+#define FP0CE_SUBOP(i) (((i) >> 13) & 7)
+#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
+#define FP0C_FORMAT(i) (((i) >> 11) & 3)
+#define FP0E_FORMAT(i) (((i) >> 11) & 1)
+
+/* Major opcode 0c, uid 2 (performance monitoring) */
+#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
+
+/* Major opcode 2e (fused operations). */
+#define FP2E_SUBOP(i) (((i) >> 5) & 1)
+#define FP2E_FORMAT(i) (((i) >> 11) & 1)
+
+/* Major opcode 26 (FMPYSUB) */
+/* Major opcode 06 (FMPYADD) */
+#define FPx6_FORMAT(i) ((i) & 0x1f)
+
+/* Flags and enable bits of the status word. */
+#define FPSW_FLAGS(w) ((w) >> 27)
+#define FPSW_ENABLE(w) ((w) & 0x1f)
+#define FPSW_V (1<<4)
+#define FPSW_Z (1<<3)
+#define FPSW_O (1<<2)
+#define FPSW_U (1<<1)
+#define FPSW_I (1<<0)
+
+/* Handle a floating point exception. Return zero if the faulting
+ instruction can be completed successfully. */
+int
+handle_fpe(struct pt_regs *regs)
+{
+ extern void printbinary(unsigned long x, int nbits);
+ struct siginfo si;
+ unsigned int orig_sw, sw;
+ int signalcode;
+ /* need an intermediate copy of float regs because FPU emulation
+ * code expects an artificial last entry which contains zero
+ *
+ * also, the passed in fr registers contain one word that defines
+ * the fpu type. the fpu type information is constructed
+ * inside the emulation code
+ */
+ __u64 frcopy[36];
+
+ memcpy(frcopy, regs->fr, sizeof regs->fr);
+ frcopy[32] = 0;
+
+ memcpy(&orig_sw, frcopy, sizeof(orig_sw));
+
+ if (FPUDEBUG) {
+ printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n ");
+ printbinary(orig_sw, 32);
+ printk(KERN_DEBUG "\n");
+ }
+
+ signalcode = decode_fpu(frcopy, 0x666);
+
+ /* Status word = FR0L. */
+ memcpy(&sw, frcopy, sizeof(sw));
+ if (FPUDEBUG) {
+ printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n",
+ signalcode >> 24, signalcode & 0xffffff);
+ printbinary(sw, 32);
+ printk(KERN_DEBUG "\n");
+ }
+
+ memcpy(regs->fr, frcopy, sizeof regs->fr);
+ if (signalcode != 0) {
+ si.si_signo = signalcode >> 24;
+ si.si_errno = 0;
+ si.si_code = signalcode & 0xffffff;
+ si.si_addr = (void __user *) regs->iaoq[0];
+ force_sig_info(si.si_signo, &si, current);
+ return -1;
+ }
+
+ return signalcode ? -1 : 0;
+}
diff --git a/arch/parisc/math-emu/fcnvff.c b/arch/parisc/math-emu/fcnvff.c
new file mode 100644
index 000000000000..76c063f7d17c
--- /dev/null
+++ b/arch/parisc/math-emu/fcnvff.c
@@ -0,0 +1,309 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/fcnvff.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single Floating-point to Double Floating-point
+ * Double Floating-point to Single Floating-point
+ *
+ * External Interfaces:
+ * dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status)
+ * sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ * Single Floating-point to Double Floating-point
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvff(
+ sgl_floating_point *srcptr,
+ unsigned int *nullptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int src, resultp1, resultp2;
+ register int src_exponent;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src);
+ Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */
+ /*
+ * Test for NaN or infinity
+ */
+ if (src_exponent == SGL_INFINITY_EXPONENT) {
+ /*
+ * determine if NaN or infinity
+ */
+ if (Sgl_iszero_mantissa(src)) {
+ /*
+ * is infinity; want to return double infinity
+ */
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(src)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ else {
+ Set_invalidflag();
+ Sgl_set_quiet(src);
+ }
+ }
+ /*
+ * NaN is quiet, return as double NaN
+ */
+ Dbl_setinfinity_exponent(resultp1);
+ Sgl_to_dbl_mantissa(src,resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Test for zero or denormalized
+ */
+ if (src_exponent == 0) {
+ /*
+ * determine if zero or denormalized
+ */
+ if (Sgl_isnotzero_mantissa(src)) {
+ /*
+ * is denormalized; want to normalize
+ */
+ Sgl_clear_signexponent(src);
+ Sgl_leftshiftby1(src);
+ Sgl_normalize(src,src_exponent);
+ Sgl_to_dbl_exponent(src_exponent,resultp1);
+ Sgl_to_dbl_mantissa(src,resultp1,resultp2);
+ }
+ else {
+ Dbl_setzero_exponentmantissa(resultp1,resultp2);
+ }
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * No special cases, just complete the conversion
+ */
+ Sgl_to_dbl_exponent(src_exponent, resultp1);
+ Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Single Floating-point
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvff(
+ dbl_floating_point *srcptr,
+ unsigned int *nullptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int srcp1, srcp2, result;
+ register int src_exponent, dest_exponent, dest_mantissa;
+ register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+ register boolean lsb_odd = FALSE;
+ boolean is_tiny;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1);
+ Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */
+ /*
+ * Test for NaN or infinity
+ */
+ if (src_exponent == DBL_INFINITY_EXPONENT) {
+ /*
+ * determine if NaN or infinity
+ */
+ if (Dbl_iszero_mantissa(srcp1,srcp2)) {
+ /*
+ * is infinity; want to return single infinity
+ */
+ Sgl_setinfinity_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(srcp1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ else {
+ Set_invalidflag();
+ /* make NaN quiet */
+ Dbl_set_quiet(srcp1);
+ }
+ }
+ /*
+ * NaN is quiet, return as single NaN
+ */
+ Sgl_setinfinity_exponent(result);
+ Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
+ if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ Dbl_to_sgl_exponent(src_exponent,dest_exponent);
+ if (dest_exponent > 0) {
+ Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
+ stickybit,lsb_odd);
+ }
+ else {
+ if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
+ Sgl_setzero_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ if (Is_underflowtrap_enabled()) {
+ Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
+ guardbit,stickybit,lsb_odd);
+ }
+ else {
+ /* compute result, determine inexact info,
+ * and set Underflowflag if appropriate
+ */
+ Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
+ dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
+ is_tiny);
+ }
+ }
+ /*
+ * Now round result if not exact
+ */
+ if (inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result)) dest_mantissa++;
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result)) dest_mantissa++;
+ break;
+ case ROUNDNEAREST:
+ if (guardbit) {
+ if (stickybit || lsb_odd) dest_mantissa++;
+ }
+ }
+ }
+ Sgl_set_exponentmantissa(result,dest_mantissa);
+
+ /*
+ * check for mantissa overflow after rounding
+ */
+ if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
+ Sgl_isone_hidden(result)) dest_exponent++;
+
+ /*
+ * Test for overflow
+ */
+ if (dest_exponent >= SGL_INFINITY_EXPONENT) {
+ /* trap if OVERFLOWTRAP enabled */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Check for gross overflow
+ */
+ if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
+ return(UNIMPLEMENTEDEXCEPTION);
+
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
+ *dstptr = result;
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OVERFLOWEXCEPTION);
+ }
+ Set_overflowflag();
+ inexact = TRUE;
+ /* set result to infinity or largest number */
+ Sgl_setoverflow(result);
+ }
+ /*
+ * Test for underflow
+ */
+ else if (dest_exponent <= 0) {
+ /* trap if UNDERFLOWTRAP enabled */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Check for gross underflow
+ */
+ if (dest_exponent <= -(SGL_WRAP))
+ return(UNIMPLEMENTEDEXCEPTION);
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(result,dest_exponent,unfl);
+ *dstptr = result;
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(UNDERFLOWEXCEPTION);
+ }
+ /*
+ * result is denormalized or signed zero
+ */
+ if (inexact && is_tiny) Set_underflowflag();
+
+ }
+ else Sgl_set_exponent(result,dest_exponent);
+ *dstptr = result;
+ /*
+ * Trap if inexact trap is enabled
+ */
+ if (inexact)
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/fcnvfu.c b/arch/parisc/math-emu/fcnvfu.c
new file mode 100644
index 000000000000..7e8565537bf5
--- /dev/null
+++ b/arch/parisc/math-emu/fcnvfu.c
@@ -0,0 +1,536 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Floating-point to Unsigned Fixed-point Converts
+ *
+ * External Interfaces:
+ * dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
+ * dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
+ * sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
+ * sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/************************************************************************
+ * Floating-point to Unsigned Fixed-point Converts *
+ ************************************************************************/
+
+/*
+ * Single Floating-point to Single Unsigned Fixed
+ */
+/*ARGSUSED*/
+int
+sgl_to_sgl_fcnvfu(
+ sgl_floating_point *srcptr,
+ unsigned int *nullptr,
+ unsigned int *dstptr,
+ unsigned int *status)
+{
+ register unsigned int src, result;
+ register int src_exponent;
+ register boolean inexact = FALSE;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > SGL_FX_MAX_EXP + 1) {
+ if (Sgl_isone_sign(src)) {
+ result = 0;
+ } else {
+ result = 0xffffffff;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ /*
+ * Check sign.
+ * If negative, trap unimplemented.
+ */
+ if (Sgl_isone_sign(src)) {
+ result = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ Sgl_clear_signexponent_set_hidden(src);
+ Suint_from_sgl_mantissa(src,src_exponent,result);
+
+ /* check for inexact */
+ if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ result++;
+ break;
+ case ROUNDMINUS: /* never negative */
+ break;
+ case ROUNDNEAREST:
+ if (Sgl_isone_roundbit(src,src_exponent) &&
+ (Sgl_isone_stickybit(src,src_exponent) ||
+ (result & 1))) {
+ result++;
+ }
+ break;
+ }
+ }
+ } else {
+ result = 0;
+
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(src)) {
+ result++;
+ }
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(src)) {
+ result = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ inexact = FALSE;
+ }
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1 &&
+ Sgl_isnotzero_mantissa(src)) {
+ if (Sgl_isone_sign(src)) {
+ result = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ inexact = FALSE;
+ }
+ else result++;
+ }
+ break;
+ }
+ }
+ }
+ *dstptr = result;
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Single Floating-point to Double Unsigned Fixed
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvfu(
+ sgl_floating_point *srcptr,
+ unsigned int *nullptr,
+ dbl_unsigned *dstptr,
+ unsigned int *status)
+{
+ register int src_exponent;
+ register unsigned int src, resultp1, resultp2;
+ register boolean inexact = FALSE;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > DBL_FX_MAX_EXP + 1) {
+ if (Sgl_isone_sign(src)) {
+ resultp1 = resultp2 = 0;
+ } else {
+ resultp1 = resultp2 = 0xffffffff;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ /*
+ * Check sign.
+ * If negative, trap unimplemented.
+ */
+ if (Sgl_isone_sign(src)) {
+ resultp1 = resultp2 = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ Sgl_clear_signexponent_set_hidden(src);
+ Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
+
+ /* check for inexact */
+ if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ Duint_increment(resultp1,resultp2);
+ break;
+ case ROUNDMINUS: /* never negative */
+ break;
+ case ROUNDNEAREST:
+ if (Sgl_isone_roundbit(src,src_exponent) &&
+ (Sgl_isone_stickybit(src,src_exponent) ||
+ Duint_isone_lowp2(resultp2))) {
+ Duint_increment(resultp1,resultp2);
+ }
+ break;
+ }
+ }
+ } else {
+ Duint_setzero(resultp1,resultp2);
+
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(src)) {
+ Duint_increment(resultp1,resultp2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(src)) {
+ resultp1 = resultp2 = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ inexact = FALSE;
+ }
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1 &&
+ Sgl_isnotzero_mantissa(src)) {
+ if (Sgl_isone_sign(src)) {
+ resultp1 = 0;
+ resultp2 = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ inexact = FALSE;
+ }
+ else Duint_increment(resultp1,resultp2);
+ }
+ }
+ }
+ }
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Single Unsigned Fixed
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
+ unsigned int *dstptr, unsigned int *status)
+{
+ register unsigned int srcp1, srcp2, result;
+ register int src_exponent;
+ register boolean inexact = FALSE;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > SGL_FX_MAX_EXP + 1) {
+ if (Dbl_isone_sign(srcp1)) {
+ result = 0;
+ } else {
+ result = 0xffffffff;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ /*
+ * Check sign.
+ * If negative, trap unimplemented.
+ */
+ if (Dbl_isone_sign(srcp1)) {
+ result = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ Dbl_clear_signexponent_set_hidden(srcp1);
+ Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
+
+ /* check for inexact */
+ if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ result++;
+ break;
+ case ROUNDMINUS: /* never negative */
+ break;
+ case ROUNDNEAREST:
+ if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
+ (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
+ result&1))
+ result++;
+ break;
+ }
+ /* check for overflow */
+ if (result == 0) {
+ result = 0xffffffff;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ } else {
+ result = 0;
+
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(srcp1)) result++;
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(srcp1)) {
+ result = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ inexact = FALSE;
+ }
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1 &&
+ Dbl_isnotzero_mantissa(srcp1,srcp2))
+ if (Dbl_isone_sign(srcp1)) {
+ result = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ inexact = FALSE;
+ }
+ else result++;
+ }
+ }
+ }
+ *dstptr = result;
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Double Unsigned Fixed
+ */
+/*ARGSUSED*/
+int
+dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
+ dbl_unsigned * dstptr, unsigned int *status)
+{
+ register int src_exponent;
+ register unsigned int srcp1, srcp2, resultp1, resultp2;
+ register boolean inexact = FALSE;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > DBL_FX_MAX_EXP + 1) {
+ if (Dbl_isone_sign(srcp1)) {
+ resultp1 = resultp2 = 0;
+ } else {
+ resultp1 = resultp2 = 0xffffffff;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ /*
+ * Check sign.
+ * If negative, trap unimplemented.
+ */
+ if (Dbl_isone_sign(srcp1)) {
+ resultp1 = resultp2 = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ Dbl_clear_signexponent_set_hidden(srcp1);
+ Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
+ resultp2);
+
+ /* check for inexact */
+ if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ Duint_increment(resultp1,resultp2);
+ break;
+ case ROUNDMINUS: /* never negative */
+ break;
+ case ROUNDNEAREST:
+ if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
+ if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
+ Duint_isone_lowp2(resultp2))
+ Duint_increment(resultp1,resultp2);
+ }
+ }
+ } else {
+ Duint_setzero(resultp1,resultp2);
+
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(srcp1)) {
+ Duint_increment(resultp1,resultp2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(srcp1)) {
+ resultp1 = resultp2 = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ inexact = FALSE;
+ }
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1 &&
+ Dbl_isnotzero_mantissa(srcp1,srcp2))
+ if (Dbl_iszero_sign(srcp1)) {
+ Duint_increment(resultp1,resultp2);
+ } else {
+ resultp1 = 0;
+ resultp2 = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ inexact = FALSE;
+ }
+ }
+ }
+ }
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
+
diff --git a/arch/parisc/math-emu/fcnvfut.c b/arch/parisc/math-emu/fcnvfut.c
new file mode 100644
index 000000000000..4176a44ed750
--- /dev/null
+++ b/arch/parisc/math-emu/fcnvfut.c
@@ -0,0 +1,332 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/fcnvfut.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Floating-point to Unsigned Fixed-point Converts with Truncation
+ *
+ * External Interfaces:
+ * dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
+ * dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
+ * sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
+ * sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/************************************************************************
+ * Floating-point to Unsigned Fixed-point Converts with Truncation *
+ ************************************************************************/
+
+/*
+ * Convert single floating-point to single fixed-point format
+ * with truncated result
+ */
+/*ARGSUSED*/
+int
+sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
+ unsigned int *dstptr, unsigned int *status)
+{
+ register unsigned int src, result;
+ register int src_exponent;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > SGL_FX_MAX_EXP + 1) {
+ if (Sgl_isone_sign(src)) {
+ result = 0;
+ } else {
+ result = 0xffffffff;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ /*
+ * Check sign.
+ * If negative, trap unimplemented.
+ */
+ if (Sgl_isone_sign(src)) {
+ result = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ Sgl_clear_signexponent_set_hidden(src);
+ Suint_from_sgl_mantissa(src,src_exponent,result);
+ *dstptr = result;
+
+ /* check for inexact */
+ if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ else {
+ *dstptr = 0;
+
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Single Floating-point to Double Unsigned Fixed
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
+ dbl_unsigned * dstptr, unsigned int *status)
+{
+ register int src_exponent;
+ register unsigned int src, resultp1, resultp2;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > DBL_FX_MAX_EXP + 1) {
+ if (Sgl_isone_sign(src)) {
+ resultp1 = resultp2 = 0;
+ } else {
+ resultp1 = resultp2 = 0xffffffff;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ /*
+ * Check sign.
+ * If negative, trap unimplemented.
+ */
+ if (Sgl_isone_sign(src)) {
+ resultp1 = resultp2 = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ Sgl_clear_signexponent_set_hidden(src);
+ Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ else {
+ Duint_setzero(resultp1,resultp2);
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Single Unsigned Fixed
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
+ unsigned int *dstptr, unsigned int *status)
+{
+ register unsigned int srcp1, srcp2, result;
+ register int src_exponent;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > SGL_FX_MAX_EXP + 1) {
+ if (Dbl_isone_sign(srcp1)) {
+ result = 0;
+ } else {
+ result = 0xffffffff;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ /*
+ * Check sign.
+ * If negative, trap unimplemented.
+ */
+ if (Dbl_isone_sign(srcp1)) {
+ result = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ Dbl_clear_signexponent_set_hidden(srcp1);
+ Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
+ *dstptr = result;
+
+ /* check for inexact */
+ if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ else {
+ *dstptr = 0;
+
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Double Unsigned Fixed
+ */
+/*ARGSUSED*/
+int
+dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
+ dbl_unsigned * dstptr, unsigned int *status)
+{
+ register int src_exponent;
+ register unsigned int srcp1, srcp2, resultp1, resultp2;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > DBL_FX_MAX_EXP + 1) {
+ if (Dbl_isone_sign(srcp1)) {
+ resultp1 = resultp2 = 0;
+ } else {
+ resultp1 = resultp2 = 0xffffffff;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ /*
+ * Check sign.
+ * If negative, trap unimplemented.
+ */
+ if (Dbl_isone_sign(srcp1)) {
+ resultp1 = resultp2 = 0;
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ Dbl_clear_signexponent_set_hidden(srcp1);
+ Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,
+ resultp1,resultp2);
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ else {
+ Duint_setzero(resultp1,resultp2);
+ Duint_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/fcnvfx.c b/arch/parisc/math-emu/fcnvfx.c
new file mode 100644
index 000000000000..d6475bddb507
--- /dev/null
+++ b/arch/parisc/math-emu/fcnvfx.c
@@ -0,0 +1,501 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single Floating-point to Single Fixed-point
+ * Single Floating-point to Double Fixed-point
+ * Double Floating-point to Single Fixed-point
+ * Double Floating-point to Double Fixed-point
+ *
+ * External Interfaces:
+ * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
+ * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
+ * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
+ * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ * Single Floating-point to Single Fixed-point
+ */
+/*ARGSUSED*/
+int
+sgl_to_sgl_fcnvfx(
+ sgl_floating_point *srcptr,
+ sgl_floating_point *nullptr,
+ int *dstptr,
+ sgl_floating_point *status)
+{
+ register unsigned int src, temp;
+ register int src_exponent, result;
+ register boolean inexact = FALSE;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > SGL_FX_MAX_EXP) {
+ /* check for MININT */
+ if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
+ Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
+ if (Sgl_iszero_sign(src)) result = 0x7fffffff;
+ else result = 0x80000000;
+
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ temp = src;
+ Sgl_clear_signexponent_set_hidden(temp);
+ Int_from_sgl_mantissa(temp,src_exponent);
+ if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
+ else result = Sgl_all(temp);
+
+ /* check for inexact */
+ if (Sgl_isinexact_to_fix(src,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(src)) result++;
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(src)) result--;
+ break;
+ case ROUNDNEAREST:
+ if (Sgl_isone_roundbit(src,src_exponent)) {
+ if (Sgl_isone_stickybit(src,src_exponent)
+ || (Sgl_isone_lowmantissa(temp)))
+ if (Sgl_iszero_sign(src)) result++;
+ else result--;
+ }
+ }
+ }
+ }
+ else {
+ result = 0;
+
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(src)) result++;
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(src)) result--;
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1)
+ if (Sgl_isnotzero_mantissa(src))
+ if (Sgl_iszero_sign(src)) result++;
+ else result--;
+ }
+ }
+ }
+ *dstptr = result;
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Single Floating-point to Double Fixed-point
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvfx(
+ sgl_floating_point *srcptr,
+ unsigned int *nullptr,
+ dbl_integer *dstptr,
+ unsigned int *status)
+{
+ register int src_exponent, resultp1;
+ register unsigned int src, temp, resultp2;
+ register boolean inexact = FALSE;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > DBL_FX_MAX_EXP) {
+ /* check for MININT */
+ if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
+ Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
+ if (Sgl_iszero_sign(src)) {
+ resultp1 = 0x7fffffff;
+ resultp2 = 0xffffffff;
+ }
+ else {
+ resultp1 = 0x80000000;
+ resultp2 = 0;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ Dint_set_minint(resultp1,resultp2);
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ temp = src;
+ Sgl_clear_signexponent_set_hidden(temp);
+ Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
+ if (Sgl_isone_sign(src)) {
+ Dint_setone_sign(resultp1,resultp2);
+ }
+
+ /* check for inexact */
+ if (Sgl_isinexact_to_fix(src,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(src)) {
+ Dint_increment(resultp1,resultp2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(src)) {
+ Dint_decrement(resultp1,resultp2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (Sgl_isone_roundbit(src,src_exponent))
+ if (Sgl_isone_stickybit(src,src_exponent) ||
+ (Dint_isone_lowp2(resultp2)))
+ if (Sgl_iszero_sign(src)) {
+ Dint_increment(resultp1,resultp2);
+ }
+ else {
+ Dint_decrement(resultp1,resultp2);
+ }
+ }
+ }
+ }
+ else {
+ Dint_setzero(resultp1,resultp2);
+
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(src)) {
+ Dint_increment(resultp1,resultp2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(src)) {
+ Dint_decrement(resultp1,resultp2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1)
+ if (Sgl_isnotzero_mantissa(src))
+ if (Sgl_iszero_sign(src)) {
+ Dint_increment(resultp1,resultp2);
+ }
+ else {
+ Dint_decrement(resultp1,resultp2);
+ }
+ }
+ }
+ }
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Single Fixed-point
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvfx(
+ dbl_floating_point *srcptr,
+ unsigned int *nullptr,
+ int *dstptr,
+ unsigned int *status)
+{
+ register unsigned int srcp1,srcp2, tempp1,tempp2;
+ register int src_exponent, result;
+ register boolean inexact = FALSE;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > SGL_FX_MAX_EXP) {
+ /* check for MININT */
+ if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
+ if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
+ else result = 0x80000000;
+
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ tempp1 = srcp1;
+ tempp2 = srcp2;
+ Dbl_clear_signexponent_set_hidden(tempp1);
+ Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
+ if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
+ result = -Dbl_allp1(tempp1);
+ else result = Dbl_allp1(tempp1);
+
+ /* check for inexact */
+ if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(srcp1)) result++;
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(srcp1)) result--;
+ break;
+ case ROUNDNEAREST:
+ if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
+ if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
+ (Dbl_isone_lowmantissap1(tempp1)))
+ if (Dbl_iszero_sign(srcp1)) result++;
+ else result--;
+ }
+ /* check for overflow */
+ if ((Dbl_iszero_sign(srcp1) && result < 0) ||
+ (Dbl_isone_sign(srcp1) && result > 0)) {
+
+ if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
+ else result = 0x80000000;
+
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ }
+ else {
+ result = 0;
+
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(srcp1)) result++;
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(srcp1)) result--;
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1)
+ if (Dbl_isnotzero_mantissa(srcp1,srcp2))
+ if (Dbl_iszero_sign(srcp1)) result++;
+ else result--;
+ }
+ }
+ }
+ *dstptr = result;
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Double Fixed-point
+ */
+/*ARGSUSED*/
+int
+dbl_to_dbl_fcnvfx(
+ dbl_floating_point *srcptr,
+ unsigned int *nullptr,
+ dbl_integer *dstptr,
+ unsigned int *status)
+{
+ register int src_exponent, resultp1;
+ register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
+ register boolean inexact = FALSE;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > DBL_FX_MAX_EXP) {
+ /* check for MININT */
+ if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
+ Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
+ if (Dbl_iszero_sign(srcp1)) {
+ resultp1 = 0x7fffffff;
+ resultp2 = 0xffffffff;
+ }
+ else {
+ resultp1 = 0x80000000;
+ resultp2 = 0;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ tempp1 = srcp1;
+ tempp2 = srcp2;
+ Dbl_clear_signexponent_set_hidden(tempp1);
+ Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
+ resultp2);
+ if (Dbl_isone_sign(srcp1)) {
+ Dint_setone_sign(resultp1,resultp2);
+ }
+
+ /* check for inexact */
+ if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(srcp1)) {
+ Dint_increment(resultp1,resultp2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(srcp1)) {
+ Dint_decrement(resultp1,resultp2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
+ if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
+ (Dint_isone_lowp2(resultp2)))
+ if (Dbl_iszero_sign(srcp1)) {
+ Dint_increment(resultp1,resultp2);
+ }
+ else {
+ Dint_decrement(resultp1,resultp2);
+ }
+ }
+ }
+ }
+ else {
+ Dint_setzero(resultp1,resultp2);
+
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(srcp1)) {
+ Dint_increment(resultp1,resultp2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(srcp1)) {
+ Dint_decrement(resultp1,resultp2);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1)
+ if (Dbl_isnotzero_mantissa(srcp1,srcp2))
+ if (Dbl_iszero_sign(srcp1)) {
+ Dint_increment(resultp1,resultp2);
+ }
+ else {
+ Dint_decrement(resultp1,resultp2);
+ }
+ }
+ }
+ }
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/fcnvfxt.c b/arch/parisc/math-emu/fcnvfxt.c
new file mode 100644
index 000000000000..8b9010c4690e
--- /dev/null
+++ b/arch/parisc/math-emu/fcnvfxt.c
@@ -0,0 +1,328 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/fcnvfxt.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single Floating-point to Single Fixed-point /w truncated result
+ * Single Floating-point to Double Fixed-point /w truncated result
+ * Double Floating-point to Single Fixed-point /w truncated result
+ * Double Floating-point to Double Fixed-point /w truncated result
+ *
+ * External Interfaces:
+ * dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
+ * dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
+ * sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
+ * sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ * Convert single floating-point to single fixed-point format
+ * with truncated result
+ */
+/*ARGSUSED*/
+int
+sgl_to_sgl_fcnvfxt(
+ sgl_floating_point *srcptr,
+ unsigned int *nullptr,
+ int *dstptr,
+ unsigned int *status)
+{
+ register unsigned int src, temp;
+ register int src_exponent, result;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > SGL_FX_MAX_EXP) {
+ /* check for MININT */
+ if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
+ Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
+ if (Sgl_iszero_sign(src)) result = 0x7fffffff;
+ else result = 0x80000000;
+
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ temp = src;
+ Sgl_clear_signexponent_set_hidden(temp);
+ Int_from_sgl_mantissa(temp,src_exponent);
+ if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
+ else result = Sgl_all(temp);
+ *dstptr = result;
+
+ /* check for inexact */
+ if (Sgl_isinexact_to_fix(src,src_exponent)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ else {
+ *dstptr = 0;
+
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Single Floating-point to Double Fixed-point
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvfxt(
+ sgl_floating_point *srcptr,
+ unsigned int *nullptr,
+ dbl_integer *dstptr,
+ unsigned int *status)
+{
+ register int src_exponent, resultp1;
+ register unsigned int src, temp, resultp2;
+
+ src = *srcptr;
+ src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > DBL_FX_MAX_EXP) {
+ /* check for MININT */
+ if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
+ Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
+ if (Sgl_iszero_sign(src)) {
+ resultp1 = 0x7fffffff;
+ resultp2 = 0xffffffff;
+ }
+ else {
+ resultp1 = 0x80000000;
+ resultp2 = 0;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ Dint_set_minint(resultp1,resultp2);
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ temp = src;
+ Sgl_clear_signexponent_set_hidden(temp);
+ Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
+ if (Sgl_isone_sign(src)) {
+ Dint_setone_sign(resultp1,resultp2);
+ }
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (Sgl_isinexact_to_fix(src,src_exponent)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ else {
+ Dint_setzero(resultp1,resultp2);
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Single Fixed-point
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvfxt(
+ dbl_floating_point *srcptr,
+ unsigned int *nullptr,
+ int *dstptr,
+ unsigned int *status)
+{
+ register unsigned int srcp1, srcp2, tempp1, tempp2;
+ register int src_exponent, result;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > SGL_FX_MAX_EXP) {
+ /* check for MININT */
+ if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
+ if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
+ else result = 0x80000000;
+
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ tempp1 = srcp1;
+ tempp2 = srcp2;
+ Dbl_clear_signexponent_set_hidden(tempp1);
+ Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
+ if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
+ result = -Dbl_allp1(tempp1);
+ else result = Dbl_allp1(tempp1);
+ *dstptr = result;
+
+ /* check for inexact */
+ if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ else {
+ *dstptr = 0;
+
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point to Double Fixed-point
+ */
+/*ARGSUSED*/
+int
+dbl_to_dbl_fcnvfxt(
+ dbl_floating_point *srcptr,
+ unsigned int *nullptr,
+ dbl_integer *dstptr,
+ unsigned int *status)
+{
+ register int src_exponent, resultp1;
+ register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+ /*
+ * Test for overflow
+ */
+ if (src_exponent > DBL_FX_MAX_EXP) {
+ /* check for MININT */
+ if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
+ Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
+ if (Dbl_iszero_sign(srcp1)) {
+ resultp1 = 0x7fffffff;
+ resultp2 = 0xffffffff;
+ }
+ else {
+ resultp1 = 0x80000000;
+ resultp2 = 0;
+ }
+ if (Is_invalidtrap_enabled()) {
+ return(INVALIDEXCEPTION);
+ }
+ Set_invalidflag();
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ tempp1 = srcp1;
+ tempp2 = srcp2;
+ Dbl_clear_signexponent_set_hidden(tempp1);
+ Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
+ resultp1,resultp2);
+ if (Dbl_isone_sign(srcp1)) {
+ Dint_setone_sign(resultp1,resultp2);
+ }
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ else {
+ Dint_setzero(resultp1,resultp2);
+ Dint_copytoptr(resultp1,resultp2,dstptr);
+
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ }
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/fcnvuf.c b/arch/parisc/math-emu/fcnvuf.c
new file mode 100644
index 000000000000..5e68189fee22
--- /dev/null
+++ b/arch/parisc/math-emu/fcnvuf.c
@@ -0,0 +1,318 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/fcnvuf.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Fixed point to Floating-point Converts
+ *
+ * External Interfaces:
+ * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
+ * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
+ * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
+ * sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/************************************************************************
+ * Fixed point to Floating-point Converts *
+ ************************************************************************/
+
+/*
+ * Convert Single Unsigned Fixed to Single Floating-point format
+ */
+
+int
+sgl_to_sgl_fcnvuf(
+ unsigned int *srcptr,
+ unsigned int *nullptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int src, result = 0;
+ register int dst_exponent;
+
+ src = *srcptr;
+
+ /* Check for zero */
+ if (src == 0) {
+ Sgl_setzero(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate exponent and normalized mantissa
+ */
+ dst_exponent = 16; /* initialize for normalization */
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(src,dst_exponent);
+ /* left justify source, with msb at bit position 0 */
+ src <<= dst_exponent+1;
+ Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH);
+ Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
+
+ /* check for inexact */
+ if (Suint_isinexact_to_sgl(src)) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ Sgl_increment(result);
+ break;
+ case ROUNDMINUS: /* never negative */
+ break;
+ case ROUNDNEAREST:
+ Sgl_roundnearest_from_suint(src,result);
+ break;
+ }
+ if (Is_inexacttrap_enabled()) {
+ *dstptr = result;
+ return(INEXACTEXCEPTION);
+ }
+ else Set_inexactflag();
+ }
+ *dstptr = result;
+ return(NOEXCEPTION);
+}
+
+/*
+ * Single Unsigned Fixed to Double Floating-point
+ */
+
+int
+sgl_to_dbl_fcnvuf(
+ unsigned int *srcptr,
+ unsigned int *nullptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register int dst_exponent;
+ register unsigned int src, resultp1 = 0, resultp2 = 0;
+
+ src = *srcptr;
+
+ /* Check for zero */
+ if (src == 0) {
+ Dbl_setzero(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate exponent and normalized mantissa
+ */
+ dst_exponent = 16; /* initialize for normalization */
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(src,dst_exponent);
+ /* left justify source, with msb at bit position 0 */
+ src <<= dst_exponent+1;
+ Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH);
+ Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH));
+ Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Unsigned Fixed to Single Floating-point
+ */
+
+int
+dbl_to_sgl_fcnvuf(
+ dbl_unsigned *srcptr,
+ unsigned int *nullptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+{
+ int dst_exponent;
+ unsigned int srcp1, srcp2, result = 0;
+
+ Duint_copyfromptr(srcptr,srcp1,srcp2);
+
+ /* Check for zero */
+ if (srcp1 == 0 && srcp2 == 0) {
+ Sgl_setzero(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate exponent and normalized mantissa
+ */
+ dst_exponent = 16; /* initialize for normalization */
+ if (srcp1 == 0) {
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(srcp2,dst_exponent);
+ /* left justify source, with msb at bit position 0 */
+ srcp1 = srcp2 << dst_exponent+1;
+ srcp2 = 0;
+ /*
+ * since msb set is in second word, need to
+ * adjust bit position count
+ */
+ dst_exponent += 32;
+ }
+ else {
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ *
+ */
+ Find_ms_one_bit(srcp1,dst_exponent);
+ /* left justify source, with msb at bit position 0 */
+ if (dst_exponent >= 0) {
+ Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
+ srcp1);
+ srcp2 <<= dst_exponent+1;
+ }
+ }
+ Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH);
+ Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
+
+ /* check for inexact */
+ if (Duint_isinexact_to_sgl(srcp1,srcp2)) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ Sgl_increment(result);
+ break;
+ case ROUNDMINUS: /* never negative */
+ break;
+ case ROUNDNEAREST:
+ Sgl_roundnearest_from_duint(srcp1,srcp2,result);
+ break;
+ }
+ if (Is_inexacttrap_enabled()) {
+ *dstptr = result;
+ return(INEXACTEXCEPTION);
+ }
+ else Set_inexactflag();
+ }
+ *dstptr = result;
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Unsigned Fixed to Double Floating-point
+ */
+
+int
+dbl_to_dbl_fcnvuf(
+ dbl_unsigned *srcptr,
+ unsigned int *nullptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register int dst_exponent;
+ register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0;
+
+ Duint_copyfromptr(srcptr,srcp1,srcp2);
+
+ /* Check for zero */
+ if (srcp1 == 0 && srcp2 ==0) {
+ Dbl_setzero(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate exponent and normalized mantissa
+ */
+ dst_exponent = 16; /* initialize for normalization */
+ if (srcp1 == 0) {
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(srcp2,dst_exponent);
+ /* left justify source, with msb at bit position 0 */
+ srcp1 = srcp2 << dst_exponent+1;
+ srcp2 = 0;
+ /*
+ * since msb set is in second word, need to
+ * adjust bit position count
+ */
+ dst_exponent += 32;
+ }
+ else {
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(srcp1,dst_exponent);
+ /* left justify source, with msb at bit position 0 */
+ if (dst_exponent >= 0) {
+ Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
+ srcp1);
+ srcp2 <<= dst_exponent+1;
+ }
+ }
+ Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH);
+ Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2);
+ Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
+
+ /* check for inexact */
+ if (Duint_isinexact_to_dbl(srcp2)) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ Dbl_increment(resultp1,resultp2);
+ break;
+ case ROUNDMINUS: /* never negative */
+ break;
+ case ROUNDNEAREST:
+ Dbl_roundnearest_from_duint(srcp2,resultp1,
+ resultp2);
+ break;
+ }
+ if (Is_inexacttrap_enabled()) {
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(INEXACTEXCEPTION);
+ }
+ else Set_inexactflag();
+ }
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+}
+
diff --git a/arch/parisc/math-emu/fcnvxf.c b/arch/parisc/math-emu/fcnvxf.c
new file mode 100644
index 000000000000..05c7fadb3729
--- /dev/null
+++ b/arch/parisc/math-emu/fcnvxf.c
@@ -0,0 +1,386 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single Fixed-point to Single Floating-point
+ * Single Fixed-point to Double Floating-point
+ * Double Fixed-point to Single Floating-point
+ * Double Fixed-point to Double Floating-point
+ *
+ * External Interfaces:
+ * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
+ * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
+ * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
+ * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ * Convert single fixed-point to single floating-point format
+ */
+
+int
+sgl_to_sgl_fcnvxf(
+ int *srcptr,
+ unsigned int *nullptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register int src, dst_exponent;
+ register unsigned int result = 0;
+
+ src = *srcptr;
+ /*
+ * set sign bit of result and get magnitude of source
+ */
+ if (src < 0) {
+ Sgl_setone_sign(result);
+ Int_negate(src);
+ }
+ else {
+ Sgl_setzero_sign(result);
+ /* Check for zero */
+ if (src == 0) {
+ Sgl_setzero(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate exponent and normalized mantissa
+ */
+ dst_exponent = 16; /* initialize for normalization */
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(src,dst_exponent);
+ /* left justify source, with msb at bit position 1 */
+ if (dst_exponent >= 0) src <<= dst_exponent;
+ else src = 1 << 30;
+ Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
+ Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
+
+ /* check for inexact */
+ if (Int_isinexact_to_sgl(src)) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result))
+ Sgl_increment(result);
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result))
+ Sgl_increment(result);
+ break;
+ case ROUNDNEAREST:
+ Sgl_roundnearest_from_int(src,result);
+ }
+ if (Is_inexacttrap_enabled()) {
+ *dstptr = result;
+ return(INEXACTEXCEPTION);
+ }
+ else Set_inexactflag();
+ }
+ *dstptr = result;
+ return(NOEXCEPTION);
+}
+
+/*
+ * Single Fixed-point to Double Floating-point
+ */
+
+int
+sgl_to_dbl_fcnvxf(
+ int *srcptr,
+ unsigned int *nullptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register int src, dst_exponent;
+ register unsigned int resultp1 = 0, resultp2 = 0;
+
+ src = *srcptr;
+ /*
+ * set sign bit of result and get magnitude of source
+ */
+ if (src < 0) {
+ Dbl_setone_sign(resultp1);
+ Int_negate(src);
+ }
+ else {
+ Dbl_setzero_sign(resultp1);
+ /* Check for zero */
+ if (src == 0) {
+ Dbl_setzero(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate exponent and normalized mantissa
+ */
+ dst_exponent = 16; /* initialize for normalization */
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(src,dst_exponent);
+ /* left justify source, with msb at bit position 1 */
+ if (dst_exponent >= 0) src <<= dst_exponent;
+ else src = 1 << 30;
+ Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
+ Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
+ Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Fixed-point to Single Floating-point
+ */
+
+int
+dbl_to_sgl_fcnvxf(
+ dbl_integer *srcptr,
+ unsigned int *nullptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+{
+ int dst_exponent, srcp1;
+ unsigned int result = 0, srcp2;
+
+ Dint_copyfromptr(srcptr,srcp1,srcp2);
+ /*
+ * set sign bit of result and get magnitude of source
+ */
+ if (srcp1 < 0) {
+ Sgl_setone_sign(result);
+ Dint_negate(srcp1,srcp2);
+ }
+ else {
+ Sgl_setzero_sign(result);
+ /* Check for zero */
+ if (srcp1 == 0 && srcp2 == 0) {
+ Sgl_setzero(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate exponent and normalized mantissa
+ */
+ dst_exponent = 16; /* initialize for normalization */
+ if (srcp1 == 0) {
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(srcp2,dst_exponent);
+ /* left justify source, with msb at bit position 1 */
+ if (dst_exponent >= 0) {
+ srcp1 = srcp2 << dst_exponent;
+ srcp2 = 0;
+ }
+ else {
+ srcp1 = srcp2 >> 1;
+ srcp2 <<= 31;
+ }
+ /*
+ * since msb set is in second word, need to
+ * adjust bit position count
+ */
+ dst_exponent += 32;
+ }
+ else {
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ *
+ */
+ Find_ms_one_bit(srcp1,dst_exponent);
+ /* left justify source, with msb at bit position 1 */
+ if (dst_exponent > 0) {
+ Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
+ srcp1);
+ srcp2 <<= dst_exponent;
+ }
+ /*
+ * If dst_exponent = 0, we don't need to shift anything.
+ * If dst_exponent = -1, src = - 2**63 so we won't need to
+ * shift srcp2.
+ */
+ else srcp1 >>= -(dst_exponent);
+ }
+ Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
+ Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
+
+ /* check for inexact */
+ if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result))
+ Sgl_increment(result);
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result))
+ Sgl_increment(result);
+ break;
+ case ROUNDNEAREST:
+ Sgl_roundnearest_from_dint(srcp1,srcp2,result);
+ }
+ if (Is_inexacttrap_enabled()) {
+ *dstptr = result;
+ return(INEXACTEXCEPTION);
+ }
+ else Set_inexactflag();
+ }
+ *dstptr = result;
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Fixed-point to Double Floating-point
+ */
+
+int
+dbl_to_dbl_fcnvxf(
+ dbl_integer *srcptr,
+ unsigned int *nullptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register int srcp1, dst_exponent;
+ register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
+
+ Dint_copyfromptr(srcptr,srcp1,srcp2);
+ /*
+ * set sign bit of result and get magnitude of source
+ */
+ if (srcp1 < 0) {
+ Dbl_setone_sign(resultp1);
+ Dint_negate(srcp1,srcp2);
+ }
+ else {
+ Dbl_setzero_sign(resultp1);
+ /* Check for zero */
+ if (srcp1 == 0 && srcp2 ==0) {
+ Dbl_setzero(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * Generate exponent and normalized mantissa
+ */
+ dst_exponent = 16; /* initialize for normalization */
+ if (srcp1 == 0) {
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(srcp2,dst_exponent);
+ /* left justify source, with msb at bit position 1 */
+ if (dst_exponent >= 0) {
+ srcp1 = srcp2 << dst_exponent;
+ srcp2 = 0;
+ }
+ else {
+ srcp1 = srcp2 >> 1;
+ srcp2 <<= 31;
+ }
+ /*
+ * since msb set is in second word, need to
+ * adjust bit position count
+ */
+ dst_exponent += 32;
+ }
+ else {
+ /*
+ * Check word for most significant bit set. Returns
+ * a value in dst_exponent indicating the bit position,
+ * between -1 and 30.
+ */
+ Find_ms_one_bit(srcp1,dst_exponent);
+ /* left justify source, with msb at bit position 1 */
+ if (dst_exponent > 0) {
+ Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
+ srcp1);
+ srcp2 <<= dst_exponent;
+ }
+ /*
+ * If dst_exponent = 0, we don't need to shift anything.
+ * If dst_exponent = -1, src = - 2**63 so we won't need to
+ * shift srcp2.
+ */
+ else srcp1 >>= -(dst_exponent);
+ }
+ Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
+ Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
+ Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
+
+ /* check for inexact */
+ if (Dint_isinexact_to_dbl(srcp2)) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1)) {
+ Dbl_increment(resultp1,resultp2);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1)) {
+ Dbl_increment(resultp1,resultp2);
+ }
+ break;
+ case ROUNDNEAREST:
+ Dbl_roundnearest_from_dint(srcp2,resultp1,
+ resultp2);
+ }
+ if (Is_inexacttrap_enabled()) {
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(INEXACTEXCEPTION);
+ }
+ else Set_inexactflag();
+ }
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/float.h b/arch/parisc/math-emu/float.h
new file mode 100644
index 000000000000..ce76f6dfa25b
--- /dev/null
+++ b/arch/parisc/math-emu/float.h
@@ -0,0 +1,582 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/float.h $Revision: 1.1 $
+ *
+ * Purpose:
+ * <<please update with a synopis of the functionality provided by this file>>
+ *
+ * BE header: no
+ *
+ * Shipped: yes
+ * /usr/conf/pa/spmath/float.h
+ *
+ * END_DESC
+*/
+
+#ifdef __NO_PA_HDRS
+ PA header file -- do not include this header file for non-PA builds.
+#endif
+
+#include "fpbits.h"
+#include "hppa.h"
+/*
+ * Want to pick up the FPU capability flags, not the PDC structures.
+ * 'LOCORE' isn't really true in this case, but we don't want the C structures
+ * so it suits our purposes
+ */
+#define LOCORE
+#include "fpu.h"
+
+/*
+ * Declare the basic structures for the 3 different
+ * floating-point precisions.
+ *
+ * Single number
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s| exp | mantissa |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Sall(object) (object)
+#define Ssign(object) Bitfield_extract( 0, 1,object)
+#define Ssignedsign(object) Bitfield_signed_extract( 0, 1,object)
+#define Sexponent(object) Bitfield_extract( 1, 8,object)
+#define Smantissa(object) Bitfield_mask( 9, 23,object)
+#define Ssignaling(object) Bitfield_extract( 9, 1,object)
+#define Ssignalingnan(object) Bitfield_extract( 1, 9,object)
+#define Shigh2mantissa(object) Bitfield_extract( 9, 2,object)
+#define Sexponentmantissa(object) Bitfield_mask( 1, 31,object)
+#define Ssignexponent(object) Bitfield_extract( 0, 9,object)
+#define Shidden(object) Bitfield_extract( 8, 1,object)
+#define Shiddenoverflow(object) Bitfield_extract( 7, 1,object)
+#define Shiddenhigh7mantissa(object) Bitfield_extract( 8, 8,object)
+#define Shiddenhigh3mantissa(object) Bitfield_extract( 8, 4,object)
+#define Slow(object) Bitfield_mask( 31, 1,object)
+#define Slow4(object) Bitfield_mask( 28, 4,object)
+#define Slow31(object) Bitfield_mask( 1, 31,object)
+#define Shigh31(object) Bitfield_extract( 0, 31,object)
+#define Ssignedhigh31(object) Bitfield_signed_extract( 0, 31,object)
+#define Shigh4(object) Bitfield_extract( 0, 4,object)
+#define Sbit24(object) Bitfield_extract( 24, 1,object)
+#define Sbit28(object) Bitfield_extract( 28, 1,object)
+#define Sbit29(object) Bitfield_extract( 29, 1,object)
+#define Sbit30(object) Bitfield_extract( 30, 1,object)
+#define Sbit31(object) Bitfield_mask( 31, 1,object)
+
+#define Deposit_ssign(object,value) Bitfield_deposit(value,0,1,object)
+#define Deposit_sexponent(object,value) Bitfield_deposit(value,1,8,object)
+#define Deposit_smantissa(object,value) Bitfield_deposit(value,9,23,object)
+#define Deposit_shigh2mantissa(object,value) Bitfield_deposit(value,9,2,object)
+#define Deposit_sexponentmantissa(object,value) \
+ Bitfield_deposit(value,1,31,object)
+#define Deposit_ssignexponent(object,value) Bitfield_deposit(value,0,9,object)
+#define Deposit_slow(object,value) Bitfield_deposit(value,31,1,object)
+#define Deposit_shigh4(object,value) Bitfield_deposit(value,0,4,object)
+
+#define Is_ssign(object) Bitfield_mask( 0, 1,object)
+#define Is_ssignaling(object) Bitfield_mask( 9, 1,object)
+#define Is_shidden(object) Bitfield_mask( 8, 1,object)
+#define Is_shiddenoverflow(object) Bitfield_mask( 7, 1,object)
+#define Is_slow(object) Bitfield_mask( 31, 1,object)
+#define Is_sbit24(object) Bitfield_mask( 24, 1,object)
+#define Is_sbit28(object) Bitfield_mask( 28, 1,object)
+#define Is_sbit29(object) Bitfield_mask( 29, 1,object)
+#define Is_sbit30(object) Bitfield_mask( 30, 1,object)
+#define Is_sbit31(object) Bitfield_mask( 31, 1,object)
+
+/*
+ * Double number.
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s| exponent | mantissa part 1 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | mantissa part 2 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Dallp1(object) (object)
+#define Dsign(object) Bitfield_extract( 0, 1,object)
+#define Dsignedsign(object) Bitfield_signed_extract( 0, 1,object)
+#define Dexponent(object) Bitfield_extract( 1, 11,object)
+#define Dmantissap1(object) Bitfield_mask( 12, 20,object)
+#define Dsignaling(object) Bitfield_extract( 12, 1,object)
+#define Dsignalingnan(object) Bitfield_extract( 1, 12,object)
+#define Dhigh2mantissa(object) Bitfield_extract( 12, 2,object)
+#define Dexponentmantissap1(object) Bitfield_mask( 1, 31,object)
+#define Dsignexponent(object) Bitfield_extract( 0, 12,object)
+#define Dhidden(object) Bitfield_extract( 11, 1,object)
+#define Dhiddenoverflow(object) Bitfield_extract( 10, 1,object)
+#define Dhiddenhigh7mantissa(object) Bitfield_extract( 11, 8,object)
+#define Dhiddenhigh3mantissa(object) Bitfield_extract( 11, 4,object)
+#define Dlowp1(object) Bitfield_mask( 31, 1,object)
+#define Dlow31p1(object) Bitfield_mask( 1, 31,object)
+#define Dhighp1(object) Bitfield_extract( 0, 1,object)
+#define Dhigh4p1(object) Bitfield_extract( 0, 4,object)
+#define Dhigh31p1(object) Bitfield_extract( 0, 31,object)
+#define Dsignedhigh31p1(object) Bitfield_signed_extract( 0, 31,object)
+#define Dbit3p1(object) Bitfield_extract( 3, 1,object)
+
+#define Deposit_dsign(object,value) Bitfield_deposit(value,0,1,object)
+#define Deposit_dexponent(object,value) Bitfield_deposit(value,1,11,object)
+#define Deposit_dmantissap1(object,value) Bitfield_deposit(value,12,20,object)
+#define Deposit_dhigh2mantissa(object,value) Bitfield_deposit(value,12,2,object)
+#define Deposit_dexponentmantissap1(object,value) \
+ Bitfield_deposit(value,1,31,object)
+#define Deposit_dsignexponent(object,value) Bitfield_deposit(value,0,12,object)
+#define Deposit_dlowp1(object,value) Bitfield_deposit(value,31,1,object)
+#define Deposit_dhigh4p1(object,value) Bitfield_deposit(value,0,4,object)
+
+#define Is_dsign(object) Bitfield_mask( 0, 1,object)
+#define Is_dsignaling(object) Bitfield_mask( 12, 1,object)
+#define Is_dhidden(object) Bitfield_mask( 11, 1,object)
+#define Is_dhiddenoverflow(object) Bitfield_mask( 10, 1,object)
+#define Is_dlowp1(object) Bitfield_mask( 31, 1,object)
+#define Is_dhighp1(object) Bitfield_mask( 0, 1,object)
+#define Is_dbit3p1(object) Bitfield_mask( 3, 1,object)
+
+#define Dallp2(object) (object)
+#define Dmantissap2(object) (object)
+#define Dlowp2(object) Bitfield_mask( 31, 1,object)
+#define Dlow4p2(object) Bitfield_mask( 28, 4,object)
+#define Dlow31p2(object) Bitfield_mask( 1, 31,object)
+#define Dhighp2(object) Bitfield_extract( 0, 1,object)
+#define Dhigh31p2(object) Bitfield_extract( 0, 31,object)
+#define Dbit2p2(object) Bitfield_extract( 2, 1,object)
+#define Dbit3p2(object) Bitfield_extract( 3, 1,object)
+#define Dbit21p2(object) Bitfield_extract( 21, 1,object)
+#define Dbit28p2(object) Bitfield_extract( 28, 1,object)
+#define Dbit29p2(object) Bitfield_extract( 29, 1,object)
+#define Dbit30p2(object) Bitfield_extract( 30, 1,object)
+#define Dbit31p2(object) Bitfield_mask( 31, 1,object)
+
+#define Deposit_dlowp2(object,value) Bitfield_deposit(value,31,1,object)
+
+#define Is_dlowp2(object) Bitfield_mask( 31, 1,object)
+#define Is_dhighp2(object) Bitfield_mask( 0, 1,object)
+#define Is_dbit2p2(object) Bitfield_mask( 2, 1,object)
+#define Is_dbit3p2(object) Bitfield_mask( 3, 1,object)
+#define Is_dbit21p2(object) Bitfield_mask( 21, 1,object)
+#define Is_dbit28p2(object) Bitfield_mask( 28, 1,object)
+#define Is_dbit29p2(object) Bitfield_mask( 29, 1,object)
+#define Is_dbit30p2(object) Bitfield_mask( 30, 1,object)
+#define Is_dbit31p2(object) Bitfield_mask( 31, 1,object)
+
+/*
+ * Quad number.
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s| exponent | mantissa part 1 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | mantissa part 2 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | mantissa part 3 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | mantissa part 4 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+typedef struct
+ {
+ union
+ {
+ struct { unsigned qallp1; } u_qallp1;
+/* Not needed for now...
+ Bitfield_extract( 0, 1,u_qsign,qsign)
+ Bitfield_signed_extract( 0, 1,u_qsignedsign,qsignedsign)
+ Bitfield_extract( 1, 15,u_qexponent,qexponent)
+ Bitfield_extract(16, 16,u_qmantissap1,qmantissap1)
+ Bitfield_extract(16, 1,u_qsignaling,qsignaling)
+ Bitfield_extract(1, 16,u_qsignalingnan,qsignalingnan)
+ Bitfield_extract(16, 2,u_qhigh2mantissa,qhigh2mantissa)
+ Bitfield_extract( 1, 31,u_qexponentmantissap1,qexponentmantissap1)
+ Bitfield_extract( 0, 16,u_qsignexponent,qsignexponent)
+ Bitfield_extract(15, 1,u_qhidden,qhidden)
+ Bitfield_extract(14, 1,u_qhiddenoverflow,qhiddenoverflow)
+ Bitfield_extract(15, 8,u_qhiddenhigh7mantissa,qhiddenhigh7mantissa)
+ Bitfield_extract(15, 4,u_qhiddenhigh3mantissa,qhiddenhigh3mantissa)
+ Bitfield_extract(31, 1,u_qlowp1,qlowp1)
+ Bitfield_extract( 1, 31,u_qlow31p1,qlow31p1)
+ Bitfield_extract( 0, 1,u_qhighp1,qhighp1)
+ Bitfield_extract( 0, 4,u_qhigh4p1,qhigh4p1)
+ Bitfield_extract( 0, 31,u_qhigh31p1,qhigh31p1)
+ */
+ } quad_u1;
+ union
+ {
+ struct { unsigned qallp2; } u_qallp2;
+ /* Not needed for now...
+ Bitfield_extract(31, 1,u_qlowp2,qlowp2)
+ Bitfield_extract( 1, 31,u_qlow31p2,qlow31p2)
+ Bitfield_extract( 0, 1,u_qhighp2,qhighp2)
+ Bitfield_extract( 0, 31,u_qhigh31p2,qhigh31p2)
+ */
+ } quad_u2;
+ union
+ {
+ struct { unsigned qallp3; } u_qallp3;
+ /* Not needed for now...
+ Bitfield_extract(31, 1,u_qlowp3,qlowp3)
+ Bitfield_extract( 1, 31,u_qlow31p3,qlow31p3)
+ Bitfield_extract( 0, 1,u_qhighp3,qhighp3)
+ Bitfield_extract( 0, 31,u_qhigh31p3,qhigh31p3)
+ */
+ } quad_u3;
+ union
+ {
+ struct { unsigned qallp4; } u_qallp4;
+ /* Not need for now...
+ Bitfield_extract(31, 1,u_qlowp4,qlowp4)
+ Bitfield_extract( 1, 31,u_qlow31p4,qlow31p4)
+ Bitfield_extract( 0, 1,u_qhighp4,qhighp4)
+ Bitfield_extract( 0, 31,u_qhigh31p4,qhigh31p4)
+ */
+ } quad_u4;
+ } quad_floating_point;
+
+/* Extension - An additional structure to hold the guard, round and
+ * sticky bits during computations.
+ */
+#define Extall(object) (object)
+#define Extsign(object) Bitfield_extract( 0, 1,object)
+#define Exthigh31(object) Bitfield_extract( 0, 31,object)
+#define Extlow31(object) Bitfield_extract( 1, 31,object)
+#define Extlow(object) Bitfield_extract( 31, 1,object)
+
+/*
+ * Single extended - The upper word is just like single precision,
+ * but one additional word of mantissa is needed.
+ */
+#define Sextallp1(object) (object)
+#define Sextallp2(object) (object)
+#define Sextlowp1(object) Bitfield_extract( 31, 1,object)
+#define Sexthighp2(object) Bitfield_extract( 0, 1,object)
+#define Sextlow31p2(object) Bitfield_extract( 1, 31,object)
+#define Sexthiddenoverflow(object) Bitfield_extract( 4, 1,object)
+#define Is_sexthiddenoverflow(object) Bitfield_mask( 4, 1,object)
+
+/*
+ * Double extended - The upper two words are just like double precision,
+ * but two additional words of mantissa are needed.
+ */
+#define Dextallp1(object) (object)
+#define Dextallp2(object) (object)
+#define Dextallp3(object) (object)
+#define Dextallp4(object) (object)
+#define Dextlowp2(object) Bitfield_extract( 31, 1,object)
+#define Dexthighp3(object) Bitfield_extract( 0, 1,object)
+#define Dextlow31p3(object) Bitfield_extract( 1, 31,object)
+#define Dexthiddenoverflow(object) Bitfield_extract( 10, 1,object)
+#define Is_dexthiddenoverflow(object) Bitfield_mask( 10, 1,object)
+#define Deposit_dextlowp4(object,value) Bitfield_deposit(value,31,1,object)
+
+/*
+ * Declare the basic structures for the 3 different
+ * fixed-point precisions.
+ *
+ * Single number
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s| integer |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+typedef int sgl_integer;
+
+/*
+ * Double number.
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s| high integer |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | low integer |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+struct dint {
+ int wd0;
+ unsigned int wd1;
+};
+
+struct dblwd {
+ unsigned int wd0;
+ unsigned int wd1;
+};
+
+/*
+ * Quad number.
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s| integer part1 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | integer part 2 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | integer part 3 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | integer part 4 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+
+struct quadwd {
+ int wd0;
+ unsigned int wd1;
+ unsigned int wd2;
+ unsigned int wd3;
+};
+
+typedef struct quadwd quad_integer;
+
+
+/* useful typedefs */
+typedef unsigned int sgl_floating_point;
+typedef struct dblwd dbl_floating_point;
+typedef struct dint dbl_integer;
+typedef struct dblwd dbl_unsigned;
+
+/*
+ * Define the different precisions' parameters.
+ */
+#define SGL_BITLENGTH 32
+#define SGL_EMAX 127
+#define SGL_EMIN (-126)
+#define SGL_BIAS 127
+#define SGL_WRAP 192
+#define SGL_INFINITY_EXPONENT (SGL_EMAX+SGL_BIAS+1)
+#define SGL_THRESHOLD 32
+#define SGL_EXP_LENGTH 8
+#define SGL_P 24
+
+#define DBL_BITLENGTH 64
+#define DBL_EMAX 1023
+#define DBL_EMIN (-1022)
+#define DBL_BIAS 1023
+#define DBL_WRAP 1536
+#define DBL_INFINITY_EXPONENT (DBL_EMAX+DBL_BIAS+1)
+#define DBL_THRESHOLD 64
+#define DBL_EXP_LENGTH 11
+#define DBL_P 53
+
+#define QUAD_BITLENGTH 128
+#define QUAD_EMAX 16383
+#define QUAD_EMIN (-16382)
+#define QUAD_BIAS 16383
+#define QUAD_WRAP 24576
+#define QUAD_INFINITY_EXPONENT (QUAD_EMAX+QUAD_BIAS+1)
+#define QUAD_P 113
+
+/* Boolean Values etc. */
+#define FALSE 0
+#define TRUE (!FALSE)
+#define NOT !
+#define XOR ^
+
+/* other constants */
+#undef NULL
+#define NULL 0
+#define NIL 0
+#define SGL 0
+#define DBL 1
+#define BADFMT 2
+#define QUAD 3
+
+
+/* Types */
+typedef int boolean;
+typedef int FORMAT;
+typedef int VOID;
+
+
+/* Declare status register equivalent to FPUs architecture.
+ *
+ * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |V|Z|O|U|I|C| rsv | model | version |RM |rsv|T|r|V|Z|O|U|I|
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Cbit(object) Bitfield_extract( 5, 1,object)
+#define Tbit(object) Bitfield_extract( 25, 1,object)
+#define Roundingmode(object) Bitfield_extract( 21, 2,object)
+#define Invalidtrap(object) Bitfield_extract( 27, 1,object)
+#define Divisionbyzerotrap(object) Bitfield_extract( 28, 1,object)
+#define Overflowtrap(object) Bitfield_extract( 29, 1,object)
+#define Underflowtrap(object) Bitfield_extract( 30, 1,object)
+#define Inexacttrap(object) Bitfield_extract( 31, 1,object)
+#define Invalidflag(object) Bitfield_extract( 0, 1,object)
+#define Divisionbyzeroflag(object) Bitfield_extract( 1, 1,object)
+#define Overflowflag(object) Bitfield_extract( 2, 1,object)
+#define Underflowflag(object) Bitfield_extract( 3, 1,object)
+#define Inexactflag(object) Bitfield_extract( 4, 1,object)
+#define Allflags(object) Bitfield_extract( 0, 5,object)
+
+/* Definitions relevant to the status register */
+
+/* Rounding Modes */
+#define ROUNDNEAREST 0
+#define ROUNDZERO 1
+#define ROUNDPLUS 2
+#define ROUNDMINUS 3
+
+/* Exceptions */
+#define NOEXCEPTION 0x0
+#define INVALIDEXCEPTION 0x20
+#define DIVISIONBYZEROEXCEPTION 0x10
+#define OVERFLOWEXCEPTION 0x08
+#define UNDERFLOWEXCEPTION 0x04
+#define INEXACTEXCEPTION 0x02
+#define UNIMPLEMENTEDEXCEPTION 0x01
+
+/* New exceptions for the 2E Opcode */
+#define OPC_2E_INVALIDEXCEPTION 0x30
+#define OPC_2E_OVERFLOWEXCEPTION 0x18
+#define OPC_2E_UNDERFLOWEXCEPTION 0x0c
+#define OPC_2E_INEXACTEXCEPTION 0x12
+
+/* Declare exception registers equivalent to FPUs architecture
+ *
+ * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |excepttype | r1 | r2/ext | operation |parm |n| t/cond |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Allexception(object) (object)
+#define Exceptiontype(object) Bitfield_extract( 0, 6,object)
+#define Instructionfield(object) Bitfield_mask( 6,26,object)
+#define Parmfield(object) Bitfield_extract( 23, 3,object)
+#define Rabit(object) Bitfield_extract( 24, 1,object)
+#define Ibit(object) Bitfield_extract( 25, 1,object)
+
+#define Set_exceptiontype(object,value) Bitfield_deposit(value, 0, 6,object)
+#define Set_parmfield(object,value) Bitfield_deposit(value, 23, 3,object)
+#define Set_exceptiontype_and_instr_field(exception,instruction,object) \
+ object = exception << 26 | instruction
+
+/* Declare the condition field
+ *
+ * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | |G|L|E|U|X|
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Allexception(object) (object)
+#define Greaterthanbit(object) Bitfield_extract( 27, 1,object)
+#define Lessthanbit(object) Bitfield_extract( 28, 1,object)
+#define Equalbit(object) Bitfield_extract( 29, 1,object)
+#define Unorderedbit(object) Bitfield_extract( 30, 1,object)
+#define Exceptionbit(object) Bitfield_extract( 31, 1,object)
+
+/* An alias name for the status register */
+#define Fpustatus_register (*status)
+
+/**************************************************
+ * Status register referencing and manipulation. *
+ **************************************************/
+
+/* Rounding mode */
+#define Rounding_mode() Roundingmode(Fpustatus_register)
+#define Is_rounding_mode(rmode) \
+ (Roundingmode(Fpustatus_register) == rmode)
+#define Set_rounding_mode(value) \
+ Bitfield_deposit(value,21,2,Fpustatus_register)
+
+/* Boolean testing of the trap enable bits */
+#define Is_invalidtrap_enabled() Invalidtrap(Fpustatus_register)
+#define Is_divisionbyzerotrap_enabled() Divisionbyzerotrap(Fpustatus_register)
+#define Is_overflowtrap_enabled() Overflowtrap(Fpustatus_register)
+#define Is_underflowtrap_enabled() Underflowtrap(Fpustatus_register)
+#define Is_inexacttrap_enabled() Inexacttrap(Fpustatus_register)
+
+/* Set the indicated flags in the status register */
+#define Set_invalidflag() Bitfield_deposit(1,0,1,Fpustatus_register)
+#define Set_divisionbyzeroflag() Bitfield_deposit(1,1,1,Fpustatus_register)
+#define Set_overflowflag() Bitfield_deposit(1,2,1,Fpustatus_register)
+#define Set_underflowflag() Bitfield_deposit(1,3,1,Fpustatus_register)
+#define Set_inexactflag() Bitfield_deposit(1,4,1,Fpustatus_register)
+
+#define Clear_all_flags() Bitfield_deposit(0,0,5,Fpustatus_register)
+
+/* Manipulate the trap and condition code bits (tbit and cbit) */
+#define Set_tbit() Bitfield_deposit(1,25,1,Fpustatus_register)
+#define Clear_tbit() Bitfield_deposit(0,25,1,Fpustatus_register)
+#define Is_tbit_set() Tbit(Fpustatus_register)
+#define Is_cbit_set() Cbit(Fpustatus_register)
+
+#define Set_status_cbit(value) \
+ Bitfield_deposit(value,5,1,Fpustatus_register)
+
+/*******************************
+ * Condition field referencing *
+ *******************************/
+#define Unordered(cond) Unorderedbit(cond)
+#define Equal(cond) Equalbit(cond)
+#define Lessthan(cond) Lessthanbit(cond)
+#define Greaterthan(cond) Greaterthanbit(cond)
+#define Exception(cond) Exceptionbit(cond)
+
+
+/* Defines for the extension */
+#define Ext_isone_sign(extent) (Extsign(extent))
+#define Ext_isnotzero(extent) \
+ (Extall(extent))
+#define Ext_isnotzero_lower(extent) \
+ (Extlow31(extent))
+#define Ext_leftshiftby1(extent) \
+ Extall(extent) <<= 1
+#define Ext_negate(extent) \
+ (int )Extall(extent) = 0 - (int )Extall(extent)
+#define Ext_setone_low(extent) Bitfield_deposit(1,31,1,extent)
+#define Ext_setzero(extent) Extall(extent) = 0
+
+typedef int operation;
+
+/* error messages */
+
+#define NONE 0
+#define UNDEFFPINST 1
+
+/* Function definitions: opcode, opclass */
+#define FTEST (1<<2) | 0
+#define FCPY (2<<2) | 0
+#define FABS (3<<2) | 0
+#define FSQRT (4<<2) | 0
+#define FRND (5<<2) | 0
+
+#define FCNVFF (0<<2) | 1
+#define FCNVXF (1<<2) | 1
+#define FCNVFX (2<<2) | 1
+#define FCNVFXT (3<<2) | 1
+
+#define FCMP (0<<2) | 2
+
+#define FADD (0<<2) | 3
+#define FSUB (1<<2) | 3
+#define FMPY (2<<2) | 3
+#define FDIV (3<<2) | 3
+#define FREM (4<<2) | 3
+
diff --git a/arch/parisc/math-emu/fmpyfadd.c b/arch/parisc/math-emu/fmpyfadd.c
new file mode 100644
index 000000000000..5dd7f93a89be
--- /dev/null
+++ b/arch/parisc/math-emu/fmpyfadd.c
@@ -0,0 +1,2655 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/fmpyfadd.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Double Floating-point Multiply Fused Add
+ * Double Floating-point Multiply Negate Fused Add
+ * Single Floating-point Multiply Fused Add
+ * Single Floating-point Multiply Negate Fused Add
+ *
+ * External Interfaces:
+ * dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+ * dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+ * sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+ * sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+
+
+/*
+ * Double Floating-point Multiply Fused Add
+ */
+
+int
+dbl_fmpyfadd(
+ dbl_floating_point *src1ptr,
+ dbl_floating_point *src2ptr,
+ dbl_floating_point *src3ptr,
+ unsigned int *status,
+ dbl_floating_point *dstptr)
+{
+ unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
+ register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
+ unsigned int rightp1, rightp2, rightp3, rightp4;
+ unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
+ register int mpy_exponent, add_exponent, count;
+ boolean inexact = FALSE, is_tiny = FALSE;
+
+ unsigned int signlessleft1, signlessright1, save;
+ register int result_exponent, diff_exponent;
+ int sign_save, jumpsize;
+
+ Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
+ Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
+ Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
+
+ /*
+ * set sign bit of result of multiply
+ */
+ if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
+ Dbl_setnegativezerop1(resultp1);
+ else Dbl_setzerop1(resultp1);
+
+ /*
+ * Generate multiply exponent
+ */
+ mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
+
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd1p1)) {
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
+ Dbl_isnotnan(opnd3p1,opnd3p2)) {
+ if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+ /*
+ * invalid since operands are infinity
+ * and zero
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Check third operand for infinity with a
+ * sign opposite of the multiply result
+ */
+ if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
+ (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
+ /*
+ * invalid since attempting a magnitude
+ * subtraction of infinities
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * return infinity
+ */
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd1p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd1p1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is third operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd3p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd3p1);
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd2p1)) {
+ if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+ if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
+ if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
+ /*
+ * invalid since multiply operands are
+ * zero & infinity
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(opnd2p1,opnd2p2);
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Check third operand for infinity with a
+ * sign opposite of the multiply result
+ */
+ if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
+ (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
+ /*
+ * invalid since attempting a magnitude
+ * subtraction of infinities
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * return infinity
+ */
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ }
+ /*
+ * is third operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd3p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd3p1);
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check third operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd3p1)) {
+ if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
+ /* return infinity */
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ } else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd3p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd3p1);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * Generate multiply mantissa
+ */
+ if (Dbl_isnotzero_exponent(opnd1p1)) {
+ /* set hidden bit */
+ Dbl_clear_signexponent_set_hidden(opnd1p1);
+ }
+ else {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ /*
+ * Perform the add opnd3 with zero here.
+ */
+ if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
+ if (Is_rounding_mode(ROUNDMINUS)) {
+ Dbl_or_signs(opnd3p1,resultp1);
+ } else {
+ Dbl_and_signs(opnd3p1,resultp1);
+ }
+ }
+ /*
+ * Now let's check for trapped underflow case.
+ */
+ else if (Dbl_iszero_exponent(opnd3p1) &&
+ Is_underflowtrap_enabled()) {
+ /* need to normalize results mantissa */
+ sign_save = Dbl_signextendedsign(opnd3p1);
+ result_exponent = 0;
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
+ Dbl_set_sign(opnd3p1,/*using*/sign_save);
+ Dbl_setwrapped_exponent(opnd3p1,result_exponent,
+ unfl);
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ /* inexact = FALSE */
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized, adjust exponent */
+ Dbl_clear_signexponent(opnd1p1);
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
+ }
+ /* opnd2 needs to have hidden bit set with msb in hidden bit */
+ if (Dbl_isnotzero_exponent(opnd2p1)) {
+ Dbl_clear_signexponent_set_hidden(opnd2p1);
+ }
+ else {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+ /*
+ * Perform the add opnd3 with zero here.
+ */
+ if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
+ if (Is_rounding_mode(ROUNDMINUS)) {
+ Dbl_or_signs(opnd3p1,resultp1);
+ } else {
+ Dbl_and_signs(opnd3p1,resultp1);
+ }
+ }
+ /*
+ * Now let's check for trapped underflow case.
+ */
+ else if (Dbl_iszero_exponent(opnd3p1) &&
+ Is_underflowtrap_enabled()) {
+ /* need to normalize results mantissa */
+ sign_save = Dbl_signextendedsign(opnd3p1);
+ result_exponent = 0;
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
+ Dbl_set_sign(opnd3p1,/*using*/sign_save);
+ Dbl_setwrapped_exponent(opnd3p1,result_exponent,
+ unfl);
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ /* inexact = FALSE */
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized; want to normalize */
+ Dbl_clear_signexponent(opnd2p1);
+ Dbl_leftshiftby1(opnd2p1,opnd2p2);
+ Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
+ }
+
+ /* Multiply the first two source mantissas together */
+
+ /*
+ * The intermediate result will be kept in tmpres,
+ * which needs enough room for 106 bits of mantissa,
+ * so lets call it a Double extended.
+ */
+ Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+
+ /*
+ * Four bits at a time are inspected in each loop, and a
+ * simple shift and add multiply algorithm is used.
+ */
+ for (count = DBL_P-1; count >= 0; count -= 4) {
+ Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+ if (Dbit28p2(opnd1p2)) {
+ /* Fourword_add should be an ADD followed by 3 ADDC's */
+ Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+ opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
+ }
+ if (Dbit29p2(opnd1p2)) {
+ Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+ opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
+ }
+ if (Dbit30p2(opnd1p2)) {
+ Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+ opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
+ }
+ if (Dbit31p2(opnd1p2)) {
+ Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+ opnd2p1, opnd2p2, 0, 0);
+ }
+ Dbl_rightshiftby4(opnd1p1,opnd1p2);
+ }
+ if (Is_dexthiddenoverflow(tmpresp1)) {
+ /* result mantissa >= 2 (mantissa overflow) */
+ mpy_exponent++;
+ Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+ }
+
+ /*
+ * Restore the sign of the mpy result which was saved in resultp1.
+ * The exponent will continue to be kept in mpy_exponent.
+ */
+ Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
+
+ /*
+ * No rounding is required, since the result of the multiply
+ * is exact in the extended format.
+ */
+
+ /*
+ * Now we are ready to perform the add portion of the operation.
+ *
+ * The exponents need to be kept as integers for now, since the
+ * multiply result might not fit into the exponent field. We
+ * can't overflow or underflow because of this yet, since the
+ * add could bring the final result back into range.
+ */
+ add_exponent = Dbl_exponent(opnd3p1);
+
+ /*
+ * Check for denormalized or zero add operand.
+ */
+ if (add_exponent == 0) {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
+ /* right is zero */
+ /* Left can't be zero and must be result.
+ *
+ * The final result is now in tmpres and mpy_exponent,
+ * and needs to be rounded and squeezed back into
+ * double precision format from double extended.
+ */
+ result_exponent = mpy_exponent;
+ Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+ resultp1,resultp2,resultp3,resultp4);
+ sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
+ goto round;
+ }
+
+ /*
+ * Neither are zeroes.
+ * Adjust exponent and normalize add operand.
+ */
+ sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */
+ Dbl_clear_signexponent(opnd3p1);
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
+ Dbl_set_sign(opnd3p1,sign_save); /* restore sign */
+ } else {
+ Dbl_clear_exponent_set_hidden(opnd3p1);
+ }
+ /*
+ * Copy opnd3 to the double extended variable called right.
+ */
+ Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
+
+ /*
+ * A zero "save" helps discover equal operands (for later),
+ * and is used in swapping operands (if needed).
+ */
+ Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
+
+ /*
+ * Compare magnitude of operands.
+ */
+ Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
+ Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
+ if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
+ Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
+ /*
+ * Set the left operand to the larger one by XOR swap.
+ * First finish the first word "save".
+ */
+ Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
+ Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
+ Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
+ rightp2,rightp3,rightp4);
+ /* also setup exponents used in rest of routine */
+ diff_exponent = add_exponent - mpy_exponent;
+ result_exponent = add_exponent;
+ } else {
+ /* also setup exponents used in rest of routine */
+ diff_exponent = mpy_exponent - add_exponent;
+ result_exponent = mpy_exponent;
+ }
+ /* Invariant: left is not smaller than right. */
+
+ /*
+ * Special case alignment of operands that would force alignment
+ * beyond the extent of the extension. A further optimization
+ * could special case this but only reduces the path length for
+ * this infrequent case.
+ */
+ if (diff_exponent > DBLEXT_THRESHOLD) {
+ diff_exponent = DBLEXT_THRESHOLD;
+ }
+
+ /* Align right operand by shifting it to the right */
+ Dblext_clear_sign(rightp1);
+ Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
+ /*shifted by*/diff_exponent);
+
+ /* Treat sum and difference of the operands separately. */
+ if ((int)save < 0) {
+ /*
+ * Difference of the two operands. Overflow can occur if the
+ * multiply overflowed. A borrow can occur out of the hidden
+ * bit and force a post normalization phase.
+ */
+ Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+ rightp1,rightp2,rightp3,rightp4,
+ resultp1,resultp2,resultp3,resultp4);
+ sign_save = Dbl_signextendedsign(resultp1);
+ if (Dbl_iszero_hidden(resultp1)) {
+ /* Handle normalization */
+ /* A straight foward algorithm would now shift the
+ * result and extension left until the hidden bit
+ * becomes one. Not all of the extension bits need
+ * participate in the shift. Only the two most
+ * significant bits (round and guard) are needed.
+ * If only a single shift is needed then the guard
+ * bit becomes a significant low order bit and the
+ * extension must participate in the rounding.
+ * If more than a single shift is needed, then all
+ * bits to the right of the guard bit are zeros,
+ * and the guard bit may or may not be zero. */
+ Dblext_leftshiftby1(resultp1,resultp2,resultp3,
+ resultp4);
+
+ /* Need to check for a zero result. The sign and
+ * exponent fields have already been zeroed. The more
+ * efficient test of the full object can be used.
+ */
+ if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){
+ /* Must have been "x-x" or "x+(-x)". */
+ if (Is_rounding_mode(ROUNDMINUS))
+ Dbl_setone_sign(resultp1);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ result_exponent--;
+
+ /* Look to see if normalization is finished. */
+ if (Dbl_isone_hidden(resultp1)) {
+ /* No further normalization is needed */
+ goto round;
+ }
+
+ /* Discover first one bit to determine shift amount.
+ * Use a modified binary search. We have already
+ * shifted the result one position right and still
+ * not found a one so the remainder of the extension
+ * must be zero and simplifies rounding. */
+ /* Scan bytes */
+ while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
+ Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
+ result_exponent -= 8;
+ }
+ /* Now narrow it down to the nibble */
+ if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
+ /* The lower nibble contains the
+ * normalizing one */
+ Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
+ result_exponent -= 4;
+ }
+ /* Select case where first bit is set (already
+ * normalized) otherwise select the proper shift. */
+ jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
+ if (jumpsize <= 7) switch(jumpsize) {
+ case 1:
+ Dblext_leftshiftby3(resultp1,resultp2,resultp3,
+ resultp4);
+ result_exponent -= 3;
+ break;
+ case 2:
+ case 3:
+ Dblext_leftshiftby2(resultp1,resultp2,resultp3,
+ resultp4);
+ result_exponent -= 2;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ Dblext_leftshiftby1(resultp1,resultp2,resultp3,
+ resultp4);
+ result_exponent -= 1;
+ break;
+ }
+ } /* end if (hidden...)... */
+ /* Fall through and round */
+ } /* end if (save < 0)... */
+ else {
+ /* Add magnitudes */
+ Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+ rightp1,rightp2,rightp3,rightp4,
+ /*to*/resultp1,resultp2,resultp3,resultp4);
+ sign_save = Dbl_signextendedsign(resultp1);
+ if (Dbl_isone_hiddenoverflow(resultp1)) {
+ /* Prenormalization required. */
+ Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
+ resultp4);
+ result_exponent++;
+ } /* end if hiddenoverflow... */
+ } /* end else ...add magnitudes... */
+
+ /* Round the result. If the extension and lower two words are
+ * all zeros, then the result is exact. Otherwise round in the
+ * correct direction. Underflow is possible. If a postnormalization
+ * is necessary, then the mantissa is all zeros so no shift is needed.
+ */
+ round:
+ if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
+ Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
+ result_exponent,is_tiny);
+ }
+ Dbl_set_sign(resultp1,/*using*/sign_save);
+ if (Dblext_isnotzero_mantissap3(resultp3) ||
+ Dblext_isnotzero_mantissap4(resultp4)) {
+ inexact = TRUE;
+ switch(Rounding_mode()) {
+ case ROUNDNEAREST: /* The default. */
+ if (Dblext_isone_highp3(resultp3)) {
+ /* at least 1/2 ulp */
+ if (Dblext_isnotzero_low31p3(resultp3) ||
+ Dblext_isnotzero_mantissap4(resultp4) ||
+ Dblext_isone_lowp2(resultp2)) {
+ /* either exactly half way and odd or
+ * more than 1/2ulp */
+ Dbl_increment(resultp1,resultp2);
+ }
+ }
+ break;
+
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1)) {
+ /* Round up positive results */
+ Dbl_increment(resultp1,resultp2);
+ }
+ break;
+
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1)) {
+ /* Round down negative results */
+ Dbl_increment(resultp1,resultp2);
+ }
+
+ case ROUNDZERO:;
+ /* truncate is simple */
+ } /* end switch... */
+ if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
+ }
+ if (result_exponent >= DBL_INFINITY_EXPONENT) {
+ /* trap if OVERFLOWTRAP enabled */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OPC_2E_OVERFLOWEXCEPTION |
+ OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return (OPC_2E_OVERFLOWEXCEPTION);
+ }
+ inexact = TRUE;
+ Set_overflowflag();
+ /* set result to infinity or largest number */
+ Dbl_setoverflow(resultp1,resultp2);
+
+ } else if (result_exponent <= 0) { /* underflow case */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OPC_2E_UNDERFLOWEXCEPTION |
+ OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ else if (inexact && is_tiny) Set_underflowflag();
+ }
+ else Dbl_set_exponent(resultp1,result_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point Multiply Negate Fused Add
+ */
+
+dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+
+dbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
+unsigned int *status;
+{
+ unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
+ register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
+ unsigned int rightp1, rightp2, rightp3, rightp4;
+ unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
+ register int mpy_exponent, add_exponent, count;
+ boolean inexact = FALSE, is_tiny = FALSE;
+
+ unsigned int signlessleft1, signlessright1, save;
+ register int result_exponent, diff_exponent;
+ int sign_save, jumpsize;
+
+ Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
+ Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
+ Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
+
+ /*
+ * set sign bit of result of multiply
+ */
+ if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
+ Dbl_setzerop1(resultp1);
+ else
+ Dbl_setnegativezerop1(resultp1);
+
+ /*
+ * Generate multiply exponent
+ */
+ mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
+
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd1p1)) {
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
+ Dbl_isnotnan(opnd3p1,opnd3p2)) {
+ if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+ /*
+ * invalid since operands are infinity
+ * and zero
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Check third operand for infinity with a
+ * sign opposite of the multiply result
+ */
+ if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
+ (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
+ /*
+ * invalid since attempting a magnitude
+ * subtraction of infinities
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * return infinity
+ */
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd1p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd1p1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is third operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd3p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd3p1);
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd2p1)) {
+ if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+ if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
+ if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
+ /*
+ * invalid since multiply operands are
+ * zero & infinity
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(opnd2p1,opnd2p2);
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Check third operand for infinity with a
+ * sign opposite of the multiply result
+ */
+ if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
+ (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
+ /*
+ * invalid since attempting a magnitude
+ * subtraction of infinities
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Dbl_makequietnan(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * return infinity
+ */
+ Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd2p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd2p1);
+ }
+ /*
+ * is third operand a signaling NaN?
+ */
+ else if (Dbl_is_signalingnan(opnd3p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd3p1);
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check third operand for NaN's or infinity
+ */
+ if (Dbl_isinfinity_exponent(opnd3p1)) {
+ if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
+ /* return infinity */
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ } else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Dbl_isone_signaling(opnd3p1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(opnd3p1);
+ }
+ /*
+ * return quiet NaN
+ */
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * Generate multiply mantissa
+ */
+ if (Dbl_isnotzero_exponent(opnd1p1)) {
+ /* set hidden bit */
+ Dbl_clear_signexponent_set_hidden(opnd1p1);
+ }
+ else {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+ /*
+ * Perform the add opnd3 with zero here.
+ */
+ if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
+ if (Is_rounding_mode(ROUNDMINUS)) {
+ Dbl_or_signs(opnd3p1,resultp1);
+ } else {
+ Dbl_and_signs(opnd3p1,resultp1);
+ }
+ }
+ /*
+ * Now let's check for trapped underflow case.
+ */
+ else if (Dbl_iszero_exponent(opnd3p1) &&
+ Is_underflowtrap_enabled()) {
+ /* need to normalize results mantissa */
+ sign_save = Dbl_signextendedsign(opnd3p1);
+ result_exponent = 0;
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
+ Dbl_set_sign(opnd3p1,/*using*/sign_save);
+ Dbl_setwrapped_exponent(opnd3p1,result_exponent,
+ unfl);
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ /* inexact = FALSE */
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized, adjust exponent */
+ Dbl_clear_signexponent(opnd1p1);
+ Dbl_leftshiftby1(opnd1p1,opnd1p2);
+ Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
+ }
+ /* opnd2 needs to have hidden bit set with msb in hidden bit */
+ if (Dbl_isnotzero_exponent(opnd2p1)) {
+ Dbl_clear_signexponent_set_hidden(opnd2p1);
+ }
+ else {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+ /*
+ * Perform the add opnd3 with zero here.
+ */
+ if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
+ if (Is_rounding_mode(ROUNDMINUS)) {
+ Dbl_or_signs(opnd3p1,resultp1);
+ } else {
+ Dbl_and_signs(opnd3p1,resultp1);
+ }
+ }
+ /*
+ * Now let's check for trapped underflow case.
+ */
+ else if (Dbl_iszero_exponent(opnd3p1) &&
+ Is_underflowtrap_enabled()) {
+ /* need to normalize results mantissa */
+ sign_save = Dbl_signextendedsign(opnd3p1);
+ result_exponent = 0;
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
+ Dbl_set_sign(opnd3p1,/*using*/sign_save);
+ Dbl_setwrapped_exponent(opnd3p1,result_exponent,
+ unfl);
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ /* inexact = FALSE */
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized; want to normalize */
+ Dbl_clear_signexponent(opnd2p1);
+ Dbl_leftshiftby1(opnd2p1,opnd2p2);
+ Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
+ }
+
+ /* Multiply the first two source mantissas together */
+
+ /*
+ * The intermediate result will be kept in tmpres,
+ * which needs enough room for 106 bits of mantissa,
+ * so lets call it a Double extended.
+ */
+ Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+
+ /*
+ * Four bits at a time are inspected in each loop, and a
+ * simple shift and add multiply algorithm is used.
+ */
+ for (count = DBL_P-1; count >= 0; count -= 4) {
+ Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+ if (Dbit28p2(opnd1p2)) {
+ /* Fourword_add should be an ADD followed by 3 ADDC's */
+ Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+ opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
+ }
+ if (Dbit29p2(opnd1p2)) {
+ Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+ opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
+ }
+ if (Dbit30p2(opnd1p2)) {
+ Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+ opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
+ }
+ if (Dbit31p2(opnd1p2)) {
+ Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+ opnd2p1, opnd2p2, 0, 0);
+ }
+ Dbl_rightshiftby4(opnd1p1,opnd1p2);
+ }
+ if (Is_dexthiddenoverflow(tmpresp1)) {
+ /* result mantissa >= 2 (mantissa overflow) */
+ mpy_exponent++;
+ Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+ }
+
+ /*
+ * Restore the sign of the mpy result which was saved in resultp1.
+ * The exponent will continue to be kept in mpy_exponent.
+ */
+ Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
+
+ /*
+ * No rounding is required, since the result of the multiply
+ * is exact in the extended format.
+ */
+
+ /*
+ * Now we are ready to perform the add portion of the operation.
+ *
+ * The exponents need to be kept as integers for now, since the
+ * multiply result might not fit into the exponent field. We
+ * can't overflow or underflow because of this yet, since the
+ * add could bring the final result back into range.
+ */
+ add_exponent = Dbl_exponent(opnd3p1);
+
+ /*
+ * Check for denormalized or zero add operand.
+ */
+ if (add_exponent == 0) {
+ /* check for zero */
+ if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
+ /* right is zero */
+ /* Left can't be zero and must be result.
+ *
+ * The final result is now in tmpres and mpy_exponent,
+ * and needs to be rounded and squeezed back into
+ * double precision format from double extended.
+ */
+ result_exponent = mpy_exponent;
+ Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+ resultp1,resultp2,resultp3,resultp4);
+ sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
+ goto round;
+ }
+
+ /*
+ * Neither are zeroes.
+ * Adjust exponent and normalize add operand.
+ */
+ sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */
+ Dbl_clear_signexponent(opnd3p1);
+ Dbl_leftshiftby1(opnd3p1,opnd3p2);
+ Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
+ Dbl_set_sign(opnd3p1,sign_save); /* restore sign */
+ } else {
+ Dbl_clear_exponent_set_hidden(opnd3p1);
+ }
+ /*
+ * Copy opnd3 to the double extended variable called right.
+ */
+ Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
+
+ /*
+ * A zero "save" helps discover equal operands (for later),
+ * and is used in swapping operands (if needed).
+ */
+ Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
+
+ /*
+ * Compare magnitude of operands.
+ */
+ Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
+ Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
+ if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
+ Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
+ /*
+ * Set the left operand to the larger one by XOR swap.
+ * First finish the first word "save".
+ */
+ Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
+ Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
+ Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
+ rightp2,rightp3,rightp4);
+ /* also setup exponents used in rest of routine */
+ diff_exponent = add_exponent - mpy_exponent;
+ result_exponent = add_exponent;
+ } else {
+ /* also setup exponents used in rest of routine */
+ diff_exponent = mpy_exponent - add_exponent;
+ result_exponent = mpy_exponent;
+ }
+ /* Invariant: left is not smaller than right. */
+
+ /*
+ * Special case alignment of operands that would force alignment
+ * beyond the extent of the extension. A further optimization
+ * could special case this but only reduces the path length for
+ * this infrequent case.
+ */
+ if (diff_exponent > DBLEXT_THRESHOLD) {
+ diff_exponent = DBLEXT_THRESHOLD;
+ }
+
+ /* Align right operand by shifting it to the right */
+ Dblext_clear_sign(rightp1);
+ Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
+ /*shifted by*/diff_exponent);
+
+ /* Treat sum and difference of the operands separately. */
+ if ((int)save < 0) {
+ /*
+ * Difference of the two operands. Overflow can occur if the
+ * multiply overflowed. A borrow can occur out of the hidden
+ * bit and force a post normalization phase.
+ */
+ Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+ rightp1,rightp2,rightp3,rightp4,
+ resultp1,resultp2,resultp3,resultp4);
+ sign_save = Dbl_signextendedsign(resultp1);
+ if (Dbl_iszero_hidden(resultp1)) {
+ /* Handle normalization */
+ /* A straight foward algorithm would now shift the
+ * result and extension left until the hidden bit
+ * becomes one. Not all of the extension bits need
+ * participate in the shift. Only the two most
+ * significant bits (round and guard) are needed.
+ * If only a single shift is needed then the guard
+ * bit becomes a significant low order bit and the
+ * extension must participate in the rounding.
+ * If more than a single shift is needed, then all
+ * bits to the right of the guard bit are zeros,
+ * and the guard bit may or may not be zero. */
+ Dblext_leftshiftby1(resultp1,resultp2,resultp3,
+ resultp4);
+
+ /* Need to check for a zero result. The sign and
+ * exponent fields have already been zeroed. The more
+ * efficient test of the full object can be used.
+ */
+ if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) {
+ /* Must have been "x-x" or "x+(-x)". */
+ if (Is_rounding_mode(ROUNDMINUS))
+ Dbl_setone_sign(resultp1);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ result_exponent--;
+
+ /* Look to see if normalization is finished. */
+ if (Dbl_isone_hidden(resultp1)) {
+ /* No further normalization is needed */
+ goto round;
+ }
+
+ /* Discover first one bit to determine shift amount.
+ * Use a modified binary search. We have already
+ * shifted the result one position right and still
+ * not found a one so the remainder of the extension
+ * must be zero and simplifies rounding. */
+ /* Scan bytes */
+ while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
+ Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
+ result_exponent -= 8;
+ }
+ /* Now narrow it down to the nibble */
+ if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
+ /* The lower nibble contains the
+ * normalizing one */
+ Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
+ result_exponent -= 4;
+ }
+ /* Select case where first bit is set (already
+ * normalized) otherwise select the proper shift. */
+ jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
+ if (jumpsize <= 7) switch(jumpsize) {
+ case 1:
+ Dblext_leftshiftby3(resultp1,resultp2,resultp3,
+ resultp4);
+ result_exponent -= 3;
+ break;
+ case 2:
+ case 3:
+ Dblext_leftshiftby2(resultp1,resultp2,resultp3,
+ resultp4);
+ result_exponent -= 2;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ Dblext_leftshiftby1(resultp1,resultp2,resultp3,
+ resultp4);
+ result_exponent -= 1;
+ break;
+ }
+ } /* end if (hidden...)... */
+ /* Fall through and round */
+ } /* end if (save < 0)... */
+ else {
+ /* Add magnitudes */
+ Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+ rightp1,rightp2,rightp3,rightp4,
+ /*to*/resultp1,resultp2,resultp3,resultp4);
+ sign_save = Dbl_signextendedsign(resultp1);
+ if (Dbl_isone_hiddenoverflow(resultp1)) {
+ /* Prenormalization required. */
+ Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
+ resultp4);
+ result_exponent++;
+ } /* end if hiddenoverflow... */
+ } /* end else ...add magnitudes... */
+
+ /* Round the result. If the extension and lower two words are
+ * all zeros, then the result is exact. Otherwise round in the
+ * correct direction. Underflow is possible. If a postnormalization
+ * is necessary, then the mantissa is all zeros so no shift is needed.
+ */
+ round:
+ if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
+ Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
+ result_exponent,is_tiny);
+ }
+ Dbl_set_sign(resultp1,/*using*/sign_save);
+ if (Dblext_isnotzero_mantissap3(resultp3) ||
+ Dblext_isnotzero_mantissap4(resultp4)) {
+ inexact = TRUE;
+ switch(Rounding_mode()) {
+ case ROUNDNEAREST: /* The default. */
+ if (Dblext_isone_highp3(resultp3)) {
+ /* at least 1/2 ulp */
+ if (Dblext_isnotzero_low31p3(resultp3) ||
+ Dblext_isnotzero_mantissap4(resultp4) ||
+ Dblext_isone_lowp2(resultp2)) {
+ /* either exactly half way and odd or
+ * more than 1/2ulp */
+ Dbl_increment(resultp1,resultp2);
+ }
+ }
+ break;
+
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(resultp1)) {
+ /* Round up positive results */
+ Dbl_increment(resultp1,resultp2);
+ }
+ break;
+
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(resultp1)) {
+ /* Round down negative results */
+ Dbl_increment(resultp1,resultp2);
+ }
+
+ case ROUNDZERO:;
+ /* truncate is simple */
+ } /* end switch... */
+ if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
+ }
+ if (result_exponent >= DBL_INFINITY_EXPONENT) {
+ /* Overflow */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OPC_2E_OVERFLOWEXCEPTION |
+ OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return (OPC_2E_OVERFLOWEXCEPTION);
+ }
+ inexact = TRUE;
+ Set_overflowflag();
+ Dbl_setoverflow(resultp1,resultp2);
+ } else if (result_exponent <= 0) { /* underflow case */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OPC_2E_UNDERFLOWEXCEPTION |
+ OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ else if (inexact && is_tiny) Set_underflowflag();
+ }
+ else Dbl_set_exponent(resultp1,result_exponent);
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+}
+
+/*
+ * Single Floating-point Multiply Fused Add
+ */
+
+sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+
+sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
+unsigned int *status;
+{
+ unsigned int opnd1, opnd2, opnd3;
+ register unsigned int tmpresp1, tmpresp2;
+ unsigned int rightp1, rightp2;
+ unsigned int resultp1, resultp2 = 0;
+ register int mpy_exponent, add_exponent, count;
+ boolean inexact = FALSE, is_tiny = FALSE;
+
+ unsigned int signlessleft1, signlessright1, save;
+ register int result_exponent, diff_exponent;
+ int sign_save, jumpsize;
+
+ Sgl_copyfromptr(src1ptr,opnd1);
+ Sgl_copyfromptr(src2ptr,opnd2);
+ Sgl_copyfromptr(src3ptr,opnd3);
+
+ /*
+ * set sign bit of result of multiply
+ */
+ if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2))
+ Sgl_setnegativezero(resultp1);
+ else Sgl_setzero(resultp1);
+
+ /*
+ * Generate multiply exponent
+ */
+ mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
+
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd1)) {
+ if (Sgl_iszero_mantissa(opnd1)) {
+ if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
+ if (Sgl_iszero_exponentmantissa(opnd2)) {
+ /*
+ * invalid since operands are infinity
+ * and zero
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Check third operand for infinity with a
+ * sign opposite of the multiply result
+ */
+ if (Sgl_isinfinity(opnd3) &&
+ (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
+ /*
+ * invalid since attempting a magnitude
+ * subtraction of infinities
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * return infinity
+ */
+ Sgl_setinfinity_exponentmantissa(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ Sgl_copytoptr(opnd2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is third operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd3)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd3);
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Sgl_copytoptr(opnd1,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd2)) {
+ if (Sgl_iszero_mantissa(opnd2)) {
+ if (Sgl_isnotnan(opnd3)) {
+ if (Sgl_iszero_exponentmantissa(opnd1)) {
+ /*
+ * invalid since multiply operands are
+ * zero & infinity
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(opnd2);
+ Sgl_copytoptr(opnd2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Check third operand for infinity with a
+ * sign opposite of the multiply result
+ */
+ if (Sgl_isinfinity(opnd3) &&
+ (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
+ /*
+ * invalid since attempting a magnitude
+ * subtraction of infinities
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * return infinity
+ */
+ Sgl_setinfinity_exponentmantissa(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ }
+ /*
+ * is third operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd3)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd3);
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Sgl_copytoptr(opnd2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check third operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd3)) {
+ if (Sgl_iszero_mantissa(opnd3)) {
+ /* return infinity */
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ } else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd3)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd3);
+ }
+ /*
+ * return quiet NaN
+ */
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * Generate multiply mantissa
+ */
+ if (Sgl_isnotzero_exponent(opnd1)) {
+ /* set hidden bit */
+ Sgl_clear_signexponent_set_hidden(opnd1);
+ }
+ else {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd1)) {
+ /*
+ * Perform the add opnd3 with zero here.
+ */
+ if (Sgl_iszero_exponentmantissa(opnd3)) {
+ if (Is_rounding_mode(ROUNDMINUS)) {
+ Sgl_or_signs(opnd3,resultp1);
+ } else {
+ Sgl_and_signs(opnd3,resultp1);
+ }
+ }
+ /*
+ * Now let's check for trapped underflow case.
+ */
+ else if (Sgl_iszero_exponent(opnd3) &&
+ Is_underflowtrap_enabled()) {
+ /* need to normalize results mantissa */
+ sign_save = Sgl_signextendedsign(opnd3);
+ result_exponent = 0;
+ Sgl_leftshiftby1(opnd3);
+ Sgl_normalize(opnd3,result_exponent);
+ Sgl_set_sign(opnd3,/*using*/sign_save);
+ Sgl_setwrapped_exponent(opnd3,result_exponent,
+ unfl);
+ Sgl_copytoptr(opnd3,dstptr);
+ /* inexact = FALSE */
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized, adjust exponent */
+ Sgl_clear_signexponent(opnd1);
+ Sgl_leftshiftby1(opnd1);
+ Sgl_normalize(opnd1,mpy_exponent);
+ }
+ /* opnd2 needs to have hidden bit set with msb in hidden bit */
+ if (Sgl_isnotzero_exponent(opnd2)) {
+ Sgl_clear_signexponent_set_hidden(opnd2);
+ }
+ else {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd2)) {
+ /*
+ * Perform the add opnd3 with zero here.
+ */
+ if (Sgl_iszero_exponentmantissa(opnd3)) {
+ if (Is_rounding_mode(ROUNDMINUS)) {
+ Sgl_or_signs(opnd3,resultp1);
+ } else {
+ Sgl_and_signs(opnd3,resultp1);
+ }
+ }
+ /*
+ * Now let's check for trapped underflow case.
+ */
+ else if (Sgl_iszero_exponent(opnd3) &&
+ Is_underflowtrap_enabled()) {
+ /* need to normalize results mantissa */
+ sign_save = Sgl_signextendedsign(opnd3);
+ result_exponent = 0;
+ Sgl_leftshiftby1(opnd3);
+ Sgl_normalize(opnd3,result_exponent);
+ Sgl_set_sign(opnd3,/*using*/sign_save);
+ Sgl_setwrapped_exponent(opnd3,result_exponent,
+ unfl);
+ Sgl_copytoptr(opnd3,dstptr);
+ /* inexact = FALSE */
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized; want to normalize */
+ Sgl_clear_signexponent(opnd2);
+ Sgl_leftshiftby1(opnd2);
+ Sgl_normalize(opnd2,mpy_exponent);
+ }
+
+ /* Multiply the first two source mantissas together */
+
+ /*
+ * The intermediate result will be kept in tmpres,
+ * which needs enough room for 106 bits of mantissa,
+ * so lets call it a Double extended.
+ */
+ Sglext_setzero(tmpresp1,tmpresp2);
+
+ /*
+ * Four bits at a time are inspected in each loop, and a
+ * simple shift and add multiply algorithm is used.
+ */
+ for (count = SGL_P-1; count >= 0; count -= 4) {
+ Sglext_rightshiftby4(tmpresp1,tmpresp2);
+ if (Sbit28(opnd1)) {
+ /* Twoword_add should be an ADD followed by 2 ADDC's */
+ Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
+ }
+ if (Sbit29(opnd1)) {
+ Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
+ }
+ if (Sbit30(opnd1)) {
+ Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
+ }
+ if (Sbit31(opnd1)) {
+ Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
+ }
+ Sgl_rightshiftby4(opnd1);
+ }
+ if (Is_sexthiddenoverflow(tmpresp1)) {
+ /* result mantissa >= 2 (mantissa overflow) */
+ mpy_exponent++;
+ Sglext_rightshiftby4(tmpresp1,tmpresp2);
+ } else {
+ Sglext_rightshiftby3(tmpresp1,tmpresp2);
+ }
+
+ /*
+ * Restore the sign of the mpy result which was saved in resultp1.
+ * The exponent will continue to be kept in mpy_exponent.
+ */
+ Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
+
+ /*
+ * No rounding is required, since the result of the multiply
+ * is exact in the extended format.
+ */
+
+ /*
+ * Now we are ready to perform the add portion of the operation.
+ *
+ * The exponents need to be kept as integers for now, since the
+ * multiply result might not fit into the exponent field. We
+ * can't overflow or underflow because of this yet, since the
+ * add could bring the final result back into range.
+ */
+ add_exponent = Sgl_exponent(opnd3);
+
+ /*
+ * Check for denormalized or zero add operand.
+ */
+ if (add_exponent == 0) {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd3)) {
+ /* right is zero */
+ /* Left can't be zero and must be result.
+ *
+ * The final result is now in tmpres and mpy_exponent,
+ * and needs to be rounded and squeezed back into
+ * double precision format from double extended.
+ */
+ result_exponent = mpy_exponent;
+ Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
+ sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
+ goto round;
+ }
+
+ /*
+ * Neither are zeroes.
+ * Adjust exponent and normalize add operand.
+ */
+ sign_save = Sgl_signextendedsign(opnd3); /* save sign */
+ Sgl_clear_signexponent(opnd3);
+ Sgl_leftshiftby1(opnd3);
+ Sgl_normalize(opnd3,add_exponent);
+ Sgl_set_sign(opnd3,sign_save); /* restore sign */
+ } else {
+ Sgl_clear_exponent_set_hidden(opnd3);
+ }
+ /*
+ * Copy opnd3 to the double extended variable called right.
+ */
+ Sgl_copyto_sglext(opnd3,rightp1,rightp2);
+
+ /*
+ * A zero "save" helps discover equal operands (for later),
+ * and is used in swapping operands (if needed).
+ */
+ Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
+
+ /*
+ * Compare magnitude of operands.
+ */
+ Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
+ Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
+ if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
+ Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
+ /*
+ * Set the left operand to the larger one by XOR swap.
+ * First finish the first word "save".
+ */
+ Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
+ Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
+ Sglext_swap_lower(tmpresp2,rightp2);
+ /* also setup exponents used in rest of routine */
+ diff_exponent = add_exponent - mpy_exponent;
+ result_exponent = add_exponent;
+ } else {
+ /* also setup exponents used in rest of routine */
+ diff_exponent = mpy_exponent - add_exponent;
+ result_exponent = mpy_exponent;
+ }
+ /* Invariant: left is not smaller than right. */
+
+ /*
+ * Special case alignment of operands that would force alignment
+ * beyond the extent of the extension. A further optimization
+ * could special case this but only reduces the path length for
+ * this infrequent case.
+ */
+ if (diff_exponent > SGLEXT_THRESHOLD) {
+ diff_exponent = SGLEXT_THRESHOLD;
+ }
+
+ /* Align right operand by shifting it to the right */
+ Sglext_clear_sign(rightp1);
+ Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
+
+ /* Treat sum and difference of the operands separately. */
+ if ((int)save < 0) {
+ /*
+ * Difference of the two operands. Overflow can occur if the
+ * multiply overflowed. A borrow can occur out of the hidden
+ * bit and force a post normalization phase.
+ */
+ Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
+ resultp1,resultp2);
+ sign_save = Sgl_signextendedsign(resultp1);
+ if (Sgl_iszero_hidden(resultp1)) {
+ /* Handle normalization */
+ /* A straight foward algorithm would now shift the
+ * result and extension left until the hidden bit
+ * becomes one. Not all of the extension bits need
+ * participate in the shift. Only the two most
+ * significant bits (round and guard) are needed.
+ * If only a single shift is needed then the guard
+ * bit becomes a significant low order bit and the
+ * extension must participate in the rounding.
+ * If more than a single shift is needed, then all
+ * bits to the right of the guard bit are zeros,
+ * and the guard bit may or may not be zero. */
+ Sglext_leftshiftby1(resultp1,resultp2);
+
+ /* Need to check for a zero result. The sign and
+ * exponent fields have already been zeroed. The more
+ * efficient test of the full object can be used.
+ */
+ if (Sglext_iszero(resultp1,resultp2)) {
+ /* Must have been "x-x" or "x+(-x)". */
+ if (Is_rounding_mode(ROUNDMINUS))
+ Sgl_setone_sign(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+ result_exponent--;
+
+ /* Look to see if normalization is finished. */
+ if (Sgl_isone_hidden(resultp1)) {
+ /* No further normalization is needed */
+ goto round;
+ }
+
+ /* Discover first one bit to determine shift amount.
+ * Use a modified binary search. We have already
+ * shifted the result one position right and still
+ * not found a one so the remainder of the extension
+ * must be zero and simplifies rounding. */
+ /* Scan bytes */
+ while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
+ Sglext_leftshiftby8(resultp1,resultp2);
+ result_exponent -= 8;
+ }
+ /* Now narrow it down to the nibble */
+ if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
+ /* The lower nibble contains the
+ * normalizing one */
+ Sglext_leftshiftby4(resultp1,resultp2);
+ result_exponent -= 4;
+ }
+ /* Select case where first bit is set (already
+ * normalized) otherwise select the proper shift. */
+ jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
+ if (jumpsize <= 7) switch(jumpsize) {
+ case 1:
+ Sglext_leftshiftby3(resultp1,resultp2);
+ result_exponent -= 3;
+ break;
+ case 2:
+ case 3:
+ Sglext_leftshiftby2(resultp1,resultp2);
+ result_exponent -= 2;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ Sglext_leftshiftby1(resultp1,resultp2);
+ result_exponent -= 1;
+ break;
+ }
+ } /* end if (hidden...)... */
+ /* Fall through and round */
+ } /* end if (save < 0)... */
+ else {
+ /* Add magnitudes */
+ Sglext_addition(tmpresp1,tmpresp2,
+ rightp1,rightp2, /*to*/resultp1,resultp2);
+ sign_save = Sgl_signextendedsign(resultp1);
+ if (Sgl_isone_hiddenoverflow(resultp1)) {
+ /* Prenormalization required. */
+ Sglext_arithrightshiftby1(resultp1,resultp2);
+ result_exponent++;
+ } /* end if hiddenoverflow... */
+ } /* end else ...add magnitudes... */
+
+ /* Round the result. If the extension and lower two words are
+ * all zeros, then the result is exact. Otherwise round in the
+ * correct direction. Underflow is possible. If a postnormalization
+ * is necessary, then the mantissa is all zeros so no shift is needed.
+ */
+ round:
+ if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
+ Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
+ }
+ Sgl_set_sign(resultp1,/*using*/sign_save);
+ if (Sglext_isnotzero_mantissap2(resultp2)) {
+ inexact = TRUE;
+ switch(Rounding_mode()) {
+ case ROUNDNEAREST: /* The default. */
+ if (Sglext_isone_highp2(resultp2)) {
+ /* at least 1/2 ulp */
+ if (Sglext_isnotzero_low31p2(resultp2) ||
+ Sglext_isone_lowp1(resultp1)) {
+ /* either exactly half way and odd or
+ * more than 1/2ulp */
+ Sgl_increment(resultp1);
+ }
+ }
+ break;
+
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(resultp1)) {
+ /* Round up positive results */
+ Sgl_increment(resultp1);
+ }
+ break;
+
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(resultp1)) {
+ /* Round down negative results */
+ Sgl_increment(resultp1);
+ }
+
+ case ROUNDZERO:;
+ /* truncate is simple */
+ } /* end switch... */
+ if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
+ }
+ if (result_exponent >= SGL_INFINITY_EXPONENT) {
+ /* Overflow */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+ Sgl_copytoptr(resultp1,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OPC_2E_OVERFLOWEXCEPTION |
+ OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return (OPC_2E_OVERFLOWEXCEPTION);
+ }
+ inexact = TRUE;
+ Set_overflowflag();
+ Sgl_setoverflow(resultp1);
+ } else if (result_exponent <= 0) { /* underflow case */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
+ Sgl_copytoptr(resultp1,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OPC_2E_UNDERFLOWEXCEPTION |
+ OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ else if (inexact && is_tiny) Set_underflowflag();
+ }
+ else Sgl_set_exponent(resultp1,result_exponent);
+ Sgl_copytoptr(resultp1,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+}
+
+/*
+ * Single Floating-point Multiply Negate Fused Add
+ */
+
+sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+
+sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
+unsigned int *status;
+{
+ unsigned int opnd1, opnd2, opnd3;
+ register unsigned int tmpresp1, tmpresp2;
+ unsigned int rightp1, rightp2;
+ unsigned int resultp1, resultp2 = 0;
+ register int mpy_exponent, add_exponent, count;
+ boolean inexact = FALSE, is_tiny = FALSE;
+
+ unsigned int signlessleft1, signlessright1, save;
+ register int result_exponent, diff_exponent;
+ int sign_save, jumpsize;
+
+ Sgl_copyfromptr(src1ptr,opnd1);
+ Sgl_copyfromptr(src2ptr,opnd2);
+ Sgl_copyfromptr(src3ptr,opnd3);
+
+ /*
+ * set sign bit of result of multiply
+ */
+ if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2))
+ Sgl_setzero(resultp1);
+ else
+ Sgl_setnegativezero(resultp1);
+
+ /*
+ * Generate multiply exponent
+ */
+ mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
+
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd1)) {
+ if (Sgl_iszero_mantissa(opnd1)) {
+ if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
+ if (Sgl_iszero_exponentmantissa(opnd2)) {
+ /*
+ * invalid since operands are infinity
+ * and zero
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Check third operand for infinity with a
+ * sign opposite of the multiply result
+ */
+ if (Sgl_isinfinity(opnd3) &&
+ (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
+ /*
+ * invalid since attempting a magnitude
+ * subtraction of infinities
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * return infinity
+ */
+ Sgl_setinfinity_exponentmantissa(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ Sgl_copytoptr(opnd2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * is third operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd3)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd3);
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Sgl_copytoptr(opnd1,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd2)) {
+ if (Sgl_iszero_mantissa(opnd2)) {
+ if (Sgl_isnotnan(opnd3)) {
+ if (Sgl_iszero_exponentmantissa(opnd1)) {
+ /*
+ * invalid since multiply operands are
+ * zero & infinity
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(opnd2);
+ Sgl_copytoptr(opnd2,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Check third operand for infinity with a
+ * sign opposite of the multiply result
+ */
+ if (Sgl_isinfinity(opnd3) &&
+ (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
+ /*
+ * invalid since attempting a magnitude
+ * subtraction of infinities
+ */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * return infinity
+ */
+ Sgl_setinfinity_exponentmantissa(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ }
+ /*
+ * is third operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd3)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd3);
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ Sgl_copytoptr(opnd2,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check third operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd3)) {
+ if (Sgl_iszero_mantissa(opnd3)) {
+ /* return infinity */
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ } else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd3)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(OPC_2E_INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd3);
+ }
+ /*
+ * return quiet NaN
+ */
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * Generate multiply mantissa
+ */
+ if (Sgl_isnotzero_exponent(opnd1)) {
+ /* set hidden bit */
+ Sgl_clear_signexponent_set_hidden(opnd1);
+ }
+ else {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd1)) {
+ /*
+ * Perform the add opnd3 with zero here.
+ */
+ if (Sgl_iszero_exponentmantissa(opnd3)) {
+ if (Is_rounding_mode(ROUNDMINUS)) {
+ Sgl_or_signs(opnd3,resultp1);
+ } else {
+ Sgl_and_signs(opnd3,resultp1);
+ }
+ }
+ /*
+ * Now let's check for trapped underflow case.
+ */
+ else if (Sgl_iszero_exponent(opnd3) &&
+ Is_underflowtrap_enabled()) {
+ /* need to normalize results mantissa */
+ sign_save = Sgl_signextendedsign(opnd3);
+ result_exponent = 0;
+ Sgl_leftshiftby1(opnd3);
+ Sgl_normalize(opnd3,result_exponent);
+ Sgl_set_sign(opnd3,/*using*/sign_save);
+ Sgl_setwrapped_exponent(opnd3,result_exponent,
+ unfl);
+ Sgl_copytoptr(opnd3,dstptr);
+ /* inexact = FALSE */
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized, adjust exponent */
+ Sgl_clear_signexponent(opnd1);
+ Sgl_leftshiftby1(opnd1);
+ Sgl_normalize(opnd1,mpy_exponent);
+ }
+ /* opnd2 needs to have hidden bit set with msb in hidden bit */
+ if (Sgl_isnotzero_exponent(opnd2)) {
+ Sgl_clear_signexponent_set_hidden(opnd2);
+ }
+ else {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd2)) {
+ /*
+ * Perform the add opnd3 with zero here.
+ */
+ if (Sgl_iszero_exponentmantissa(opnd3)) {
+ if (Is_rounding_mode(ROUNDMINUS)) {
+ Sgl_or_signs(opnd3,resultp1);
+ } else {
+ Sgl_and_signs(opnd3,resultp1);
+ }
+ }
+ /*
+ * Now let's check for trapped underflow case.
+ */
+ else if (Sgl_iszero_exponent(opnd3) &&
+ Is_underflowtrap_enabled()) {
+ /* need to normalize results mantissa */
+ sign_save = Sgl_signextendedsign(opnd3);
+ result_exponent = 0;
+ Sgl_leftshiftby1(opnd3);
+ Sgl_normalize(opnd3,result_exponent);
+ Sgl_set_sign(opnd3,/*using*/sign_save);
+ Sgl_setwrapped_exponent(opnd3,result_exponent,
+ unfl);
+ Sgl_copytoptr(opnd3,dstptr);
+ /* inexact = FALSE */
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ Sgl_copytoptr(opnd3,dstptr);
+ return(NOEXCEPTION);
+ }
+ /* is denormalized; want to normalize */
+ Sgl_clear_signexponent(opnd2);
+ Sgl_leftshiftby1(opnd2);
+ Sgl_normalize(opnd2,mpy_exponent);
+ }
+
+ /* Multiply the first two source mantissas together */
+
+ /*
+ * The intermediate result will be kept in tmpres,
+ * which needs enough room for 106 bits of mantissa,
+ * so lets call it a Double extended.
+ */
+ Sglext_setzero(tmpresp1,tmpresp2);
+
+ /*
+ * Four bits at a time are inspected in each loop, and a
+ * simple shift and add multiply algorithm is used.
+ */
+ for (count = SGL_P-1; count >= 0; count -= 4) {
+ Sglext_rightshiftby4(tmpresp1,tmpresp2);
+ if (Sbit28(opnd1)) {
+ /* Twoword_add should be an ADD followed by 2 ADDC's */
+ Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
+ }
+ if (Sbit29(opnd1)) {
+ Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
+ }
+ if (Sbit30(opnd1)) {
+ Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
+ }
+ if (Sbit31(opnd1)) {
+ Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
+ }
+ Sgl_rightshiftby4(opnd1);
+ }
+ if (Is_sexthiddenoverflow(tmpresp1)) {
+ /* result mantissa >= 2 (mantissa overflow) */
+ mpy_exponent++;
+ Sglext_rightshiftby4(tmpresp1,tmpresp2);
+ } else {
+ Sglext_rightshiftby3(tmpresp1,tmpresp2);
+ }
+
+ /*
+ * Restore the sign of the mpy result which was saved in resultp1.
+ * The exponent will continue to be kept in mpy_exponent.
+ */
+ Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
+
+ /*
+ * No rounding is required, since the result of the multiply
+ * is exact in the extended format.
+ */
+
+ /*
+ * Now we are ready to perform the add portion of the operation.
+ *
+ * The exponents need to be kept as integers for now, since the
+ * multiply result might not fit into the exponent field. We
+ * can't overflow or underflow because of this yet, since the
+ * add could bring the final result back into range.
+ */
+ add_exponent = Sgl_exponent(opnd3);
+
+ /*
+ * Check for denormalized or zero add operand.
+ */
+ if (add_exponent == 0) {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd3)) {
+ /* right is zero */
+ /* Left can't be zero and must be result.
+ *
+ * The final result is now in tmpres and mpy_exponent,
+ * and needs to be rounded and squeezed back into
+ * double precision format from double extended.
+ */
+ result_exponent = mpy_exponent;
+ Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
+ sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
+ goto round;
+ }
+
+ /*
+ * Neither are zeroes.
+ * Adjust exponent and normalize add operand.
+ */
+ sign_save = Sgl_signextendedsign(opnd3); /* save sign */
+ Sgl_clear_signexponent(opnd3);
+ Sgl_leftshiftby1(opnd3);
+ Sgl_normalize(opnd3,add_exponent);
+ Sgl_set_sign(opnd3,sign_save); /* restore sign */
+ } else {
+ Sgl_clear_exponent_set_hidden(opnd3);
+ }
+ /*
+ * Copy opnd3 to the double extended variable called right.
+ */
+ Sgl_copyto_sglext(opnd3,rightp1,rightp2);
+
+ /*
+ * A zero "save" helps discover equal operands (for later),
+ * and is used in swapping operands (if needed).
+ */
+ Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
+
+ /*
+ * Compare magnitude of operands.
+ */
+ Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
+ Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
+ if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
+ Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
+ /*
+ * Set the left operand to the larger one by XOR swap.
+ * First finish the first word "save".
+ */
+ Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
+ Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
+ Sglext_swap_lower(tmpresp2,rightp2);
+ /* also setup exponents used in rest of routine */
+ diff_exponent = add_exponent - mpy_exponent;
+ result_exponent = add_exponent;
+ } else {
+ /* also setup exponents used in rest of routine */
+ diff_exponent = mpy_exponent - add_exponent;
+ result_exponent = mpy_exponent;
+ }
+ /* Invariant: left is not smaller than right. */
+
+ /*
+ * Special case alignment of operands that would force alignment
+ * beyond the extent of the extension. A further optimization
+ * could special case this but only reduces the path length for
+ * this infrequent case.
+ */
+ if (diff_exponent > SGLEXT_THRESHOLD) {
+ diff_exponent = SGLEXT_THRESHOLD;
+ }
+
+ /* Align right operand by shifting it to the right */
+ Sglext_clear_sign(rightp1);
+ Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
+
+ /* Treat sum and difference of the operands separately. */
+ if ((int)save < 0) {
+ /*
+ * Difference of the two operands. Overflow can occur if the
+ * multiply overflowed. A borrow can occur out of the hidden
+ * bit and force a post normalization phase.
+ */
+ Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
+ resultp1,resultp2);
+ sign_save = Sgl_signextendedsign(resultp1);
+ if (Sgl_iszero_hidden(resultp1)) {
+ /* Handle normalization */
+ /* A straight foward algorithm would now shift the
+ * result and extension left until the hidden bit
+ * becomes one. Not all of the extension bits need
+ * participate in the shift. Only the two most
+ * significant bits (round and guard) are needed.
+ * If only a single shift is needed then the guard
+ * bit becomes a significant low order bit and the
+ * extension must participate in the rounding.
+ * If more than a single shift is needed, then all
+ * bits to the right of the guard bit are zeros,
+ * and the guard bit may or may not be zero. */
+ Sglext_leftshiftby1(resultp1,resultp2);
+
+ /* Need to check for a zero result. The sign and
+ * exponent fields have already been zeroed. The more
+ * efficient test of the full object can be used.
+ */
+ if (Sglext_iszero(resultp1,resultp2)) {
+ /* Must have been "x-x" or "x+(-x)". */
+ if (Is_rounding_mode(ROUNDMINUS))
+ Sgl_setone_sign(resultp1);
+ Sgl_copytoptr(resultp1,dstptr);
+ return(NOEXCEPTION);
+ }
+ result_exponent--;
+
+ /* Look to see if normalization is finished. */
+ if (Sgl_isone_hidden(resultp1)) {
+ /* No further normalization is needed */
+ goto round;
+ }
+
+ /* Discover first one bit to determine shift amount.
+ * Use a modified binary search. We have already
+ * shifted the result one position right and still
+ * not found a one so the remainder of the extension
+ * must be zero and simplifies rounding. */
+ /* Scan bytes */
+ while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
+ Sglext_leftshiftby8(resultp1,resultp2);
+ result_exponent -= 8;
+ }
+ /* Now narrow it down to the nibble */
+ if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
+ /* The lower nibble contains the
+ * normalizing one */
+ Sglext_leftshiftby4(resultp1,resultp2);
+ result_exponent -= 4;
+ }
+ /* Select case where first bit is set (already
+ * normalized) otherwise select the proper shift. */
+ jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
+ if (jumpsize <= 7) switch(jumpsize) {
+ case 1:
+ Sglext_leftshiftby3(resultp1,resultp2);
+ result_exponent -= 3;
+ break;
+ case 2:
+ case 3:
+ Sglext_leftshiftby2(resultp1,resultp2);
+ result_exponent -= 2;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ Sglext_leftshiftby1(resultp1,resultp2);
+ result_exponent -= 1;
+ break;
+ }
+ } /* end if (hidden...)... */
+ /* Fall through and round */
+ } /* end if (save < 0)... */
+ else {
+ /* Add magnitudes */
+ Sglext_addition(tmpresp1,tmpresp2,
+ rightp1,rightp2, /*to*/resultp1,resultp2);
+ sign_save = Sgl_signextendedsign(resultp1);
+ if (Sgl_isone_hiddenoverflow(resultp1)) {
+ /* Prenormalization required. */
+ Sglext_arithrightshiftby1(resultp1,resultp2);
+ result_exponent++;
+ } /* end if hiddenoverflow... */
+ } /* end else ...add magnitudes... */
+
+ /* Round the result. If the extension and lower two words are
+ * all zeros, then the result is exact. Otherwise round in the
+ * correct direction. Underflow is possible. If a postnormalization
+ * is necessary, then the mantissa is all zeros so no shift is needed.
+ */
+ round:
+ if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
+ Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
+ }
+ Sgl_set_sign(resultp1,/*using*/sign_save);
+ if (Sglext_isnotzero_mantissap2(resultp2)) {
+ inexact = TRUE;
+ switch(Rounding_mode()) {
+ case ROUNDNEAREST: /* The default. */
+ if (Sglext_isone_highp2(resultp2)) {
+ /* at least 1/2 ulp */
+ if (Sglext_isnotzero_low31p2(resultp2) ||
+ Sglext_isone_lowp1(resultp1)) {
+ /* either exactly half way and odd or
+ * more than 1/2ulp */
+ Sgl_increment(resultp1);
+ }
+ }
+ break;
+
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(resultp1)) {
+ /* Round up positive results */
+ Sgl_increment(resultp1);
+ }
+ break;
+
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(resultp1)) {
+ /* Round down negative results */
+ Sgl_increment(resultp1);
+ }
+
+ case ROUNDZERO:;
+ /* truncate is simple */
+ } /* end switch... */
+ if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
+ }
+ if (result_exponent >= SGL_INFINITY_EXPONENT) {
+ /* Overflow */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+ Sgl_copytoptr(resultp1,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OPC_2E_OVERFLOWEXCEPTION |
+ OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return (OPC_2E_OVERFLOWEXCEPTION);
+ }
+ inexact = TRUE;
+ Set_overflowflag();
+ Sgl_setoverflow(resultp1);
+ } else if (result_exponent <= 0) { /* underflow case */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
+ Sgl_copytoptr(resultp1,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return (OPC_2E_UNDERFLOWEXCEPTION |
+ OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OPC_2E_UNDERFLOWEXCEPTION);
+ }
+ else if (inexact && is_tiny) Set_underflowflag();
+ }
+ else Sgl_set_exponent(resultp1,result_exponent);
+ Sgl_copytoptr(resultp1,dstptr);
+ if (inexact)
+ if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+}
+
diff --git a/arch/parisc/math-emu/fpbits.h b/arch/parisc/math-emu/fpbits.h
new file mode 100644
index 000000000000..cefad064d74a
--- /dev/null
+++ b/arch/parisc/math-emu/fpbits.h
@@ -0,0 +1,65 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef __NO_PA_HDRS
+ PA header file -- do not include this header file for non-PA builds.
+#endif
+
+
+/*
+ * These macros are designed to be portable to all machines that have
+ * a wordsize greater than or equal to 32 bits that support the portable
+ * C compiler and the standard C preprocessor. Wordsize (default 32)
+ * and bitfield assignment (default left-to-right, unlike VAX, PDP-11)
+ * should be predefined using the constants HOSTWDSZ and BITFRL and
+ * the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20).
+ * Note that the macro arguments assume that the integer being referenced
+ * is a 32-bit integer (right-justified on the 20) and that bit 0 is the
+ * most significant bit.
+ */
+
+#ifndef HOSTWDSZ
+#define HOSTWDSZ 32
+#endif
+
+
+/*########################### Macros ######################################*/
+
+/*-------------------------------------------------------------------------
+ * NewDeclareBitField_Reference - Declare a structure similar to the simulator
+ * function "DeclBitfR" except its use is restricted to occur within a larger
+ * enclosing structure or union definition. This declaration is an unnamed
+ * structure with the argument, name, as the member name and the argument,
+ * uname, as the element name.
+ *----------------------------------------------------------------------- */
+#define Bitfield_extract(start, length, object) \
+ ((object) >> (HOSTWDSZ - (start) - (length)) & \
+ ((unsigned)-1 >> (HOSTWDSZ - (length))))
+
+#define Bitfield_signed_extract(start, length, object) \
+ ((int)((object) << start) >> (HOSTWDSZ - (length)))
+
+#define Bitfield_mask(start, len, object) \
+ ((object) & (((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len)))
+
+#define Bitfield_deposit(value,start,len,object) object = \
+ ((object) & ~(((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | \
+ (((value) & ((unsigned)-1 >> (HOSTWDSZ-len))) << (HOSTWDSZ-start-len))
diff --git a/arch/parisc/math-emu/fpu.h b/arch/parisc/math-emu/fpu.h
new file mode 100644
index 000000000000..0af5c3c88949
--- /dev/null
+++ b/arch/parisc/math-emu/fpu.h
@@ -0,0 +1,76 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/fp/fpu.h $Revision: 1.1 $
+ *
+ * Purpose:
+ * <<please update with a synopis of the functionality provided by this file>>
+ *
+ *
+ * END_DESC
+*/
+
+#ifdef __NO_PA_HDRS
+ PA header file -- do not include this header file for non-PA builds.
+#endif
+
+
+#ifndef _MACHINE_FPU_INCLUDED /* allows multiple inclusion */
+#define _MACHINE_FPU_INCLUDED
+
+#if 0
+#ifndef _SYS_STDSYMS_INCLUDED
+# include <sys/stdsyms.h>
+#endif /* _SYS_STDSYMS_INCLUDED */
+#include <machine/pdc/pdc_rqsts.h>
+#endif
+
+#define PA83_FPU_FLAG 0x00000001
+#define PA89_FPU_FLAG 0x00000002
+#define PA2_0_FPU_FLAG 0x00000010
+
+#define TIMEX_EXTEN_FLAG 0x00000004
+
+#define ROLEX_EXTEN_FLAG 0x00000008
+#define COPR_FP 0x00000080 /* Floating point -- Coprocessor 0 */
+#define SFU_MPY_DIVIDE 0x00008000 /* Multiply/Divide __ SFU 0 */
+
+
+#define EM_FPU_TYPE_OFFSET 272
+
+/* version of EMULATION software for COPR,0,0 instruction */
+#define EMULATION_VERSION 4
+
+/*
+ * The only was to differeniate between TIMEX and ROLEX (or PCX-S and PCX-T)
+ * is thorough the potential type field from the PDC_MODEL call. The
+ * following flags are used at assist this differeniation.
+ */
+
+#define ROLEX_POTENTIAL_KEY_FLAGS PDC_MODEL_CPU_KEY_WORD_TO_IO
+#define TIMEX_POTENTIAL_KEY_FLAGS (PDC_MODEL_CPU_KEY_QUAD_STORE | \
+ PDC_MODEL_CPU_KEY_RECIP_SQRT)
+
+
+#endif /* ! _MACHINE_FPU_INCLUDED */
diff --git a/arch/parisc/math-emu/fpudispatch.c b/arch/parisc/math-emu/fpudispatch.c
new file mode 100644
index 000000000000..6e28f9f4c620
--- /dev/null
+++ b/arch/parisc/math-emu/fpudispatch.c
@@ -0,0 +1,1442 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * <<please update with a synopsis of the functionality provided by this file>>
+ *
+ * External Interfaces:
+ * <<the following list was autogenerated, please review>>
+ * emfpudispatch(ir, dummy1, dummy2, fpregs)
+ * fpudispatch(ir, excp_code, holder, fpregs)
+ *
+ * Internal Interfaces:
+ * <<the following list was autogenerated, please review>>
+ * static u_int decode_06(u_int, u_int *)
+ * static u_int decode_0c(u_int, u_int, u_int, u_int *)
+ * static u_int decode_0e(u_int, u_int, u_int, u_int *)
+ * static u_int decode_26(u_int, u_int *)
+ * static u_int decode_2e(u_int, u_int *)
+ * static void update_status_cbit(u_int *, u_int, u_int, u_int)
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+#define FPUDEBUG 0
+
+#include "float.h"
+#include <linux/kernel.h>
+#include <asm/processor.h>
+/* #include <sys/debug.h> */
+/* #include <machine/sys/mdep_private.h> */
+
+#define COPR_INST 0x30000000
+
+/*
+ * definition of extru macro. If pos and len are constants, the compiler
+ * will generate an extru instruction when optimized
+ */
+#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
+/* definitions of bit field locations in the instruction */
+#define fpmajorpos 5
+#define fpr1pos 10
+#define fpr2pos 15
+#define fptpos 31
+#define fpsubpos 18
+#define fpclass1subpos 16
+#define fpclasspos 22
+#define fpfmtpos 20
+#define fpdfpos 18
+#define fpnulpos 26
+/*
+ * the following are the extra bits for the 0E major op
+ */
+#define fpxr1pos 24
+#define fpxr2pos 19
+#define fpxtpos 25
+#define fpxpos 23
+#define fp0efmtpos 20
+/*
+ * the following are for the multi-ops
+ */
+#define fprm1pos 10
+#define fprm2pos 15
+#define fptmpos 31
+#define fprapos 25
+#define fptapos 20
+#define fpmultifmt 26
+/*
+ * the following are for the fused FP instructions
+ */
+ /* fprm1pos 10 */
+ /* fprm2pos 15 */
+#define fpraupos 18
+#define fpxrm2pos 19
+ /* fpfmtpos 20 */
+#define fpralpos 23
+#define fpxrm1pos 24
+ /* fpxtpos 25 */
+#define fpfusedsubop 26
+ /* fptpos 31 */
+
+/*
+ * offset to constant zero in the FP emulation registers
+ */
+#define fpzeroreg (32*sizeof(double)/sizeof(u_int))
+
+/*
+ * extract the major opcode from the instruction
+ */
+#define get_major(op) extru(op,fpmajorpos,6)
+/*
+ * extract the two bit class field from the FP instruction. The class is at bit
+ * positions 21-22
+ */
+#define get_class(op) extru(op,fpclasspos,2)
+/*
+ * extract the 3 bit subop field. For all but class 1 instructions, it is
+ * located at bit positions 16-18
+ */
+#define get_subop(op) extru(op,fpsubpos,3)
+/*
+ * extract the 2 or 3 bit subop field from class 1 instructions. It is located
+ * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
+ */
+#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */
+#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */
+
+/* definitions of unimplemented exceptions */
+#define MAJOR_0C_EXCP 0x09
+#define MAJOR_0E_EXCP 0x0b
+#define MAJOR_06_EXCP 0x03
+#define MAJOR_26_EXCP 0x23
+#define MAJOR_2E_EXCP 0x2b
+#define PA83_UNIMP_EXCP 0x01
+
+/*
+ * Special Defines for TIMEX specific code
+ */
+
+#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
+#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
+
+/*
+ * Static function definitions
+ */
+#define _PROTOTYPES
+#if defined(_PROTOTYPES) || defined(_lint)
+static u_int decode_0c(u_int, u_int, u_int, u_int *);
+static u_int decode_0e(u_int, u_int, u_int, u_int *);
+static u_int decode_06(u_int, u_int *);
+static u_int decode_26(u_int, u_int *);
+static u_int decode_2e(u_int, u_int *);
+static void update_status_cbit(u_int *, u_int, u_int, u_int);
+#else /* !_PROTOTYPES&&!_lint */
+static u_int decode_0c();
+static u_int decode_0e();
+static u_int decode_06();
+static u_int decode_26();
+static u_int decode_2e();
+static void update_status_cbit();
+#endif /* _PROTOTYPES&&!_lint */
+
+#define VASSERT(x)
+
+static void parisc_linux_get_fpu_type(u_int fpregs[])
+{
+ /* on pa-linux the fpu type is not filled in by the
+ * caller; it is constructed here
+ */
+ if (boot_cpu_data.cpu_type == pcxs)
+ fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
+ else if (boot_cpu_data.cpu_type == pcxt ||
+ boot_cpu_data.cpu_type == pcxt_)
+ fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
+ else if (boot_cpu_data.cpu_type >= pcxu)
+ fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
+}
+
+/*
+ * this routine will decode the excepting floating point instruction and
+ * call the approiate emulation routine.
+ * It is called by decode_fpu with the following parameters:
+ * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
+ * where current_ir is the instruction to be emulated,
+ * unimplemented_code is the exception_code that the hardware generated
+ * and &Fpu_register is the address of emulated FP reg 0.
+ */
+u_int
+fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
+{
+ u_int class, subop;
+ u_int fpu_type_flags;
+
+ /* All FP emulation code assumes that ints are 4-bytes in length */
+ VASSERT(sizeof(int) == 4);
+
+ parisc_linux_get_fpu_type(fpregs);
+
+ fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
+
+ class = get_class(ir);
+ if (class == 1) {
+ if (fpu_type_flags & PA2_0_FPU_FLAG)
+ subop = get_subop1_PA2_0(ir);
+ else
+ subop = get_subop1_PA1_1(ir);
+ }
+ else
+ subop = get_subop(ir);
+
+ if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
+
+ switch (excp_code) {
+ case MAJOR_0C_EXCP:
+ case PA83_UNIMP_EXCP:
+ return(decode_0c(ir,class,subop,fpregs));
+ case MAJOR_0E_EXCP:
+ return(decode_0e(ir,class,subop,fpregs));
+ case MAJOR_06_EXCP:
+ return(decode_06(ir,fpregs));
+ case MAJOR_26_EXCP:
+ return(decode_26(ir,fpregs));
+ case MAJOR_2E_EXCP:
+ return(decode_2e(ir,fpregs));
+ default:
+ /* "crashme Night Gallery painting nr 2. (asm_crash.s).
+ * This was fixed for multi-user kernels, but
+ * workstation kernels had a panic here. This allowed
+ * any arbitrary user to panic the kernel by executing
+ * setting the FP exception registers to strange values
+ * and generating an emulation trap. The emulation and
+ * exception code must never be able to panic the
+ * kernel.
+ */
+ return(UNIMPLEMENTEDEXCEPTION);
+ }
+}
+
+/*
+ * this routine is called by $emulation_trap to emulate a coprocessor
+ * instruction if one doesn't exist
+ */
+u_int
+emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
+{
+ u_int class, subop, major;
+ u_int fpu_type_flags;
+
+ /* All FP emulation code assumes that ints are 4-bytes in length */
+ VASSERT(sizeof(int) == 4);
+
+ fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
+
+ major = get_major(ir);
+ class = get_class(ir);
+ if (class == 1) {
+ if (fpu_type_flags & PA2_0_FPU_FLAG)
+ subop = get_subop1_PA2_0(ir);
+ else
+ subop = get_subop1_PA1_1(ir);
+ }
+ else
+ subop = get_subop(ir);
+ switch (major) {
+ case 0x0C:
+ return(decode_0c(ir,class,subop,fpregs));
+ case 0x0E:
+ return(decode_0e(ir,class,subop,fpregs));
+ case 0x06:
+ return(decode_06(ir,fpregs));
+ case 0x26:
+ return(decode_26(ir,fpregs));
+ case 0x2E:
+ return(decode_2e(ir,fpregs));
+ default:
+ return(PA83_UNIMP_EXCP);
+ }
+}
+
+
+static u_int
+decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
+{
+ u_int r1,r2,t; /* operand register offsets */
+ u_int fmt; /* also sf for class 1 conversions */
+ u_int df; /* for class 1 conversions */
+ u_int *status;
+ u_int retval, local_status;
+ u_int fpu_type_flags;
+
+ if (ir == COPR_INST) {
+ fpregs[0] = EMULATION_VERSION << 11;
+ return(NOEXCEPTION);
+ }
+ status = &fpregs[0]; /* fp status register */
+ local_status = fpregs[0]; /* and local copy */
+ r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
+ if (r1 == 0) /* map fr0 source to constant zero */
+ r1 = fpzeroreg;
+ t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
+ if (t == 0 && class != 2) /* don't allow fr0 as a dest */
+ return(MAJOR_0C_EXCP);
+ fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
+
+ switch (class) {
+ case 0:
+ switch (subop) {
+ case 0: /* COPR 0,0 emulated above*/
+ case 1:
+ return(MAJOR_0C_EXCP);
+ case 2: /* FCPY */
+ switch (fmt) {
+ case 2: /* illegal */
+ return(MAJOR_0C_EXCP);
+ case 3: /* quad */
+ t &= ~3; /* force to even reg #s */
+ r1 &= ~3;
+ fpregs[t+3] = fpregs[r1+3];
+ fpregs[t+2] = fpregs[r1+2];
+ case 1: /* double */
+ fpregs[t+1] = fpregs[r1+1];
+ case 0: /* single */
+ fpregs[t] = fpregs[r1];
+ return(NOEXCEPTION);
+ }
+ case 3: /* FABS */
+ switch (fmt) {
+ case 2: /* illegal */
+ return(MAJOR_0C_EXCP);
+ case 3: /* quad */
+ t &= ~3; /* force to even reg #s */
+ r1 &= ~3;
+ fpregs[t+3] = fpregs[r1+3];
+ fpregs[t+2] = fpregs[r1+2];
+ case 1: /* double */
+ fpregs[t+1] = fpregs[r1+1];
+ case 0: /* single */
+ /* copy and clear sign bit */
+ fpregs[t] = fpregs[r1] & 0x7fffffff;
+ return(NOEXCEPTION);
+ }
+ case 6: /* FNEG */
+ switch (fmt) {
+ case 2: /* illegal */
+ return(MAJOR_0C_EXCP);
+ case 3: /* quad */
+ t &= ~3; /* force to even reg #s */
+ r1 &= ~3;
+ fpregs[t+3] = fpregs[r1+3];
+ fpregs[t+2] = fpregs[r1+2];
+ case 1: /* double */
+ fpregs[t+1] = fpregs[r1+1];
+ case 0: /* single */
+ /* copy and invert sign bit */
+ fpregs[t] = fpregs[r1] ^ 0x80000000;
+ return(NOEXCEPTION);
+ }
+ case 7: /* FNEGABS */
+ switch (fmt) {
+ case 2: /* illegal */
+ return(MAJOR_0C_EXCP);
+ case 3: /* quad */
+ t &= ~3; /* force to even reg #s */
+ r1 &= ~3;
+ fpregs[t+3] = fpregs[r1+3];
+ fpregs[t+2] = fpregs[r1+2];
+ case 1: /* double */
+ fpregs[t+1] = fpregs[r1+1];
+ case 0: /* single */
+ /* copy and set sign bit */
+ fpregs[t] = fpregs[r1] | 0x80000000;
+ return(NOEXCEPTION);
+ }
+ case 4: /* FSQRT */
+ switch (fmt) {
+ case 0:
+ return(sgl_fsqrt(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1:
+ return(dbl_fsqrt(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2:
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ case 5: /* FRND */
+ switch (fmt) {
+ case 0:
+ return(sgl_frnd(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1:
+ return(dbl_frnd(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2:
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ } /* end of switch (subop) */
+
+ case 1: /* class 1 */
+ df = extru(ir,fpdfpos,2); /* get dest format */
+ if ((df & 2) || (fmt & 2)) {
+ /*
+ * fmt's 2 and 3 are illegal of not implemented
+ * quad conversions
+ */
+ return(MAJOR_0C_EXCP);
+ }
+ /*
+ * encode source and dest formats into 2 bits.
+ * high bit is source, low bit is dest.
+ * bit = 1 --> double precision
+ */
+ fmt = (fmt << 1) | df;
+ switch (subop) {
+ case 0: /* FCNVFF */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(MAJOR_0C_EXCP);
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(MAJOR_0C_EXCP);
+ }
+ case 1: /* FCNVXF */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 2: /* FCNVFX */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 3: /* FCNVFXT */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 5: /* FCNVUF (PA2.0 only) */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 6: /* FCNVFU (PA2.0 only) */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 7: /* FCNVFUT (PA2.0 only) */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 4: /* undefined */
+ return(MAJOR_0C_EXCP);
+ } /* end of switch subop */
+
+ case 2: /* class 2 */
+ fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
+ r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
+ if (r2 == 0)
+ r2 = fpzeroreg;
+ if (fpu_type_flags & PA2_0_FPU_FLAG) {
+ /* FTEST if nullify bit set, otherwise FCMP */
+ if (extru(ir, fpnulpos, 1)) { /* FTEST */
+ switch (fmt) {
+ case 0:
+ /*
+ * arg0 is not used
+ * second param is the t field used for
+ * ftest,acc and ftest,rej
+ * third param is the subop (y-field)
+ */
+ BUG();
+ /* Unsupported
+ * return(ftest(0L,extru(ir,fptpos,5),
+ * &fpregs[0],subop));
+ */
+ case 1:
+ case 2:
+ case 3:
+ return(MAJOR_0C_EXCP);
+ }
+ } else { /* FCMP */
+ switch (fmt) {
+ case 0:
+ retval = sgl_fcmp(&fpregs[r1],
+ &fpregs[r2],extru(ir,fptpos,5),
+ &local_status);
+ update_status_cbit(status,local_status,
+ fpu_type_flags, subop);
+ return(retval);
+ case 1:
+ retval = dbl_fcmp(&fpregs[r1],
+ &fpregs[r2],extru(ir,fptpos,5),
+ &local_status);
+ update_status_cbit(status,local_status,
+ fpu_type_flags, subop);
+ return(retval);
+ case 2: /* illegal */
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ }
+ } /* end of if for PA2.0 */
+ else { /* PA1.0 & PA1.1 */
+ switch (subop) {
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ return(MAJOR_0C_EXCP);
+ case 0: /* FCMP */
+ switch (fmt) {
+ case 0:
+ retval = sgl_fcmp(&fpregs[r1],
+ &fpregs[r2],extru(ir,fptpos,5),
+ &local_status);
+ update_status_cbit(status,local_status,
+ fpu_type_flags, subop);
+ return(retval);
+ case 1:
+ retval = dbl_fcmp(&fpregs[r1],
+ &fpregs[r2],extru(ir,fptpos,5),
+ &local_status);
+ update_status_cbit(status,local_status,
+ fpu_type_flags, subop);
+ return(retval);
+ case 2: /* illegal */
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ case 1: /* FTEST */
+ switch (fmt) {
+ case 0:
+ /*
+ * arg0 is not used
+ * second param is the t field used for
+ * ftest,acc and ftest,rej
+ * third param is the subop (y-field)
+ */
+ BUG();
+ /* unsupported
+ * return(ftest(0L,extru(ir,fptpos,5),
+ * &fpregs[0],subop));
+ */
+ case 1:
+ case 2:
+ case 3:
+ return(MAJOR_0C_EXCP);
+ }
+ } /* end of switch subop */
+ } /* end of else for PA1.0 & PA1.1 */
+ case 3: /* class 3 */
+ r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
+ if (r2 == 0)
+ r2 = fpzeroreg;
+ switch (subop) {
+ case 5:
+ case 6:
+ case 7:
+ return(MAJOR_0C_EXCP);
+
+ case 0: /* FADD */
+ switch (fmt) {
+ case 0:
+ return(sgl_fadd(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_fadd(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 2: /* illegal */
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ case 1: /* FSUB */
+ switch (fmt) {
+ case 0:
+ return(sgl_fsub(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_fsub(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 2: /* illegal */
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ case 2: /* FMPY */
+ switch (fmt) {
+ case 0:
+ return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 2: /* illegal */
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ case 3: /* FDIV */
+ switch (fmt) {
+ case 0:
+ return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 2: /* illegal */
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ case 4: /* FREM */
+ switch (fmt) {
+ case 0:
+ return(sgl_frem(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_frem(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 2: /* illegal */
+ case 3: /* quad not implemented */
+ return(MAJOR_0C_EXCP);
+ }
+ } /* end of class 3 switch */
+ } /* end of switch(class) */
+
+ /* If we get here, something is really wrong! */
+ return(MAJOR_0C_EXCP);
+}
+
+static u_int
+decode_0e(ir,class,subop,fpregs)
+u_int ir,class,subop;
+u_int fpregs[];
+{
+ u_int r1,r2,t; /* operand register offsets */
+ u_int fmt; /* also sf for class 1 conversions */
+ u_int df; /* dest format for class 1 conversions */
+ u_int *status;
+ u_int retval, local_status;
+ u_int fpu_type_flags;
+
+ status = &fpregs[0];
+ local_status = fpregs[0];
+ r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
+ if (r1 == 0)
+ r1 = fpzeroreg;
+ t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
+ if (t == 0 && class != 2)
+ return(MAJOR_0E_EXCP);
+ if (class < 2) /* class 0 or 1 has 2 bit fmt */
+ fmt = extru(ir,fpfmtpos,2);
+ else /* class 2 and 3 have 1 bit fmt */
+ fmt = extru(ir,fp0efmtpos,1);
+ /*
+ * An undefined combination, double precision accessing the
+ * right half of a FPR, can get us into trouble.
+ * Let's just force proper alignment on it.
+ */
+ if (fmt == DBL) {
+ r1 &= ~1;
+ if (class != 1)
+ t &= ~1;
+ }
+
+ switch (class) {
+ case 0:
+ switch (subop) {
+ case 0: /* unimplemented */
+ case 1:
+ return(MAJOR_0E_EXCP);
+ case 2: /* FCPY */
+ switch (fmt) {
+ case 2:
+ case 3:
+ return(MAJOR_0E_EXCP);
+ case 1: /* double */
+ fpregs[t+1] = fpregs[r1+1];
+ case 0: /* single */
+ fpregs[t] = fpregs[r1];
+ return(NOEXCEPTION);
+ }
+ case 3: /* FABS */
+ switch (fmt) {
+ case 2:
+ case 3:
+ return(MAJOR_0E_EXCP);
+ case 1: /* double */
+ fpregs[t+1] = fpregs[r1+1];
+ case 0: /* single */
+ fpregs[t] = fpregs[r1] & 0x7fffffff;
+ return(NOEXCEPTION);
+ }
+ case 6: /* FNEG */
+ switch (fmt) {
+ case 2:
+ case 3:
+ return(MAJOR_0E_EXCP);
+ case 1: /* double */
+ fpregs[t+1] = fpregs[r1+1];
+ case 0: /* single */
+ fpregs[t] = fpregs[r1] ^ 0x80000000;
+ return(NOEXCEPTION);
+ }
+ case 7: /* FNEGABS */
+ switch (fmt) {
+ case 2:
+ case 3:
+ return(MAJOR_0E_EXCP);
+ case 1: /* double */
+ fpregs[t+1] = fpregs[r1+1];
+ case 0: /* single */
+ fpregs[t] = fpregs[r1] | 0x80000000;
+ return(NOEXCEPTION);
+ }
+ case 4: /* FSQRT */
+ switch (fmt) {
+ case 0:
+ return(sgl_fsqrt(&fpregs[r1],0,
+ &fpregs[t], status));
+ case 1:
+ return(dbl_fsqrt(&fpregs[r1],0,
+ &fpregs[t], status));
+ case 2:
+ case 3:
+ return(MAJOR_0E_EXCP);
+ }
+ case 5: /* FRMD */
+ switch (fmt) {
+ case 0:
+ return(sgl_frnd(&fpregs[r1],0,
+ &fpregs[t], status));
+ case 1:
+ return(dbl_frnd(&fpregs[r1],0,
+ &fpregs[t], status));
+ case 2:
+ case 3:
+ return(MAJOR_0E_EXCP);
+ }
+ } /* end of switch (subop */
+
+ case 1: /* class 1 */
+ df = extru(ir,fpdfpos,2); /* get dest format */
+ /*
+ * Fix Crashme problem (writing to 31R in double precision)
+ * here too.
+ */
+ if (df == DBL) {
+ t &= ~1;
+ }
+ if ((df & 2) || (fmt & 2))
+ return(MAJOR_0E_EXCP);
+
+ fmt = (fmt << 1) | df;
+ switch (subop) {
+ case 0: /* FCNVFF */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(MAJOR_0E_EXCP);
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(MAJOR_0E_EXCP);
+ }
+ case 1: /* FCNVXF */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 2: /* FCNVFX */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 3: /* FCNVFXT */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 5: /* FCNVUF (PA2.0 only) */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 6: /* FCNVFU (PA2.0 only) */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 7: /* FCNVFUT (PA2.0 only) */
+ switch(fmt) {
+ case 0: /* sgl/sgl */
+ return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 1: /* sgl/dbl */
+ return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 2: /* dbl/sgl */
+ return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
+ &fpregs[t],status));
+ case 3: /* dbl/dbl */
+ return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
+ &fpregs[t],status));
+ }
+ case 4: /* undefined */
+ return(MAJOR_0C_EXCP);
+ } /* end of switch subop */
+ case 2: /* class 2 */
+ /*
+ * Be careful out there.
+ * Crashme can generate cases where FR31R is specified
+ * as the source or target of a double precision operation.
+ * Since we just pass the address of the floating-point
+ * register to the emulation routines, this can cause
+ * corruption of fpzeroreg.
+ */
+ if (fmt == DBL)
+ r2 = (extru(ir,fpr2pos,5)<<1);
+ else
+ r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
+ fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
+ if (r2 == 0)
+ r2 = fpzeroreg;
+ if (fpu_type_flags & PA2_0_FPU_FLAG) {
+ /* FTEST if nullify bit set, otherwise FCMP */
+ if (extru(ir, fpnulpos, 1)) { /* FTEST */
+ /* not legal */
+ return(MAJOR_0E_EXCP);
+ } else { /* FCMP */
+ switch (fmt) {
+ /*
+ * fmt is only 1 bit long
+ */
+ case 0:
+ retval = sgl_fcmp(&fpregs[r1],
+ &fpregs[r2],extru(ir,fptpos,5),
+ &local_status);
+ update_status_cbit(status,local_status,
+ fpu_type_flags, subop);
+ return(retval);
+ case 1:
+ retval = dbl_fcmp(&fpregs[r1],
+ &fpregs[r2],extru(ir,fptpos,5),
+ &local_status);
+ update_status_cbit(status,local_status,
+ fpu_type_flags, subop);
+ return(retval);
+ }
+ }
+ } /* end of if for PA2.0 */
+ else { /* PA1.0 & PA1.1 */
+ switch (subop) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ return(MAJOR_0E_EXCP);
+ case 0: /* FCMP */
+ switch (fmt) {
+ /*
+ * fmt is only 1 bit long
+ */
+ case 0:
+ retval = sgl_fcmp(&fpregs[r1],
+ &fpregs[r2],extru(ir,fptpos,5),
+ &local_status);
+ update_status_cbit(status,local_status,
+ fpu_type_flags, subop);
+ return(retval);
+ case 1:
+ retval = dbl_fcmp(&fpregs[r1],
+ &fpregs[r2],extru(ir,fptpos,5),
+ &local_status);
+ update_status_cbit(status,local_status,
+ fpu_type_flags, subop);
+ return(retval);
+ }
+ } /* end of switch subop */
+ } /* end of else for PA1.0 & PA1.1 */
+ case 3: /* class 3 */
+ /*
+ * Be careful out there.
+ * Crashme can generate cases where FR31R is specified
+ * as the source or target of a double precision operation.
+ * Since we just pass the address of the floating-point
+ * register to the emulation routines, this can cause
+ * corruption of fpzeroreg.
+ */
+ if (fmt == DBL)
+ r2 = (extru(ir,fpr2pos,5)<<1);
+ else
+ r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
+ if (r2 == 0)
+ r2 = fpzeroreg;
+ switch (subop) {
+ case 5:
+ case 6:
+ case 7:
+ return(MAJOR_0E_EXCP);
+
+ /*
+ * Note that fmt is only 1 bit for class 3 */
+ case 0: /* FADD */
+ switch (fmt) {
+ case 0:
+ return(sgl_fadd(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_fadd(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ }
+ case 1: /* FSUB */
+ switch (fmt) {
+ case 0:
+ return(sgl_fsub(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_fsub(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ }
+ case 2: /* FMPY or XMPYU */
+ /*
+ * check for integer multiply (x bit set)
+ */
+ if (extru(ir,fpxpos,1)) {
+ /*
+ * emulate XMPYU
+ */
+ switch (fmt) {
+ case 0:
+ /*
+ * bad instruction if t specifies
+ * the right half of a register
+ */
+ if (t & 1)
+ return(MAJOR_0E_EXCP);
+ BUG();
+ /* unsupported
+ * impyu(&fpregs[r1],&fpregs[r2],
+ * &fpregs[t]);
+ */
+ return(NOEXCEPTION);
+ case 1:
+ return(MAJOR_0E_EXCP);
+ }
+ }
+ else { /* FMPY */
+ switch (fmt) {
+ case 0:
+ return(sgl_fmpy(&fpregs[r1],
+ &fpregs[r2],&fpregs[t],status));
+ case 1:
+ return(dbl_fmpy(&fpregs[r1],
+ &fpregs[r2],&fpregs[t],status));
+ }
+ }
+ case 3: /* FDIV */
+ switch (fmt) {
+ case 0:
+ return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ }
+ case 4: /* FREM */
+ switch (fmt) {
+ case 0:
+ return(sgl_frem(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ case 1:
+ return(dbl_frem(&fpregs[r1],&fpregs[r2],
+ &fpregs[t],status));
+ }
+ } /* end of class 3 switch */
+ } /* end of switch(class) */
+
+ /* If we get here, something is really wrong! */
+ return(MAJOR_0E_EXCP);
+}
+
+
+/*
+ * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
+ */
+static u_int
+decode_06(ir,fpregs)
+u_int ir;
+u_int fpregs[];
+{
+ u_int rm1, rm2, tm, ra, ta; /* operands */
+ u_int fmt;
+ u_int error = 0;
+ u_int status;
+ u_int fpu_type_flags;
+ union {
+ double dbl;
+ float flt;
+ struct { u_int i1; u_int i2; } ints;
+ } mtmp, atmp;
+
+
+ status = fpregs[0]; /* use a local copy of status reg */
+ fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
+ fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
+ if (fmt == 0) { /* DBL */
+ rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
+ if (rm1 == 0)
+ rm1 = fpzeroreg;
+ rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
+ if (rm2 == 0)
+ rm2 = fpzeroreg;
+ tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
+ if (tm == 0)
+ return(MAJOR_06_EXCP);
+ ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
+ ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
+ if (ta == 0)
+ return(MAJOR_06_EXCP);
+
+ if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) {
+
+ if (ra == 0) {
+ /* special case FMPYCFXT, see sgl case below */
+ if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
+ &mtmp.ints.i1,&status))
+ error = 1;
+ if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
+ &atmp.ints.i1,&atmp.ints.i1,&status))
+ error = 1;
+ }
+ else {
+
+ if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
+ &status))
+ error = 1;
+ if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
+ &status))
+ error = 1;
+ }
+ }
+
+ else
+
+ {
+ if (ra == 0)
+ ra = fpzeroreg;
+
+ if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
+ &status))
+ error = 1;
+ if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
+ &status))
+ error = 1;
+
+ }
+
+ if (error)
+ return(MAJOR_06_EXCP);
+ else {
+ /* copy results */
+ fpregs[tm] = mtmp.ints.i1;
+ fpregs[tm+1] = mtmp.ints.i2;
+ fpregs[ta] = atmp.ints.i1;
+ fpregs[ta+1] = atmp.ints.i2;
+ fpregs[0] = status;
+ return(NOEXCEPTION);
+ }
+ }
+ else { /* SGL */
+ /*
+ * calculate offsets for single precision numbers
+ * See table 6-14 in PA-89 architecture for mapping
+ */
+ rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
+ rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
+
+ rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
+ rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
+
+ tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
+ tm |= extru(ir,fptmpos-4,1); /* add right word offset */
+
+ ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
+ ra |= extru(ir,fprapos-4,1); /* add right word offset */
+
+ ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
+ ta |= extru(ir,fptapos-4,1); /* add right word offset */
+
+ if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
+ /* special case FMPYCFXT (really 0)
+ * This instruction is only present on the Timex and
+ * Rolex fpu's in so if it is the special case and
+ * one of these fpu's we run the FMPYCFXT instruction
+ */
+ if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
+ &status))
+ error = 1;
+ if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
+ &atmp.ints.i1,&status))
+ error = 1;
+ }
+ else {
+ if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
+ &status))
+ error = 1;
+ if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
+ &status))
+ error = 1;
+ }
+ if (error)
+ return(MAJOR_06_EXCP);
+ else {
+ /* copy results */
+ fpregs[tm] = mtmp.ints.i1;
+ fpregs[ta] = atmp.ints.i1;
+ fpregs[0] = status;
+ return(NOEXCEPTION);
+ }
+ }
+}
+
+/*
+ * routine to decode the 26 (FMPYSUB) instruction
+ */
+static u_int
+decode_26(ir,fpregs)
+u_int ir;
+u_int fpregs[];
+{
+ u_int rm1, rm2, tm, ra, ta; /* operands */
+ u_int fmt;
+ u_int error = 0;
+ u_int status;
+ union {
+ double dbl;
+ float flt;
+ struct { u_int i1; u_int i2; } ints;
+ } mtmp, atmp;
+
+
+ status = fpregs[0];
+ fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
+ if (fmt == 0) { /* DBL */
+ rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
+ if (rm1 == 0)
+ rm1 = fpzeroreg;
+ rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
+ if (rm2 == 0)
+ rm2 = fpzeroreg;
+ tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
+ if (tm == 0)
+ return(MAJOR_26_EXCP);
+ ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
+ if (ra == 0)
+ return(MAJOR_26_EXCP);
+ ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
+ if (ta == 0)
+ return(MAJOR_26_EXCP);
+
+ if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
+ error = 1;
+ if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
+ error = 1;
+ if (error)
+ return(MAJOR_26_EXCP);
+ else {
+ /* copy results */
+ fpregs[tm] = mtmp.ints.i1;
+ fpregs[tm+1] = mtmp.ints.i2;
+ fpregs[ta] = atmp.ints.i1;
+ fpregs[ta+1] = atmp.ints.i2;
+ fpregs[0] = status;
+ return(NOEXCEPTION);
+ }
+ }
+ else { /* SGL */
+ /*
+ * calculate offsets for single precision numbers
+ * See table 6-14 in PA-89 architecture for mapping
+ */
+ rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
+ rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
+
+ rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
+ rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
+
+ tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
+ tm |= extru(ir,fptmpos-4,1); /* add right word offset */
+
+ ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
+ ra |= extru(ir,fprapos-4,1); /* add right word offset */
+
+ ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
+ ta |= extru(ir,fptapos-4,1); /* add right word offset */
+
+ if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
+ error = 1;
+ if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
+ error = 1;
+ if (error)
+ return(MAJOR_26_EXCP);
+ else {
+ /* copy results */
+ fpregs[tm] = mtmp.ints.i1;
+ fpregs[ta] = atmp.ints.i1;
+ fpregs[0] = status;
+ return(NOEXCEPTION);
+ }
+ }
+
+}
+
+/*
+ * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
+ */
+static u_int
+decode_2e(ir,fpregs)
+u_int ir;
+u_int fpregs[];
+{
+ u_int rm1, rm2, ra, t; /* operands */
+ u_int fmt;
+
+ fmt = extru(ir,fpfmtpos,1); /* get fmt completer */
+ if (fmt == DBL) { /* DBL */
+ rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
+ if (rm1 == 0)
+ rm1 = fpzeroreg;
+ rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
+ if (rm2 == 0)
+ rm2 = fpzeroreg;
+ ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
+ sizeof(double)/sizeof(u_int);
+ if (ra == 0)
+ ra = fpzeroreg;
+ t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
+ if (t == 0)
+ return(MAJOR_2E_EXCP);
+
+ if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
+ return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
+ &fpregs[ra], &fpregs[0], &fpregs[t]));
+ } else {
+ return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
+ &fpregs[ra], &fpregs[0], &fpregs[t]));
+ }
+ } /* end DBL */
+ else { /* SGL */
+ rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
+ if (rm1 == 0)
+ rm1 = fpzeroreg;
+ rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
+ if (rm2 == 0)
+ rm2 = fpzeroreg;
+ ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
+ if (ra == 0)
+ ra = fpzeroreg;
+ t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
+ if (t == 0)
+ return(MAJOR_2E_EXCP);
+
+ if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
+ return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
+ &fpregs[ra], &fpregs[0], &fpregs[t]));
+ } else {
+ return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
+ &fpregs[ra], &fpregs[0], &fpregs[t]));
+ }
+ } /* end SGL */
+}
+
+/*
+ * update_status_cbit
+ *
+ * This routine returns the correct FP status register value in
+ * *status, based on the C-bit & V-bit returned by the FCMP
+ * emulation routine in new_status. The architecture type
+ * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field
+ * and the architecture type are used to determine what flavor
+ * of FCMP is being emulated.
+ */
+static void
+update_status_cbit(status, new_status, fpu_type, y_field)
+u_int *status, new_status;
+u_int fpu_type;
+u_int y_field;
+{
+ /*
+ * For PA89 FPU's which implement the Compare Queue and
+ * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
+ * otherwise update the specified bit in the Compare Array.
+ * Note that the y-field will always be 0 for non-PA2.0 FPU's.
+ */
+ if ((fpu_type & TIMEX_EXTEN_FLAG) ||
+ (fpu_type & ROLEX_EXTEN_FLAG) ||
+ (fpu_type & PA2_0_FPU_FLAG)) {
+ if (y_field == 0) {
+ *status = ((*status & 0x04000000) >> 5) | /* old Cbit */
+ ((*status & 0x003ff000) >> 1) | /* old CQ */
+ (new_status & 0xffc007ff); /* all other bits*/
+ } else {
+ *status = (*status & 0x04000000) | /* old Cbit */
+ ((new_status & 0x04000000) >> (y_field+4)) |
+ (new_status & ~0x04000000 & /* other bits */
+ ~(0x04000000 >> (y_field+4)));
+ }
+ }
+ /* if PA83, just update the C-bit */
+ else {
+ *status = new_status;
+ }
+}
diff --git a/arch/parisc/math-emu/frnd.c b/arch/parisc/math-emu/frnd.c
new file mode 100644
index 000000000000..904b3844bf26
--- /dev/null
+++ b/arch/parisc/math-emu/frnd.c
@@ -0,0 +1,252 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * Purpose:
+ * Single Floating-point Round to Integer
+ * Double Floating-point Round to Integer
+ * Quad Floating-point Round to Integer (returns unimplemented)
+ *
+ * External Interfaces:
+ * dbl_frnd(srcptr,nullptr,dstptr,status)
+ * sgl_frnd(srcptr,nullptr,dstptr,status)
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ * Single Floating-point Round to Integer
+ */
+
+/*ARGSUSED*/
+int
+sgl_frnd(sgl_floating_point *srcptr,
+ unsigned int *nullptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int src, result;
+ register int src_exponent;
+ register boolean inexact = FALSE;
+
+ src = *srcptr;
+ /*
+ * check source operand for NaN or infinity
+ */
+ if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
+ /*
+ * is signaling NaN?
+ */
+ if (Sgl_isone_signaling(src)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(src);
+ }
+ /*
+ * return quiet NaN or infinity
+ */
+ *dstptr = src;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Need to round?
+ */
+ if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
+ *dstptr = src;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ Sgl_clear_exponent_set_hidden(src);
+ result = src;
+ Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
+ /* check for inexact */
+ if (Sgl_isinexact_to_fix(src,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(src)) Sgl_increment(result);
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(src)) Sgl_increment(result);
+ break;
+ case ROUNDNEAREST:
+ if (Sgl_isone_roundbit(src,src_exponent))
+ if (Sgl_isone_stickybit(src,src_exponent)
+ || (Sgl_isone_lowmantissa(result)))
+ Sgl_increment(result);
+ }
+ }
+ Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
+ if (Sgl_isone_hiddenoverflow(result))
+ Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
+ else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
+ }
+ else {
+ result = src; /* set sign */
+ Sgl_setzero_exponentmantissa(result);
+ /* check for inexact */
+ if (Sgl_isnotzero_exponentmantissa(src)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(src))
+ Sgl_set_exponent(result,SGL_BIAS);
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(src))
+ Sgl_set_exponent(result,SGL_BIAS);
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1)
+ if (Sgl_isnotzero_mantissa(src))
+ Sgl_set_exponent(result,SGL_BIAS);
+ }
+ }
+ }
+ *dstptr = result;
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
+
+/*
+ * Double Floating-point Round to Integer
+ */
+
+/*ARGSUSED*/
+int
+dbl_frnd(
+ dbl_floating_point *srcptr,
+ unsigned int *nullptr,
+ dbl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int srcp1, srcp2, resultp1, resultp2;
+ register int src_exponent;
+ register boolean inexact = FALSE;
+
+ Dbl_copyfromptr(srcptr,srcp1,srcp2);
+ /*
+ * check source operand for NaN or infinity
+ */
+ if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
+ /*
+ * is signaling NaN?
+ */
+ if (Dbl_isone_signaling(srcp1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Dbl_set_quiet(srcp1);
+ }
+ /*
+ * return quiet NaN or infinity
+ */
+ Dbl_copytoptr(srcp1,srcp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Need to round?
+ */
+ if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
+ Dbl_copytoptr(srcp1,srcp2,dstptr);
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate result
+ */
+ if (src_exponent >= 0) {
+ Dbl_clear_exponent_set_hidden(srcp1);
+ resultp1 = srcp1;
+ resultp2 = srcp2;
+ Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
+ /* check for inexact */
+ if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(srcp1))
+ Dbl_increment(resultp1,resultp2);
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(srcp1))
+ Dbl_increment(resultp1,resultp2);
+ break;
+ case ROUNDNEAREST:
+ if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
+ if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
+ || (Dbl_isone_lowmantissap2(resultp2)))
+ Dbl_increment(resultp1,resultp2);
+ }
+ }
+ Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
+ if (Dbl_isone_hiddenoverflow(resultp1))
+ Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
+ else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
+ }
+ else {
+ resultp1 = srcp1; /* set sign */
+ Dbl_setzero_exponentmantissa(resultp1,resultp2);
+ /* check for inexact */
+ if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+ inexact = TRUE;
+ /* round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Dbl_iszero_sign(srcp1))
+ Dbl_set_exponent(resultp1,DBL_BIAS);
+ break;
+ case ROUNDMINUS:
+ if (Dbl_isone_sign(srcp1))
+ Dbl_set_exponent(resultp1,DBL_BIAS);
+ break;
+ case ROUNDNEAREST:
+ if (src_exponent == -1)
+ if (Dbl_isnotzero_mantissa(srcp1,srcp2))
+ Dbl_set_exponent(resultp1,DBL_BIAS);
+ }
+ }
+ }
+ Dbl_copytoptr(resultp1,resultp2,dstptr);
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/hppa.h b/arch/parisc/math-emu/hppa.h
new file mode 100644
index 000000000000..5d3d52f7323a
--- /dev/null
+++ b/arch/parisc/math-emu/hppa.h
@@ -0,0 +1,42 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef __NO_PA_HDRS
+ PA header file -- do not include this header file for non-PA builds.
+#endif
+
+
+/* amount is assumed to be a constant between 0 and 32 (non-inclusive) */
+#define Shiftdouble(left,right,amount,dest) \
+ /* int left, right, amount, dest; */ \
+ dest = ((left) << (32-(amount))) | ((unsigned int)(right) >> (amount))
+
+/* amount must be less than 32 */
+#define Variableshiftdouble(left,right,amount,dest) \
+ /* unsigned int left, right; int amount, dest; */ \
+ if (amount == 0) dest = right; \
+ else dest = ((((unsigned) left)&0x7fffffff) << (32-(amount))) | \
+ ((unsigned) right >> (amount))
+
+/* amount must be between 0 and 32 (non-inclusive) */
+#define Variable_shift_double(left,right,amount,dest) \
+ /* unsigned int left, right; int amount, dest; */ \
+ dest = (left << (32-(amount))) | ((unsigned) right >> (amount))
diff --git a/arch/parisc/math-emu/math-emu.h b/arch/parisc/math-emu/math-emu.h
new file mode 100644
index 000000000000..3a99f5929291
--- /dev/null
+++ b/arch/parisc/math-emu/math-emu.h
@@ -0,0 +1,27 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _PARISC_MATH_EMU_H
+#define _PARISC_MATH_EMU_H
+
+#include <asm/ptrace.h>
+extern int handle_fpe(struct pt_regs *regs);
+
+#endif
diff --git a/arch/parisc/math-emu/sfadd.c b/arch/parisc/math-emu/sfadd.c
new file mode 100644
index 000000000000..008d721b5d22
--- /dev/null
+++ b/arch/parisc/math-emu/sfadd.c
@@ -0,0 +1,518 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/sfadd.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single_add: add two single precision values.
+ *
+ * External Interfaces:
+ * sgl_fadd(leftptr, rightptr, dstptr, status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * Single_add: add two single precision values.
+ */
+int
+sgl_fadd(
+ sgl_floating_point *leftptr,
+ sgl_floating_point *rightptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+ {
+ register unsigned int left, right, result, extent;
+ register unsigned int signless_upper_left, signless_upper_right, save;
+
+
+ register int result_exponent, right_exponent, diff_exponent;
+ register int sign_save, jumpsize;
+ register boolean inexact = FALSE;
+ register boolean underflowtrap;
+
+ /* Create local copies of the numbers */
+ left = *leftptr;
+ right = *rightptr;
+
+ /* A zero "save" helps discover equal operands (for later), *
+ * and is used in swapping operands (if needed). */
+ Sgl_xortointp1(left,right,/*to*/save);
+
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
+ {
+ if (Sgl_iszero_mantissa(left))
+ {
+ if (Sgl_isnotnan(right))
+ {
+ if (Sgl_isinfinity(right) && save!=0)
+ {
+ /*
+ * invalid since operands are opposite signed infinity's
+ */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ *dstptr = left;
+ return(NOEXCEPTION);
+ }
+ }
+ else
+ {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(left))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(left);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(right))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(right);
+ *dstptr = right;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = left;
+ return(NOEXCEPTION);
+ }
+ } /* End left NaN or Infinity processing */
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(right))
+ {
+ if (Sgl_iszero_mantissa(right))
+ {
+ /* return infinity */
+ *dstptr = right;
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(right))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(right);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = right;
+ return(NOEXCEPTION);
+ } /* End right NaN or Infinity processing */
+
+ /* Invariant: Must be dealing with finite numbers */
+
+ /* Compare operands by removing the sign */
+ Sgl_copytoint_exponentmantissa(left,signless_upper_left);
+ Sgl_copytoint_exponentmantissa(right,signless_upper_right);
+
+ /* sign difference selects add or sub operation. */
+ if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
+ {
+ /* Set the left operand to the larger one by XOR swap *
+ * First finish the first word using "save" */
+ Sgl_xorfromintp1(save,right,/*to*/right);
+ Sgl_xorfromintp1(save,left,/*to*/left);
+ result_exponent = Sgl_exponent(left);
+ }
+ /* Invariant: left is not smaller than right. */
+
+ if((right_exponent = Sgl_exponent(right)) == 0)
+ {
+ /* Denormalized operands. First look for zeroes */
+ if(Sgl_iszero_mantissa(right))
+ {
+ /* right is zero */
+ if(Sgl_iszero_exponentmantissa(left))
+ {
+ /* Both operands are zeros */
+ if(Is_rounding_mode(ROUNDMINUS))
+ {
+ Sgl_or_signs(left,/*with*/right);
+ }
+ else
+ {
+ Sgl_and_signs(left,/*with*/right);
+ }
+ }
+ else
+ {
+ /* Left is not a zero and must be the result. Trapped
+ * underflows are signaled if left is denormalized. Result
+ * is always exact. */
+ if( (result_exponent == 0) && Is_underflowtrap_enabled() )
+ {
+ /* need to normalize results mantissa */
+ sign_save = Sgl_signextendedsign(left);
+ Sgl_leftshiftby1(left);
+ Sgl_normalize(left,result_exponent);
+ Sgl_set_sign(left,/*using*/sign_save);
+ Sgl_setwrapped_exponent(left,result_exponent,unfl);
+ *dstptr = left;
+ return(UNDERFLOWEXCEPTION);
+ }
+ }
+ *dstptr = left;
+ return(NOEXCEPTION);
+ }
+
+ /* Neither are zeroes */
+ Sgl_clear_sign(right); /* Exponent is already cleared */
+ if(result_exponent == 0 )
+ {
+ /* Both operands are denormalized. The result must be exact
+ * and is simply calculated. A sum could become normalized and a
+ * difference could cancel to a true zero. */
+ if( (/*signed*/int) save < 0 )
+ {
+ Sgl_subtract(left,/*minus*/right,/*into*/result);
+ if(Sgl_iszero_mantissa(result))
+ {
+ if(Is_rounding_mode(ROUNDMINUS))
+ {
+ Sgl_setone_sign(result);
+ }
+ else
+ {
+ Sgl_setzero_sign(result);
+ }
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ else
+ {
+ Sgl_addition(left,right,/*into*/result);
+ if(Sgl_isone_hidden(result))
+ {
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ if(Is_underflowtrap_enabled())
+ {
+ /* need to normalize result */
+ sign_save = Sgl_signextendedsign(result);
+ Sgl_leftshiftby1(result);
+ Sgl_normalize(result,result_exponent);
+ Sgl_set_sign(result,/*using*/sign_save);
+ Sgl_setwrapped_exponent(result,result_exponent,unfl);
+ *dstptr = result;
+ return(UNDERFLOWEXCEPTION);
+ }
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ right_exponent = 1; /* Set exponent to reflect different bias
+ * with denomalized numbers. */
+ }
+ else
+ {
+ Sgl_clear_signexponent_set_hidden(right);
+ }
+ Sgl_clear_exponent_set_hidden(left);
+ diff_exponent = result_exponent - right_exponent;
+
+ /*
+ * Special case alignment of operands that would force alignment
+ * beyond the extent of the extension. A further optimization
+ * could special case this but only reduces the path length for this
+ * infrequent case.
+ */
+ if(diff_exponent > SGL_THRESHOLD)
+ {
+ diff_exponent = SGL_THRESHOLD;
+ }
+
+ /* Align right operand by shifting to right */
+ Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
+ /*and lower to*/extent);
+
+ /* Treat sum and difference of the operands separately. */
+ if( (/*signed*/int) save < 0 )
+ {
+ /*
+ * Difference of the two operands. Their can be no overflow. A
+ * borrow can occur out of the hidden bit and force a post
+ * normalization phase.
+ */
+ Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
+ if(Sgl_iszero_hidden(result))
+ {
+ /* Handle normalization */
+ /* A straight foward algorithm would now shift the result
+ * and extension left until the hidden bit becomes one. Not
+ * all of the extension bits need participate in the shift.
+ * Only the two most significant bits (round and guard) are
+ * needed. If only a single shift is needed then the guard
+ * bit becomes a significant low order bit and the extension
+ * must participate in the rounding. If more than a single
+ * shift is needed, then all bits to the right of the guard
+ * bit are zeros, and the guard bit may or may not be zero. */
+ sign_save = Sgl_signextendedsign(result);
+ Sgl_leftshiftby1_withextent(result,extent,result);
+
+ /* Need to check for a zero result. The sign and exponent
+ * fields have already been zeroed. The more efficient test
+ * of the full object can be used.
+ */
+ if(Sgl_iszero(result))
+ /* Must have been "x-x" or "x+(-x)". */
+ {
+ if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ result_exponent--;
+ /* Look to see if normalization is finished. */
+ if(Sgl_isone_hidden(result))
+ {
+ if(result_exponent==0)
+ {
+ /* Denormalized, exponent should be zero. Left operand *
+ * was normalized, so extent (guard, round) was zero */
+ goto underflow;
+ }
+ else
+ {
+ /* No further normalization is needed. */
+ Sgl_set_sign(result,/*using*/sign_save);
+ Ext_leftshiftby1(extent);
+ goto round;
+ }
+ }
+
+ /* Check for denormalized, exponent should be zero. Left *
+ * operand was normalized, so extent (guard, round) was zero */
+ if(!(underflowtrap = Is_underflowtrap_enabled()) &&
+ result_exponent==0) goto underflow;
+
+ /* Shift extension to complete one bit of normalization and
+ * update exponent. */
+ Ext_leftshiftby1(extent);
+
+ /* Discover first one bit to determine shift amount. Use a
+ * modified binary search. We have already shifted the result
+ * one position right and still not found a one so the remainder
+ * of the extension must be zero and simplifies rounding. */
+ /* Scan bytes */
+ while(Sgl_iszero_hiddenhigh7mantissa(result))
+ {
+ Sgl_leftshiftby8(result);
+ if((result_exponent -= 8) <= 0 && !underflowtrap)
+ goto underflow;
+ }
+ /* Now narrow it down to the nibble */
+ if(Sgl_iszero_hiddenhigh3mantissa(result))
+ {
+ /* The lower nibble contains the normalizing one */
+ Sgl_leftshiftby4(result);
+ if((result_exponent -= 4) <= 0 && !underflowtrap)
+ goto underflow;
+ }
+ /* Select case were first bit is set (already normalized)
+ * otherwise select the proper shift. */
+ if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
+ {
+ /* Already normalized */
+ if(result_exponent <= 0) goto underflow;
+ Sgl_set_sign(result,/*using*/sign_save);
+ Sgl_set_exponent(result,/*using*/result_exponent);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ Sgl_sethigh4bits(result,/*using*/sign_save);
+ switch(jumpsize)
+ {
+ case 1:
+ {
+ Sgl_leftshiftby3(result);
+ result_exponent -= 3;
+ break;
+ }
+ case 2:
+ case 3:
+ {
+ Sgl_leftshiftby2(result);
+ result_exponent -= 2;
+ break;
+ }
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ {
+ Sgl_leftshiftby1(result);
+ result_exponent -= 1;
+ break;
+ }
+ }
+ if(result_exponent > 0)
+ {
+ Sgl_set_exponent(result,/*using*/result_exponent);
+ *dstptr = result;
+ return(NOEXCEPTION); /* Sign bit is already set */
+ }
+ /* Fixup potential underflows */
+ underflow:
+ if(Is_underflowtrap_enabled())
+ {
+ Sgl_set_sign(result,sign_save);
+ Sgl_setwrapped_exponent(result,result_exponent,unfl);
+ *dstptr = result;
+ /* inexact = FALSE; */
+ return(UNDERFLOWEXCEPTION);
+ }
+ /*
+ * Since we cannot get an inexact denormalized result,
+ * we can now return.
+ */
+ Sgl_right_align(result,/*by*/(1-result_exponent),extent);
+ Sgl_clear_signexponent(result);
+ Sgl_set_sign(result,sign_save);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ } /* end if(hidden...)... */
+ /* Fall through and round */
+ } /* end if(save < 0)... */
+ else
+ {
+ /* Add magnitudes */
+ Sgl_addition(left,right,/*to*/result);
+ if(Sgl_isone_hiddenoverflow(result))
+ {
+ /* Prenormalization required. */
+ Sgl_rightshiftby1_withextent(result,extent,extent);
+ Sgl_arithrightshiftby1(result);
+ result_exponent++;
+ } /* end if hiddenoverflow... */
+ } /* end else ...add magnitudes... */
+
+ /* Round the result. If the extension is all zeros,then the result is
+ * exact. Otherwise round in the correct direction. No underflow is
+ * possible. If a postnormalization is necessary, then the mantissa is
+ * all zeros so no shift is needed. */
+ round:
+ if(Ext_isnotzero(extent))
+ {
+ inexact = TRUE;
+ switch(Rounding_mode())
+ {
+ case ROUNDNEAREST: /* The default. */
+ if(Ext_isone_sign(extent))
+ {
+ /* at least 1/2 ulp */
+ if(Ext_isnotzero_lower(extent) ||
+ Sgl_isone_lowmantissa(result))
+ {
+ /* either exactly half way and odd or more than 1/2ulp */
+ Sgl_increment(result);
+ }
+ }
+ break;
+
+ case ROUNDPLUS:
+ if(Sgl_iszero_sign(result))
+ {
+ /* Round up positive results */
+ Sgl_increment(result);
+ }
+ break;
+
+ case ROUNDMINUS:
+ if(Sgl_isone_sign(result))
+ {
+ /* Round down negative results */
+ Sgl_increment(result);
+ }
+
+ case ROUNDZERO:;
+ /* truncate is simple */
+ } /* end switch... */
+ if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
+ }
+ if(result_exponent == SGL_INFINITY_EXPONENT)
+ {
+ /* Overflow */
+ if(Is_overflowtrap_enabled())
+ {
+ Sgl_setwrapped_exponent(result,result_exponent,ovfl);
+ *dstptr = result;
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OVERFLOWEXCEPTION);
+ }
+ else
+ {
+ Set_overflowflag();
+ inexact = TRUE;
+ Sgl_setoverflow(result);
+ }
+ }
+ else Sgl_set_exponent(result,result_exponent);
+ *dstptr = result;
+ if(inexact)
+ if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+ }
diff --git a/arch/parisc/math-emu/sfcmp.c b/arch/parisc/math-emu/sfcmp.c
new file mode 100644
index 000000000000..1466fb46e4c0
--- /dev/null
+++ b/arch/parisc/math-emu/sfcmp.c
@@ -0,0 +1,155 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/sfcmp.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * sgl_cmp: compare two values
+ *
+ * External Interfaces:
+ * sgl_fcmp(leftptr, rightptr, cond, status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * sgl_cmp: compare two values
+ */
+int
+sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr,
+ unsigned int cond, unsigned int *status)
+
+ /* The predicate to be tested */
+
+ {
+ register unsigned int left, right;
+ register int xorresult;
+
+ /* Create local copies of the numbers */
+ left = *leftptr;
+ right = *rightptr;
+
+ /*
+ * Test for NaN
+ */
+ if( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
+ || (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) )
+ {
+ /* Check if a NaN is involved. Signal an invalid exception when
+ * comparing a signaling NaN or when comparing quiet NaNs and the
+ * low bit of the condition is set */
+ if( ( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
+ && Sgl_isnotzero_mantissa(left)
+ && (Exception(cond) || Sgl_isone_signaling(left)))
+ ||
+ ( (Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
+ && Sgl_isnotzero_mantissa(right)
+ && (Exception(cond) || Sgl_isone_signaling(right)) ) )
+ {
+ if( Is_invalidtrap_enabled() ) {
+ Set_status_cbit(Unordered(cond));
+ return(INVALIDEXCEPTION);
+ }
+ else Set_invalidflag();
+ Set_status_cbit(Unordered(cond));
+ return(NOEXCEPTION);
+ }
+ /* All the exceptional conditions are handled, now special case
+ NaN compares */
+ else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
+ && Sgl_isnotzero_mantissa(left))
+ ||
+ ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
+ && Sgl_isnotzero_mantissa(right)) )
+ {
+ /* NaNs always compare unordered. */
+ Set_status_cbit(Unordered(cond));
+ return(NOEXCEPTION);
+ }
+ /* infinities will drop down to the normal compare mechanisms */
+ }
+ /* First compare for unequal signs => less or greater or
+ * special equal case */
+ Sgl_xortointp1(left,right,xorresult);
+ if( xorresult < 0 )
+ {
+ /* left negative => less, left positive => greater.
+ * equal is possible if both operands are zeros. */
+ if( Sgl_iszero_exponentmantissa(left)
+ && Sgl_iszero_exponentmantissa(right) )
+ {
+ Set_status_cbit(Equal(cond));
+ }
+ else if( Sgl_isone_sign(left) )
+ {
+ Set_status_cbit(Lessthan(cond));
+ }
+ else
+ {
+ Set_status_cbit(Greaterthan(cond));
+ }
+ }
+ /* Signs are the same. Treat negative numbers separately
+ * from the positives because of the reversed sense. */
+ else if( Sgl_all(left) == Sgl_all(right) )
+ {
+ Set_status_cbit(Equal(cond));
+ }
+ else if( Sgl_iszero_sign(left) )
+ {
+ /* Positive compare */
+ if( Sgl_all(left) < Sgl_all(right) )
+ {
+ Set_status_cbit(Lessthan(cond));
+ }
+ else
+ {
+ Set_status_cbit(Greaterthan(cond));
+ }
+ }
+ else
+ {
+ /* Negative compare. Signed or unsigned compares
+ * both work the same. That distinction is only
+ * important when the sign bits differ. */
+ if( Sgl_all(left) > Sgl_all(right) )
+ {
+ Set_status_cbit(Lessthan(cond));
+ }
+ else
+ {
+ Set_status_cbit(Greaterthan(cond));
+ }
+ }
+ return(NOEXCEPTION);
+ }
diff --git a/arch/parisc/math-emu/sfdiv.c b/arch/parisc/math-emu/sfdiv.c
new file mode 100644
index 000000000000..3e2a4d6daa9c
--- /dev/null
+++ b/arch/parisc/math-emu/sfdiv.c
@@ -0,0 +1,392 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/sfdiv.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single Precision Floating-point Divide
+ *
+ * External Interfaces:
+ * sgl_fdiv(srcptr1,srcptr2,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * Single Precision Floating-point Divide
+ */
+
+int
+sgl_fdiv (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
+ sgl_floating_point * dstptr, unsigned int *status)
+{
+ register unsigned int opnd1, opnd2, opnd3, result;
+ register int dest_exponent, count;
+ register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+ boolean is_tiny;
+
+ opnd1 = *srcptr1;
+ opnd2 = *srcptr2;
+ /*
+ * set sign bit of result
+ */
+ if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);
+ else Sgl_setzero(result);
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd1)) {
+ if (Sgl_iszero_mantissa(opnd1)) {
+ if (Sgl_isnotnan(opnd2)) {
+ if (Sgl_isinfinity(opnd2)) {
+ /*
+ * invalid since both operands
+ * are infinity
+ */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ Sgl_setinfinity_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ *dstptr = opnd2;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = opnd1;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd2)) {
+ if (Sgl_iszero_mantissa(opnd2)) {
+ /*
+ * return zero
+ */
+ Sgl_setzero_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = opnd2;
+ return(NOEXCEPTION);
+ }
+ /*
+ * check for division by zero
+ */
+ if (Sgl_iszero_exponentmantissa(opnd2)) {
+ if (Sgl_iszero_exponentmantissa(opnd1)) {
+ /* invalid since both operands are zero */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ if (Is_divisionbyzerotrap_enabled())
+ return(DIVISIONBYZEROEXCEPTION);
+ Set_divisionbyzeroflag();
+ Sgl_setinfinity_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate exponent
+ */
+ dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS;
+
+ /*
+ * Generate mantissa
+ */
+ if (Sgl_isnotzero_exponent(opnd1)) {
+ /* set hidden bit */
+ Sgl_clear_signexponent_set_hidden(opnd1);
+ }
+ else {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd1)) {
+ Sgl_setzero_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /* is denormalized; want to normalize */
+ Sgl_clear_signexponent(opnd1);
+ Sgl_leftshiftby1(opnd1);
+ Sgl_normalize(opnd1,dest_exponent);
+ }
+ /* opnd2 needs to have hidden bit set with msb in hidden bit */
+ if (Sgl_isnotzero_exponent(opnd2)) {
+ Sgl_clear_signexponent_set_hidden(opnd2);
+ }
+ else {
+ /* is denormalized; want to normalize */
+ Sgl_clear_signexponent(opnd2);
+ Sgl_leftshiftby1(opnd2);
+ while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) {
+ Sgl_leftshiftby8(opnd2);
+ dest_exponent += 8;
+ }
+ if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) {
+ Sgl_leftshiftby4(opnd2);
+ dest_exponent += 4;
+ }
+ while(Sgl_iszero_hidden(opnd2)) {
+ Sgl_leftshiftby1(opnd2);
+ dest_exponent += 1;
+ }
+ }
+
+ /* Divide the source mantissas */
+
+ /*
+ * A non_restoring divide algorithm is used.
+ */
+ Sgl_subtract(opnd1,opnd2,opnd1);
+ Sgl_setzero(opnd3);
+ for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) {
+ Sgl_leftshiftby1(opnd1);
+ Sgl_leftshiftby1(opnd3);
+ if (Sgl_iszero_sign(opnd1)) {
+ Sgl_setone_lowmantissa(opnd3);
+ Sgl_subtract(opnd1,opnd2,opnd1);
+ }
+ else Sgl_addition(opnd1,opnd2,opnd1);
+ }
+ if (count <= SGL_P) {
+ Sgl_leftshiftby1(opnd3);
+ Sgl_setone_lowmantissa(opnd3);
+ Sgl_leftshift(opnd3,SGL_P-count);
+ if (Sgl_iszero_hidden(opnd3)) {
+ Sgl_leftshiftby1(opnd3);
+ dest_exponent--;
+ }
+ }
+ else {
+ if (Sgl_iszero_hidden(opnd3)) {
+ /* need to get one more bit of result */
+ Sgl_leftshiftby1(opnd1);
+ Sgl_leftshiftby1(opnd3);
+ if (Sgl_iszero_sign(opnd1)) {
+ Sgl_setone_lowmantissa(opnd3);
+ Sgl_subtract(opnd1,opnd2,opnd1);
+ }
+ else Sgl_addition(opnd1,opnd2,opnd1);
+ dest_exponent--;
+ }
+ if (Sgl_iszero_sign(opnd1)) guardbit = TRUE;
+ stickybit = Sgl_all(opnd1);
+ }
+ inexact = guardbit | stickybit;
+
+ /*
+ * round result
+ */
+ if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
+ Sgl_clear_signexponent(opnd3);
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result))
+ Sgl_increment_mantissa(opnd3);
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result))
+ Sgl_increment_mantissa(opnd3);
+ break;
+ case ROUNDNEAREST:
+ if (guardbit) {
+ if (stickybit || Sgl_isone_lowmantissa(opnd3))
+ Sgl_increment_mantissa(opnd3);
+ }
+ }
+ if (Sgl_isone_hidden(opnd3)) dest_exponent++;
+ }
+ Sgl_set_mantissa(result,opnd3);
+
+ /*
+ * Test for overflow
+ */
+ if (dest_exponent >= SGL_INFINITY_EXPONENT) {
+ /* trap if OVERFLOWTRAP enabled */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
+ *dstptr = result;
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OVERFLOWEXCEPTION);
+ }
+ Set_overflowflag();
+ /* set result to infinity or largest number */
+ Sgl_setoverflow(result);
+ inexact = TRUE;
+ }
+ /*
+ * Test for underflow
+ */
+ else if (dest_exponent <= 0) {
+ /* trap if UNDERFLOWTRAP enabled */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(result,dest_exponent,unfl);
+ *dstptr = result;
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(UNDERFLOWEXCEPTION);
+ }
+
+ /* Determine if should set underflow flag */
+ is_tiny = TRUE;
+ if (dest_exponent == 0 && inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result)) {
+ Sgl_increment(opnd3);
+ if (Sgl_isone_hiddenoverflow(opnd3))
+ is_tiny = FALSE;
+ Sgl_decrement(opnd3);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result)) {
+ Sgl_increment(opnd3);
+ if (Sgl_isone_hiddenoverflow(opnd3))
+ is_tiny = FALSE;
+ Sgl_decrement(opnd3);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Sgl_isone_lowmantissa(opnd3))) {
+ Sgl_increment(opnd3);
+ if (Sgl_isone_hiddenoverflow(opnd3))
+ is_tiny = FALSE;
+ Sgl_decrement(opnd3);
+ }
+ break;
+ }
+ }
+
+ /*
+ * denormalize result or set to signed zero
+ */
+ stickybit = inexact;
+ Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
+
+ /* return rounded number */
+ if (inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result)) {
+ Sgl_increment(opnd3);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result)) {
+ Sgl_increment(opnd3);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Sgl_isone_lowmantissa(opnd3))) {
+ Sgl_increment(opnd3);
+ }
+ break;
+ }
+ if (is_tiny) Set_underflowflag();
+ }
+ Sgl_set_exponentmantissa(result,opnd3);
+ }
+ else Sgl_set_exponent(result,dest_exponent);
+ *dstptr = result;
+ /* check for inexact */
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/sfmpy.c b/arch/parisc/math-emu/sfmpy.c
new file mode 100644
index 000000000000..afa406983335
--- /dev/null
+++ b/arch/parisc/math-emu/sfmpy.c
@@ -0,0 +1,380 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/sfmpy.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single Precision Floating-point Multiply
+ *
+ * External Interfaces:
+ * sgl_fmpy(srcptr1,srcptr2,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * Single Precision Floating-point Multiply
+ */
+
+int
+sgl_fmpy(
+ sgl_floating_point *srcptr1,
+ sgl_floating_point *srcptr2,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int opnd1, opnd2, opnd3, result;
+ register int dest_exponent, count;
+ register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+ boolean is_tiny;
+
+ opnd1 = *srcptr1;
+ opnd2 = *srcptr2;
+ /*
+ * set sign bit of result
+ */
+ if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);
+ else Sgl_setzero(result);
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd1)) {
+ if (Sgl_iszero_mantissa(opnd1)) {
+ if (Sgl_isnotnan(opnd2)) {
+ if (Sgl_iszero_exponentmantissa(opnd2)) {
+ /*
+ * invalid since operands are infinity
+ * and zero
+ */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ Sgl_setinfinity_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ *dstptr = opnd2;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = opnd1;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(opnd2)) {
+ if (Sgl_iszero_mantissa(opnd2)) {
+ if (Sgl_iszero_exponentmantissa(opnd1)) {
+ /* invalid since operands are zero & infinity */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(opnd2);
+ *dstptr = opnd2;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ Sgl_setinfinity_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = opnd2;
+ return(NOEXCEPTION);
+ }
+ /*
+ * Generate exponent
+ */
+ dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
+
+ /*
+ * Generate mantissa
+ */
+ if (Sgl_isnotzero_exponent(opnd1)) {
+ /* set hidden bit */
+ Sgl_clear_signexponent_set_hidden(opnd1);
+ }
+ else {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd1)) {
+ Sgl_setzero_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /* is denormalized, adjust exponent */
+ Sgl_clear_signexponent(opnd1);
+ Sgl_leftshiftby1(opnd1);
+ Sgl_normalize(opnd1,dest_exponent);
+ }
+ /* opnd2 needs to have hidden bit set with msb in hidden bit */
+ if (Sgl_isnotzero_exponent(opnd2)) {
+ Sgl_clear_signexponent_set_hidden(opnd2);
+ }
+ else {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd2)) {
+ Sgl_setzero_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /* is denormalized; want to normalize */
+ Sgl_clear_signexponent(opnd2);
+ Sgl_leftshiftby1(opnd2);
+ Sgl_normalize(opnd2,dest_exponent);
+ }
+
+ /* Multiply two source mantissas together */
+
+ Sgl_leftshiftby4(opnd2); /* make room for guard bits */
+ Sgl_setzero(opnd3);
+ /*
+ * Four bits at a time are inspected in each loop, and a
+ * simple shift and add multiply algorithm is used.
+ */
+ for (count=1;count<SGL_P;count+=4) {
+ stickybit |= Slow4(opnd3);
+ Sgl_rightshiftby4(opnd3);
+ if (Sbit28(opnd1)) Sall(opnd3) += (Sall(opnd2) << 3);
+ if (Sbit29(opnd1)) Sall(opnd3) += (Sall(opnd2) << 2);
+ if (Sbit30(opnd1)) Sall(opnd3) += (Sall(opnd2) << 1);
+ if (Sbit31(opnd1)) Sall(opnd3) += Sall(opnd2);
+ Sgl_rightshiftby4(opnd1);
+ }
+ /* make sure result is left-justified */
+ if (Sgl_iszero_sign(opnd3)) {
+ Sgl_leftshiftby1(opnd3);
+ }
+ else {
+ /* result mantissa >= 2. */
+ dest_exponent++;
+ }
+ /* check for denormalized result */
+ while (Sgl_iszero_sign(opnd3)) {
+ Sgl_leftshiftby1(opnd3);
+ dest_exponent--;
+ }
+ /*
+ * check for guard, sticky and inexact bits
+ */
+ stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1);
+ guardbit = Sbit24(opnd3);
+ inexact = guardbit | stickybit;
+
+ /* re-align mantissa */
+ Sgl_rightshiftby8(opnd3);
+
+ /*
+ * round result
+ */
+ if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
+ Sgl_clear_signexponent(opnd3);
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result))
+ Sgl_increment(opnd3);
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result))
+ Sgl_increment(opnd3);
+ break;
+ case ROUNDNEAREST:
+ if (guardbit) {
+ if (stickybit || Sgl_isone_lowmantissa(opnd3))
+ Sgl_increment(opnd3);
+ }
+ }
+ if (Sgl_isone_hidden(opnd3)) dest_exponent++;
+ }
+ Sgl_set_mantissa(result,opnd3);
+
+ /*
+ * Test for overflow
+ */
+ if (dest_exponent >= SGL_INFINITY_EXPONENT) {
+ /* trap if OVERFLOWTRAP enabled */
+ if (Is_overflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
+ *dstptr = result;
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OVERFLOWEXCEPTION);
+ }
+ inexact = TRUE;
+ Set_overflowflag();
+ /* set result to infinity or largest number */
+ Sgl_setoverflow(result);
+ }
+ /*
+ * Test for underflow
+ */
+ else if (dest_exponent <= 0) {
+ /* trap if UNDERFLOWTRAP enabled */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(result,dest_exponent,unfl);
+ *dstptr = result;
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(UNDERFLOWEXCEPTION);
+ }
+
+ /* Determine if should set underflow flag */
+ is_tiny = TRUE;
+ if (dest_exponent == 0 && inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result)) {
+ Sgl_increment(opnd3);
+ if (Sgl_isone_hiddenoverflow(opnd3))
+ is_tiny = FALSE;
+ Sgl_decrement(opnd3);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result)) {
+ Sgl_increment(opnd3);
+ if (Sgl_isone_hiddenoverflow(opnd3))
+ is_tiny = FALSE;
+ Sgl_decrement(opnd3);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Sgl_isone_lowmantissa(opnd3))) {
+ Sgl_increment(opnd3);
+ if (Sgl_isone_hiddenoverflow(opnd3))
+ is_tiny = FALSE;
+ Sgl_decrement(opnd3);
+ }
+ break;
+ }
+ }
+
+ /*
+ * denormalize result or set to signed zero
+ */
+ stickybit = inexact;
+ Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
+
+ /* return zero or smallest number */
+ if (inexact) {
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ if (Sgl_iszero_sign(result)) {
+ Sgl_increment(opnd3);
+ }
+ break;
+ case ROUNDMINUS:
+ if (Sgl_isone_sign(result)) {
+ Sgl_increment(opnd3);
+ }
+ break;
+ case ROUNDNEAREST:
+ if (guardbit && (stickybit ||
+ Sgl_isone_lowmantissa(opnd3))) {
+ Sgl_increment(opnd3);
+ }
+ break;
+ }
+ if (is_tiny) Set_underflowflag();
+ }
+ Sgl_set_exponentmantissa(result,opnd3);
+ }
+ else Sgl_set_exponent(result,dest_exponent);
+ *dstptr = result;
+
+ /* check for inexact */
+ if (inexact) {
+ if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ }
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/sfrem.c b/arch/parisc/math-emu/sfrem.c
new file mode 100644
index 000000000000..3a1b7a34d87a
--- /dev/null
+++ b/arch/parisc/math-emu/sfrem.c
@@ -0,0 +1,290 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/sfrem.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single Precision Floating-point Remainder
+ *
+ * External Interfaces:
+ * sgl_frem(srcptr1,srcptr2,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * Single Precision Floating-point Remainder
+ */
+
+int
+sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
+ sgl_floating_point * dstptr, unsigned int *status)
+{
+ register unsigned int opnd1, opnd2, result;
+ register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
+ register boolean roundup = FALSE;
+
+ opnd1 = *srcptr1;
+ opnd2 = *srcptr2;
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) {
+ if (Sgl_iszero_mantissa(opnd1)) {
+ if (Sgl_isnotnan(opnd2)) {
+ /* invalid since first operand is infinity */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ else {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd1)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd1);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled())
+ return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ *dstptr = opnd2;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = opnd1;
+ return(NOEXCEPTION);
+ }
+ }
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) {
+ if (Sgl_iszero_mantissa(opnd2)) {
+ /*
+ * return first operand
+ */
+ *dstptr = opnd1;
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(opnd2)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(opnd2);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = opnd2;
+ return(NOEXCEPTION);
+ }
+ /*
+ * check second operand for zero
+ */
+ if (Sgl_iszero_exponentmantissa(opnd2)) {
+ /* invalid since second operand is zero */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * get sign of result
+ */
+ result = opnd1;
+
+ /*
+ * check for denormalized operands
+ */
+ if (opnd1_exponent == 0) {
+ /* check for zero */
+ if (Sgl_iszero_mantissa(opnd1)) {
+ *dstptr = opnd1;
+ return(NOEXCEPTION);
+ }
+ /* normalize, then continue */
+ opnd1_exponent = 1;
+ Sgl_normalize(opnd1,opnd1_exponent);
+ }
+ else {
+ Sgl_clear_signexponent_set_hidden(opnd1);
+ }
+ if (opnd2_exponent == 0) {
+ /* normalize, then continue */
+ opnd2_exponent = 1;
+ Sgl_normalize(opnd2,opnd2_exponent);
+ }
+ else {
+ Sgl_clear_signexponent_set_hidden(opnd2);
+ }
+
+ /* find result exponent and divide step loop count */
+ dest_exponent = opnd2_exponent - 1;
+ stepcount = opnd1_exponent - opnd2_exponent;
+
+ /*
+ * check for opnd1/opnd2 < 1
+ */
+ if (stepcount < 0) {
+ /*
+ * check for opnd1/opnd2 > 1/2
+ *
+ * In this case n will round to 1, so
+ * r = opnd1 - opnd2
+ */
+ if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) {
+ Sgl_all(result) = ~Sgl_all(result); /* set sign */
+ /* align opnd2 with opnd1 */
+ Sgl_leftshiftby1(opnd2);
+ Sgl_subtract(opnd2,opnd1,opnd2);
+ /* now normalize */
+ while (Sgl_iszero_hidden(opnd2)) {
+ Sgl_leftshiftby1(opnd2);
+ dest_exponent--;
+ }
+ Sgl_set_exponentmantissa(result,opnd2);
+ goto testforunderflow;
+ }
+ /*
+ * opnd1/opnd2 <= 1/2
+ *
+ * In this case n will round to zero, so
+ * r = opnd1
+ */
+ Sgl_set_exponentmantissa(result,opnd1);
+ dest_exponent = opnd1_exponent;
+ goto testforunderflow;
+ }
+
+ /*
+ * Generate result
+ *
+ * Do iterative subtract until remainder is less than operand 2.
+ */
+ while (stepcount-- > 0 && Sgl_all(opnd1)) {
+ if (Sgl_isnotlessthan(opnd1,opnd2))
+ Sgl_subtract(opnd1,opnd2,opnd1);
+ Sgl_leftshiftby1(opnd1);
+ }
+ /*
+ * Do last subtract, then determine which way to round if remainder
+ * is exactly 1/2 of opnd2
+ */
+ if (Sgl_isnotlessthan(opnd1,opnd2)) {
+ Sgl_subtract(opnd1,opnd2,opnd1);
+ roundup = TRUE;
+ }
+ if (stepcount > 0 || Sgl_iszero(opnd1)) {
+ /* division is exact, remainder is zero */
+ Sgl_setzero_exponentmantissa(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Check for cases where opnd1/opnd2 < n
+ *
+ * In this case the result's sign will be opposite that of
+ * opnd1. The mantissa also needs some correction.
+ */
+ Sgl_leftshiftby1(opnd1);
+ if (Sgl_isgreaterthan(opnd1,opnd2)) {
+ Sgl_invert_sign(result);
+ Sgl_subtract((opnd2<<1),opnd1,opnd1);
+ }
+ /* check for remainder being exactly 1/2 of opnd2 */
+ else if (Sgl_isequal(opnd1,opnd2) && roundup) {
+ Sgl_invert_sign(result);
+ }
+
+ /* normalize result's mantissa */
+ while (Sgl_iszero_hidden(opnd1)) {
+ dest_exponent--;
+ Sgl_leftshiftby1(opnd1);
+ }
+ Sgl_set_exponentmantissa(result,opnd1);
+
+ /*
+ * Test for underflow
+ */
+ testforunderflow:
+ if (dest_exponent <= 0) {
+ /* trap if UNDERFLOWTRAP enabled */
+ if (Is_underflowtrap_enabled()) {
+ /*
+ * Adjust bias of result
+ */
+ Sgl_setwrapped_exponent(result,dest_exponent,unfl);
+ *dstptr = result;
+ /* frem is always exact */
+ return(UNDERFLOWEXCEPTION);
+ }
+ /*
+ * denormalize result or set to signed zero
+ */
+ if (dest_exponent >= (1 - SGL_P)) {
+ Sgl_rightshift_exponentmantissa(result,1-dest_exponent);
+ }
+ else {
+ Sgl_setzero_exponentmantissa(result);
+ }
+ }
+ else Sgl_set_exponent(result,dest_exponent);
+ *dstptr = result;
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/sfsqrt.c b/arch/parisc/math-emu/sfsqrt.c
new file mode 100644
index 000000000000..cd3f6db1f6fb
--- /dev/null
+++ b/arch/parisc/math-emu/sfsqrt.c
@@ -0,0 +1,187 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/sfsqrt.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single Floating-point Square Root
+ *
+ * External Interfaces:
+ * sgl_fsqrt(srcptr,nullptr,dstptr,status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * Single Floating-point Square Root
+ */
+
+/*ARGSUSED*/
+unsigned int
+sgl_fsqrt(
+ sgl_floating_point *srcptr,
+ unsigned int *nullptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+{
+ register unsigned int src, result;
+ register int src_exponent;
+ register unsigned int newbit, sum;
+ register boolean guardbit = FALSE, even_exponent;
+
+ src = *srcptr;
+ /*
+ * check source operand for NaN or infinity
+ */
+ if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
+ /*
+ * is signaling NaN?
+ */
+ if (Sgl_isone_signaling(src)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(src);
+ }
+ /*
+ * Return quiet NaN or positive infinity.
+ * Fall thru to negative test if negative infinity.
+ */
+ if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) {
+ *dstptr = src;
+ return(NOEXCEPTION);
+ }
+ }
+
+ /*
+ * check for zero source operand
+ */
+ if (Sgl_iszero_exponentmantissa(src)) {
+ *dstptr = src;
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * check for negative source operand
+ */
+ if (Sgl_isone_sign(src)) {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_makequietnan(src);
+ *dstptr = src;
+ return(NOEXCEPTION);
+ }
+
+ /*
+ * Generate result
+ */
+ if (src_exponent > 0) {
+ even_exponent = Sgl_hidden(src);
+ Sgl_clear_signexponent_set_hidden(src);
+ }
+ else {
+ /* normalize operand */
+ Sgl_clear_signexponent(src);
+ src_exponent++;
+ Sgl_normalize(src,src_exponent);
+ even_exponent = src_exponent & 1;
+ }
+ if (even_exponent) {
+ /* exponent is even */
+ /* Add comment here. Explain why odd exponent needs correction */
+ Sgl_leftshiftby1(src);
+ }
+ /*
+ * Add comment here. Explain following algorithm.
+ *
+ * Trust me, it works.
+ *
+ */
+ Sgl_setzero(result);
+ newbit = 1 << SGL_P;
+ while (newbit && Sgl_isnotzero(src)) {
+ Sgl_addition(result,newbit,sum);
+ if(sum <= Sgl_all(src)) {
+ /* update result */
+ Sgl_addition(result,(newbit<<1),result);
+ Sgl_subtract(src,sum,src);
+ }
+ Sgl_rightshiftby1(newbit);
+ Sgl_leftshiftby1(src);
+ }
+ /* correct exponent for pre-shift */
+ if (even_exponent) {
+ Sgl_rightshiftby1(result);
+ }
+
+ /* check for inexact */
+ if (Sgl_isnotzero(src)) {
+ if (!even_exponent && Sgl_islessthan(result,src))
+ Sgl_increment(result);
+ guardbit = Sgl_lowmantissa(result);
+ Sgl_rightshiftby1(result);
+
+ /* now round result */
+ switch (Rounding_mode()) {
+ case ROUNDPLUS:
+ Sgl_increment(result);
+ break;
+ case ROUNDNEAREST:
+ /* stickybit is always true, so guardbit
+ * is enough to determine rounding */
+ if (guardbit) {
+ Sgl_increment(result);
+ }
+ break;
+ }
+ /* increment result exponent by 1 if mantissa overflowed */
+ if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2;
+
+ if (Is_inexacttrap_enabled()) {
+ Sgl_set_exponent(result,
+ ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
+ *dstptr = result;
+ return(INEXACTEXCEPTION);
+ }
+ else Set_inexactflag();
+ }
+ else {
+ Sgl_rightshiftby1(result);
+ }
+ Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
+ *dstptr = result;
+ return(NOEXCEPTION);
+}
diff --git a/arch/parisc/math-emu/sfsub.c b/arch/parisc/math-emu/sfsub.c
new file mode 100644
index 000000000000..24eef61c8e3b
--- /dev/null
+++ b/arch/parisc/math-emu/sfsub.c
@@ -0,0 +1,521 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * BEGIN_DESC
+ *
+ * File:
+ * @(#) pa/spmath/sfsub.c $Revision: 1.1 $
+ *
+ * Purpose:
+ * Single_subtract: subtract two single precision values.
+ *
+ * External Interfaces:
+ * sgl_fsub(leftptr, rightptr, dstptr, status)
+ *
+ * Internal Interfaces:
+ *
+ * Theory:
+ * <<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * Single_subtract: subtract two single precision values.
+ */
+int
+sgl_fsub(
+ sgl_floating_point *leftptr,
+ sgl_floating_point *rightptr,
+ sgl_floating_point *dstptr,
+ unsigned int *status)
+ {
+ register unsigned int left, right, result, extent;
+ register unsigned int signless_upper_left, signless_upper_right, save;
+
+ register int result_exponent, right_exponent, diff_exponent;
+ register int sign_save, jumpsize;
+ register boolean inexact = FALSE, underflowtrap;
+
+ /* Create local copies of the numbers */
+ left = *leftptr;
+ right = *rightptr;
+
+ /* A zero "save" helps discover equal operands (for later), *
+ * and is used in swapping operands (if needed). */
+ Sgl_xortointp1(left,right,/*to*/save);
+
+ /*
+ * check first operand for NaN's or infinity
+ */
+ if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
+ {
+ if (Sgl_iszero_mantissa(left))
+ {
+ if (Sgl_isnotnan(right))
+ {
+ if (Sgl_isinfinity(right) && save==0)
+ {
+ /*
+ * invalid since operands are same signed infinity's
+ */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ Set_invalidflag();
+ Sgl_makequietnan(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return infinity
+ */
+ *dstptr = left;
+ return(NOEXCEPTION);
+ }
+ }
+ else
+ {
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(left))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(left);
+ }
+ /*
+ * is second operand a signaling NaN?
+ */
+ else if (Sgl_is_signalingnan(right))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(right);
+ *dstptr = right;
+ return(NOEXCEPTION);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = left;
+ return(NOEXCEPTION);
+ }
+ } /* End left NaN or Infinity processing */
+ /*
+ * check second operand for NaN's or infinity
+ */
+ if (Sgl_isinfinity_exponent(right))
+ {
+ if (Sgl_iszero_mantissa(right))
+ {
+ /* return infinity */
+ Sgl_invert_sign(right);
+ *dstptr = right;
+ return(NOEXCEPTION);
+ }
+ /*
+ * is NaN; signaling or quiet?
+ */
+ if (Sgl_isone_signaling(right))
+ {
+ /* trap if INVALIDTRAP enabled */
+ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+ /* make NaN quiet */
+ Set_invalidflag();
+ Sgl_set_quiet(right);
+ }
+ /*
+ * return quiet NaN
+ */
+ *dstptr = right;
+ return(NOEXCEPTION);
+ } /* End right NaN or Infinity processing */
+
+ /* Invariant: Must be dealing with finite numbers */
+
+ /* Compare operands by removing the sign */
+ Sgl_copytoint_exponentmantissa(left,signless_upper_left);
+ Sgl_copytoint_exponentmantissa(right,signless_upper_right);
+
+ /* sign difference selects sub or add operation. */
+ if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
+ {
+ /* Set the left operand to the larger one by XOR swap *
+ * First finish the first word using "save" */
+ Sgl_xorfromintp1(save,right,/*to*/right);
+ Sgl_xorfromintp1(save,left,/*to*/left);
+ result_exponent = Sgl_exponent(left);
+ Sgl_invert_sign(left);
+ }
+ /* Invariant: left is not smaller than right. */
+
+ if((right_exponent = Sgl_exponent(right)) == 0)
+ {
+ /* Denormalized operands. First look for zeroes */
+ if(Sgl_iszero_mantissa(right))
+ {
+ /* right is zero */
+ if(Sgl_iszero_exponentmantissa(left))
+ {
+ /* Both operands are zeros */
+ Sgl_invert_sign(right);
+ if(Is_rounding_mode(ROUNDMINUS))
+ {
+ Sgl_or_signs(left,/*with*/right);
+ }
+ else
+ {
+ Sgl_and_signs(left,/*with*/right);
+ }
+ }
+ else
+ {
+ /* Left is not a zero and must be the result. Trapped
+ * underflows are signaled if left is denormalized. Result
+ * is always exact. */
+ if( (result_exponent == 0) && Is_underflowtrap_enabled() )
+ {
+ /* need to normalize results mantissa */
+ sign_save = Sgl_signextendedsign(left);
+ Sgl_leftshiftby1(left);
+ Sgl_normalize(left,result_exponent);
+ Sgl_set_sign(left,/*using*/sign_save);
+ Sgl_setwrapped_exponent(left,result_exponent,unfl);
+ *dstptr = left;
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ }
+ *dstptr = left;
+ return(NOEXCEPTION);
+ }
+
+ /* Neither are zeroes */
+ Sgl_clear_sign(right); /* Exponent is already cleared */
+ if(result_exponent == 0 )
+ {
+ /* Both operands are denormalized. The result must be exact
+ * and is simply calculated. A sum could become normalized and a
+ * difference could cancel to a true zero. */
+ if( (/*signed*/int) save >= 0 )
+ {
+ Sgl_subtract(left,/*minus*/right,/*into*/result);
+ if(Sgl_iszero_mantissa(result))
+ {
+ if(Is_rounding_mode(ROUNDMINUS))
+ {
+ Sgl_setone_sign(result);
+ }
+ else
+ {
+ Sgl_setzero_sign(result);
+ }
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ else
+ {
+ Sgl_addition(left,right,/*into*/result);
+ if(Sgl_isone_hidden(result))
+ {
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ }
+ if(Is_underflowtrap_enabled())
+ {
+ /* need to normalize result */
+ sign_save = Sgl_signextendedsign(result);
+ Sgl_leftshiftby1(result);
+ Sgl_normalize(result,result_exponent);
+ Sgl_set_sign(result,/*using*/sign_save);
+ Sgl_setwrapped_exponent(result,result_exponent,unfl);
+ *dstptr = result;
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ right_exponent = 1; /* Set exponent to reflect different bias
+ * with denomalized numbers. */
+ }
+ else
+ {
+ Sgl_clear_signexponent_set_hidden(right);
+ }
+ Sgl_clear_exponent_set_hidden(left);
+ diff_exponent = result_exponent - right_exponent;
+
+ /*
+ * Special case alignment of operands that would force alignment
+ * beyond the extent of the extension. A further optimization
+ * could special case this but only reduces the path length for this
+ * infrequent case.
+ */
+ if(diff_exponent > SGL_THRESHOLD)
+ {
+ diff_exponent = SGL_THRESHOLD;
+ }
+
+ /* Align right operand by shifting to right */
+ Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
+ /*and lower to*/extent);
+
+ /* Treat sum and difference of the operands separately. */
+ if( (/*signed*/int) save >= 0 )
+ {
+ /*
+ * Difference of the two operands. Their can be no overflow. A
+ * borrow can occur out of the hidden bit and force a post
+ * normalization phase.
+ */
+ Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
+ if(Sgl_iszero_hidden(result))
+ {
+ /* Handle normalization */
+ /* A straight foward algorithm would now shift the result
+ * and extension left until the hidden bit becomes one. Not
+ * all of the extension bits need participate in the shift.
+ * Only the two most significant bits (round and guard) are
+ * needed. If only a single shift is needed then the guard
+ * bit becomes a significant low order bit and the extension
+ * must participate in the rounding. If more than a single
+ * shift is needed, then all bits to the right of the guard
+ * bit are zeros, and the guard bit may or may not be zero. */
+ sign_save = Sgl_signextendedsign(result);
+ Sgl_leftshiftby1_withextent(result,extent,result);
+
+ /* Need to check for a zero result. The sign and exponent
+ * fields have already been zeroed. The more efficient test
+ * of the full object can be used.
+ */
+ if(Sgl_iszero(result))
+ /* Must have been "x-x" or "x+(-x)". */
+ {
+ if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ result_exponent--;
+ /* Look to see if normalization is finished. */
+ if(Sgl_isone_hidden(result))
+ {
+ if(result_exponent==0)
+ {
+ /* Denormalized, exponent should be zero. Left operand *
+ * was normalized, so extent (guard, round) was zero */
+ goto underflow;
+ }
+ else
+ {
+ /* No further normalization is needed. */
+ Sgl_set_sign(result,/*using*/sign_save);
+ Ext_leftshiftby1(extent);
+ goto round;
+ }
+ }
+
+ /* Check for denormalized, exponent should be zero. Left *
+ * operand was normalized, so extent (guard, round) was zero */
+ if(!(underflowtrap = Is_underflowtrap_enabled()) &&
+ result_exponent==0) goto underflow;
+
+ /* Shift extension to complete one bit of normalization and
+ * update exponent. */
+ Ext_leftshiftby1(extent);
+
+ /* Discover first one bit to determine shift amount. Use a
+ * modified binary search. We have already shifted the result
+ * one position right and still not found a one so the remainder
+ * of the extension must be zero and simplifies rounding. */
+ /* Scan bytes */
+ while(Sgl_iszero_hiddenhigh7mantissa(result))
+ {
+ Sgl_leftshiftby8(result);
+ if((result_exponent -= 8) <= 0 && !underflowtrap)
+ goto underflow;
+ }
+ /* Now narrow it down to the nibble */
+ if(Sgl_iszero_hiddenhigh3mantissa(result))
+ {
+ /* The lower nibble contains the normalizing one */
+ Sgl_leftshiftby4(result);
+ if((result_exponent -= 4) <= 0 && !underflowtrap)
+ goto underflow;
+ }
+ /* Select case were first bit is set (already normalized)
+ * otherwise select the proper shift. */
+ if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
+ {
+ /* Already normalized */
+ if(result_exponent <= 0) goto underflow;
+ Sgl_set_sign(result,/*using*/sign_save);
+ Sgl_set_exponent(result,/*using*/result_exponent);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ }
+ Sgl_sethigh4bits(result,/*using*/sign_save);
+ switch(jumpsize)
+ {
+ case 1:
+ {
+ Sgl_leftshiftby3(result);
+ result_exponent -= 3;
+ break;
+ }
+ case 2:
+ case 3:
+ {
+ Sgl_leftshiftby2(result);
+ result_exponent -= 2;
+ break;
+ }
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ {
+ Sgl_leftshiftby1(result);
+ result_exponent -= 1;
+ break;
+ }
+ }
+ if(result_exponent > 0)
+ {
+ Sgl_set_exponent(result,/*using*/result_exponent);
+ *dstptr = result; /* Sign bit is already set */
+ return(NOEXCEPTION);
+ }
+ /* Fixup potential underflows */
+ underflow:
+ if(Is_underflowtrap_enabled())
+ {
+ Sgl_set_sign(result,sign_save);
+ Sgl_setwrapped_exponent(result,result_exponent,unfl);
+ *dstptr = result;
+ /* inexact = FALSE */
+ return(UNDERFLOWEXCEPTION);
+ }
+ /*
+ * Since we cannot get an inexact denormalized result,
+ * we can now return.
+ */
+ Sgl_right_align(result,/*by*/(1-result_exponent),extent);
+ Sgl_clear_signexponent(result);
+ Sgl_set_sign(result,sign_save);
+ *dstptr = result;
+ return(NOEXCEPTION);
+ } /* end if(hidden...)... */
+ /* Fall through and round */
+ } /* end if(save >= 0)... */
+ else
+ {
+ /* Add magnitudes */
+ Sgl_addition(left,right,/*to*/result);
+ if(Sgl_isone_hiddenoverflow(result))
+ {
+ /* Prenormalization required. */
+ Sgl_rightshiftby1_withextent(result,extent,extent);
+ Sgl_arithrightshiftby1(result);
+ result_exponent++;
+ } /* end if hiddenoverflow... */
+ } /* end else ...sub magnitudes... */
+
+ /* Round the result. If the extension is all zeros,then the result is
+ * exact. Otherwise round in the correct direction. No underflow is
+ * possible. If a postnormalization is necessary, then the mantissa is
+ * all zeros so no shift is needed. */
+ round:
+ if(Ext_isnotzero(extent))
+ {
+ inexact = TRUE;
+ switch(Rounding_mode())
+ {
+ case ROUNDNEAREST: /* The default. */
+ if(Ext_isone_sign(extent))
+ {
+ /* at least 1/2 ulp */
+ if(Ext_isnotzero_lower(extent) ||
+ Sgl_isone_lowmantissa(result))
+ {
+ /* either exactly half way and odd or more than 1/2ulp */
+ Sgl_increment(result);
+ }
+ }
+ break;
+
+ case ROUNDPLUS:
+ if(Sgl_iszero_sign(result))
+ {
+ /* Round up positive results */
+ Sgl_increment(result);
+ }
+ break;
+
+ case ROUNDMINUS:
+ if(Sgl_isone_sign(result))
+ {
+ /* Round down negative results */
+ Sgl_increment(result);
+ }
+
+ case ROUNDZERO:;
+ /* truncate is simple */
+ } /* end switch... */
+ if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
+ }
+ if(result_exponent == SGL_INFINITY_EXPONENT)
+ {
+ /* Overflow */
+ if(Is_overflowtrap_enabled())
+ {
+ Sgl_setwrapped_exponent(result,result_exponent,ovfl);
+ *dstptr = result;
+ if (inexact)
+ if (Is_inexacttrap_enabled())
+ return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(OVERFLOWEXCEPTION);
+ }
+ else
+ {
+ Set_overflowflag();
+ inexact = TRUE;
+ Sgl_setoverflow(result);
+ }
+ }
+ else Sgl_set_exponent(result,result_exponent);
+ *dstptr = result;
+ if(inexact)
+ if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+ else Set_inexactflag();
+ return(NOEXCEPTION);
+ }
diff --git a/arch/parisc/math-emu/sgl_float.h b/arch/parisc/math-emu/sgl_float.h
new file mode 100644
index 000000000000..82519a5c2ba5
--- /dev/null
+++ b/arch/parisc/math-emu/sgl_float.h
@@ -0,0 +1,486 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef __NO_PA_HDRS
+ PA header file -- do not include this header file for non-PA builds.
+#endif
+
+/* 32-bit word grabing functions */
+#define Sgl_firstword(value) Sall(value)
+#define Sgl_secondword(value) dummy_location
+#define Sgl_thirdword(value) dummy_location
+#define Sgl_fourthword(value) dummy_location
+
+#define Sgl_sign(object) Ssign(object)
+#define Sgl_exponent(object) Sexponent(object)
+#define Sgl_signexponent(object) Ssignexponent(object)
+#define Sgl_mantissa(object) Smantissa(object)
+#define Sgl_exponentmantissa(object) Sexponentmantissa(object)
+#define Sgl_all(object) Sall(object)
+
+/* sgl_and_signs ands the sign bits of each argument and puts the result
+ * into the first argument. sgl_or_signs ors those same sign bits */
+#define Sgl_and_signs( src1dst, src2) \
+ Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst)
+#define Sgl_or_signs( src1dst, src2) \
+ Sall(src1dst) = (Sall(src2)&((unsigned int)1<<31)) | Sall(src1dst)
+
+/* The hidden bit is always the low bit of the exponent */
+#define Sgl_clear_exponent_set_hidden(srcdst) Deposit_sexponent(srcdst,1)
+#define Sgl_clear_signexponent_set_hidden(srcdst) \
+ Deposit_ssignexponent(srcdst,1)
+#define Sgl_clear_sign(srcdst) Sall(srcdst) &= ~((unsigned int)1<<31)
+#define Sgl_clear_signexponent(srcdst) Sall(srcdst) &= 0x007fffff
+
+/* varamount must be less than 32 for the next three functions */
+#define Sgl_rightshift(srcdst, varamount) \
+ Sall(srcdst) >>= varamount
+#define Sgl_leftshift(srcdst, varamount) \
+ Sall(srcdst) <<= varamount
+#define Sgl_rightshift_exponentmantissa(srcdst, varamount) \
+ Sall(srcdst) = \
+ (Sexponentmantissa(srcdst) >> varamount) | \
+ (Sall(srcdst) & ((unsigned int)1<<31))
+
+#define Sgl_leftshiftby1_withextent(left,right,result) \
+ Shiftdouble(Sall(left),Extall(right),31,Sall(result))
+
+#define Sgl_rightshiftby1_withextent(left,right,dst) \
+ Shiftdouble(Sall(left),Extall(right),1,Extall(right))
+#define Sgl_arithrightshiftby1(srcdst) \
+ Sall(srcdst) = (int)Sall(srcdst) >> 1
+
+/* Sign extend the sign bit with an integer destination */
+#define Sgl_signextendedsign(value) Ssignedsign(value)
+
+#define Sgl_isone_hidden(sgl_value) (Shidden(sgl_value))
+#define Sgl_increment(sgl_value) Sall(sgl_value) += 1
+#define Sgl_increment_mantissa(sgl_value) \
+ Deposit_smantissa(sgl_value,sgl_value+1)
+#define Sgl_decrement(sgl_value) Sall(sgl_value) -= 1
+
+#define Sgl_isone_sign(sgl_value) (Is_ssign(sgl_value)!=0)
+#define Sgl_isone_hiddenoverflow(sgl_value) \
+ (Is_shiddenoverflow(sgl_value)!=0)
+#define Sgl_isone_lowmantissa(sgl_value) (Is_slow(sgl_value)!=0)
+#define Sgl_isone_signaling(sgl_value) (Is_ssignaling(sgl_value)!=0)
+#define Sgl_is_signalingnan(sgl_value) (Ssignalingnan(sgl_value)==0x1ff)
+#define Sgl_isnotzero(sgl_value) (Sall(sgl_value)!=0)
+#define Sgl_isnotzero_hiddenhigh7mantissa(sgl_value) \
+ (Shiddenhigh7mantissa(sgl_value)!=0)
+#define Sgl_isnotzero_low4(sgl_value) (Slow4(sgl_value)!=0)
+#define Sgl_isnotzero_exponent(sgl_value) (Sexponent(sgl_value)!=0)
+#define Sgl_isnotzero_mantissa(sgl_value) (Smantissa(sgl_value)!=0)
+#define Sgl_isnotzero_exponentmantissa(sgl_value) \
+ (Sexponentmantissa(sgl_value)!=0)
+#define Sgl_iszero(sgl_value) (Sall(sgl_value)==0)
+#define Sgl_iszero_signaling(sgl_value) (Is_ssignaling(sgl_value)==0)
+#define Sgl_iszero_hidden(sgl_value) (Is_shidden(sgl_value)==0)
+#define Sgl_iszero_hiddenoverflow(sgl_value) \
+ (Is_shiddenoverflow(sgl_value)==0)
+#define Sgl_iszero_hiddenhigh3mantissa(sgl_value) \
+ (Shiddenhigh3mantissa(sgl_value)==0)
+#define Sgl_iszero_hiddenhigh7mantissa(sgl_value) \
+ (Shiddenhigh7mantissa(sgl_value)==0)
+#define Sgl_iszero_sign(sgl_value) (Is_ssign(sgl_value)==0)
+#define Sgl_iszero_exponent(sgl_value) (Sexponent(sgl_value)==0)
+#define Sgl_iszero_mantissa(sgl_value) (Smantissa(sgl_value)==0)
+#define Sgl_iszero_exponentmantissa(sgl_value) \
+ (Sexponentmantissa(sgl_value)==0)
+#define Sgl_isinfinity_exponent(sgl_value) \
+ (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT)
+#define Sgl_isnotinfinity_exponent(sgl_value) \
+ (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT)
+#define Sgl_isinfinity(sgl_value) \
+ (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \
+ Sgl_mantissa(sgl_value)==0)
+#define Sgl_isnan(sgl_value) \
+ (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \
+ Sgl_mantissa(sgl_value)!=0)
+#define Sgl_isnotnan(sgl_value) \
+ (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT || \
+ Sgl_mantissa(sgl_value)==0)
+#define Sgl_islessthan(sgl_op1,sgl_op2) \
+ (Sall(sgl_op1) < Sall(sgl_op2))
+#define Sgl_isgreaterthan(sgl_op1,sgl_op2) \
+ (Sall(sgl_op1) > Sall(sgl_op2))
+#define Sgl_isnotlessthan(sgl_op1,sgl_op2) \
+ (Sall(sgl_op1) >= Sall(sgl_op2))
+#define Sgl_isequal(sgl_op1,sgl_op2) \
+ (Sall(sgl_op1) == Sall(sgl_op2))
+
+#define Sgl_leftshiftby8(sgl_value) \
+ Sall(sgl_value) <<= 8
+#define Sgl_leftshiftby4(sgl_value) \
+ Sall(sgl_value) <<= 4
+#define Sgl_leftshiftby3(sgl_value) \
+ Sall(sgl_value) <<= 3
+#define Sgl_leftshiftby2(sgl_value) \
+ Sall(sgl_value) <<= 2
+#define Sgl_leftshiftby1(sgl_value) \
+ Sall(sgl_value) <<= 1
+#define Sgl_rightshiftby1(sgl_value) \
+ Sall(sgl_value) >>= 1
+#define Sgl_rightshiftby4(sgl_value) \
+ Sall(sgl_value) >>= 4
+#define Sgl_rightshiftby8(sgl_value) \
+ Sall(sgl_value) >>= 8
+
+#define Sgl_ismagnitudeless(signlessleft,signlessright) \
+/* unsigned int signlessleft, signlessright; */ \
+ (signlessleft < signlessright)
+
+
+#define Sgl_copytoint_exponentmantissa(source,dest) \
+ dest = Sexponentmantissa(source)
+
+/* A quiet NaN has the high mantissa bit clear and at least on other (in this
+ * case the adjacent bit) bit set. */
+#define Sgl_set_quiet(sgl_value) Deposit_shigh2mantissa(sgl_value,1)
+#define Sgl_set_exponent(sgl_value,exp) Deposit_sexponent(sgl_value,exp)
+
+#define Sgl_set_mantissa(dest,value) Deposit_smantissa(dest,value)
+#define Sgl_set_exponentmantissa(dest,value) \
+ Deposit_sexponentmantissa(dest,value)
+
+/* An infinity is represented with the max exponent and a zero mantissa */
+#define Sgl_setinfinity_exponent(sgl_value) \
+ Deposit_sexponent(sgl_value,SGL_INFINITY_EXPONENT)
+#define Sgl_setinfinity_exponentmantissa(sgl_value) \
+ Deposit_sexponentmantissa(sgl_value, \
+ (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))))
+#define Sgl_setinfinitypositive(sgl_value) \
+ Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH)))
+#define Sgl_setinfinitynegative(sgl_value) \
+ Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) \
+ | ((unsigned int)1<<31)
+#define Sgl_setinfinity(sgl_value,sign) \
+ Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | \
+ ((unsigned int)sign << 31)
+#define Sgl_sethigh4bits(sgl_value, extsign) \
+ Deposit_shigh4(sgl_value,extsign)
+#define Sgl_set_sign(sgl_value,sign) Deposit_ssign(sgl_value,sign)
+#define Sgl_invert_sign(sgl_value) \
+ Deposit_ssign(sgl_value,~Ssign(sgl_value))
+#define Sgl_setone_sign(sgl_value) Deposit_ssign(sgl_value,1)
+#define Sgl_setone_lowmantissa(sgl_value) Deposit_slow(sgl_value,1)
+#define Sgl_setzero_sign(sgl_value) Sall(sgl_value) &= 0x7fffffff
+#define Sgl_setzero_exponent(sgl_value) Sall(sgl_value) &= 0x807fffff
+#define Sgl_setzero_mantissa(sgl_value) Sall(sgl_value) &= 0xff800000
+#define Sgl_setzero_exponentmantissa(sgl_value) Sall(sgl_value) &= 0x80000000
+#define Sgl_setzero(sgl_value) Sall(sgl_value) = 0
+#define Sgl_setnegativezero(sgl_value) Sall(sgl_value) = (unsigned int)1 << 31
+
+/* Use following macro for both overflow & underflow conditions */
+#define ovfl -
+#define unfl +
+#define Sgl_setwrapped_exponent(sgl_value,exponent,op) \
+ Deposit_sexponent(sgl_value,(exponent op SGL_WRAP))
+
+#define Sgl_setlargestpositive(sgl_value) \
+ Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
+ | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 )
+#define Sgl_setlargestnegative(sgl_value) \
+ Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
+ | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) \
+ | ((unsigned int)1<<31)
+
+#define Sgl_setnegativeinfinity(sgl_value) \
+ Sall(sgl_value) = \
+ ((1<<SGL_EXP_LENGTH) | SGL_INFINITY_EXPONENT) << (32-(1+SGL_EXP_LENGTH))
+#define Sgl_setlargest(sgl_value,sign) \
+ Sall(sgl_value) = (unsigned int)sign << 31 | \
+ (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
+ | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 ))
+#define Sgl_setlargest_exponentmantissa(sgl_value) \
+ Sall(sgl_value) = Sall(sgl_value) & ((unsigned int)1<<31) | \
+ (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
+ | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 ))
+
+/* The high bit is always zero so arithmetic or logical shifts will work. */
+#define Sgl_right_align(srcdst,shift,extent) \
+ /* sgl_floating_point srcdst; int shift; extension extent */ \
+ if (shift < 32) { \
+ Extall(extent) = Sall(srcdst) << (32-(shift)); \
+ Sall(srcdst) >>= shift; \
+ } \
+ else { \
+ Extall(extent) = Sall(srcdst); \
+ Sall(srcdst) = 0; \
+ }
+#define Sgl_hiddenhigh3mantissa(sgl_value) Shiddenhigh3mantissa(sgl_value)
+#define Sgl_hidden(sgl_value) Shidden(sgl_value)
+#define Sgl_lowmantissa(sgl_value) Slow(sgl_value)
+
+/* The left argument is never smaller than the right argument */
+#define Sgl_subtract(sgl_left,sgl_right,sgl_result) \
+ Sall(sgl_result) = Sall(sgl_left) - Sall(sgl_right)
+
+/* Subtract right augmented with extension from left augmented with zeros and
+ * store into result and extension. */
+#define Sgl_subtract_withextension(left,right,extent,result) \
+ /* sgl_floating_point left,right,result; extension extent */ \
+ Sgl_subtract(left,right,result); \
+ if((Extall(extent) = 0-Extall(extent))) \
+ Sall(result) = Sall(result)-1
+
+#define Sgl_addition(sgl_left,sgl_right,sgl_result) \
+ Sall(sgl_result) = Sall(sgl_left) + Sall(sgl_right)
+
+#define Sgl_xortointp1(left,right,result) \
+ result = Sall(left) XOR Sall(right);
+
+#define Sgl_xorfromintp1(left,right,result) \
+ Sall(result) = left XOR Sall(right)
+
+/* Need to Initialize */
+#define Sgl_makequietnan(dest) \
+ Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \
+ | (1<<(32-(1+SGL_EXP_LENGTH+2)))
+#define Sgl_makesignalingnan(dest) \
+ Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \
+ | (1<<(32-(1+SGL_EXP_LENGTH+1)))
+
+#define Sgl_normalize(sgl_opnd,exponent) \
+ while(Sgl_iszero_hiddenhigh7mantissa(sgl_opnd)) { \
+ Sgl_leftshiftby8(sgl_opnd); \
+ exponent -= 8; \
+ } \
+ if(Sgl_iszero_hiddenhigh3mantissa(sgl_opnd)) { \
+ Sgl_leftshiftby4(sgl_opnd); \
+ exponent -= 4; \
+ } \
+ while(Sgl_iszero_hidden(sgl_opnd)) { \
+ Sgl_leftshiftby1(sgl_opnd); \
+ exponent -= 1; \
+ }
+
+#define Sgl_setoverflow(sgl_opnd) \
+ /* set result to infinity or largest number */ \
+ switch (Rounding_mode()) { \
+ case ROUNDPLUS: \
+ if (Sgl_isone_sign(sgl_opnd)) { \
+ Sgl_setlargestnegative(sgl_opnd); \
+ } \
+ else { \
+ Sgl_setinfinitypositive(sgl_opnd); \
+ } \
+ break; \
+ case ROUNDMINUS: \
+ if (Sgl_iszero_sign(sgl_opnd)) { \
+ Sgl_setlargestpositive(sgl_opnd); \
+ } \
+ else { \
+ Sgl_setinfinitynegative(sgl_opnd); \
+ } \
+ break; \
+ case ROUNDNEAREST: \
+ Sgl_setinfinity_exponentmantissa(sgl_opnd); \
+ break; \
+ case ROUNDZERO: \
+ Sgl_setlargest_exponentmantissa(sgl_opnd); \
+ }
+
+#define Sgl_denormalize(opnd,exponent,guard,sticky,inexact) \
+ Sgl_clear_signexponent_set_hidden(opnd); \
+ if (exponent >= (1 - SGL_P)) { \
+ guard = (Sall(opnd) >> -exponent) & 1; \
+ if (exponent < 0) sticky |= Sall(opnd) << (32+exponent); \
+ inexact = guard | sticky; \
+ Sall(opnd) >>= (1-exponent); \
+ } \
+ else { \
+ guard = 0; \
+ sticky |= Sall(opnd); \
+ inexact = sticky; \
+ Sgl_setzero(opnd); \
+ }
+
+/*
+ * The fused multiply add instructions requires a single extended format,
+ * with 48 bits of mantissa.
+ */
+#define SGLEXT_THRESHOLD 48
+
+#define Sglext_setzero(valA,valB) \
+ Sextallp1(valA) = 0; Sextallp2(valB) = 0
+
+#define Sglext_isnotzero_mantissap2(valB) (Sextallp2(valB)!=0)
+#define Sglext_isone_lowp1(val) (Sextlowp1(val)!=0)
+#define Sglext_isone_highp2(val) (Sexthighp2(val)!=0)
+#define Sglext_isnotzero_low31p2(val) (Sextlow31p2(val)!=0)
+#define Sglext_iszero(valA,valB) (Sextallp1(valA)==0 && Sextallp2(valB)==0)
+
+#define Sgl_copytoptr(src,destptr) *destptr = src
+#define Sgl_copyfromptr(srcptr,dest) dest = *srcptr
+#define Sglext_copy(srca,srcb,desta,destb) \
+ Sextallp1(desta) = Sextallp1(srca); \
+ Sextallp2(destb) = Sextallp2(srcb)
+#define Sgl_copyto_sglext(src1,dest1,dest2) \
+ Sextallp1(dest1) = Sall(src1); Sextallp2(dest2) = 0
+
+#define Sglext_swap_lower(leftp2,rightp2) \
+ Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \
+ Sextallp2(rightp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \
+ Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2)
+
+#define Sglext_setone_lowmantissap2(value) Deposit_dlowp2(value,1)
+
+/* The high bit is always zero so arithmetic or logical shifts will work. */
+#define Sglext_right_align(srcdstA,srcdstB,shift) \
+ {int shiftamt, sticky; \
+ shiftamt = shift % 32; \
+ sticky = 0; \
+ switch (shift/32) { \
+ case 0: if (shiftamt > 0) { \
+ sticky = Sextallp2(srcdstB) << 32 - (shiftamt); \
+ Variable_shift_double(Sextallp1(srcdstA), \
+ Sextallp2(srcdstB),shiftamt,Sextallp2(srcdstB)); \
+ Sextallp1(srcdstA) >>= shiftamt; \
+ } \
+ break; \
+ case 1: if (shiftamt > 0) { \
+ sticky = (Sextallp1(srcdstA) << 32 - (shiftamt)) | \
+ Sextallp2(srcdstB); \
+ } \
+ else { \
+ sticky = Sextallp2(srcdstB); \
+ } \
+ Sextallp2(srcdstB) = Sextallp1(srcdstA) >> shiftamt; \
+ Sextallp1(srcdstA) = 0; \
+ break; \
+ } \
+ if (sticky) Sglext_setone_lowmantissap2(srcdstB); \
+ }
+
+/* The left argument is never smaller than the right argument */
+#define Sglext_subtract(lefta,leftb,righta,rightb,resulta,resultb) \
+ if( Sextallp2(rightb) > Sextallp2(leftb) ) Sextallp1(lefta)--; \
+ Sextallp2(resultb) = Sextallp2(leftb) - Sextallp2(rightb); \
+ Sextallp1(resulta) = Sextallp1(lefta) - Sextallp1(righta)
+
+#define Sglext_addition(lefta,leftb,righta,rightb,resulta,resultb) \
+ /* If the sum of the low words is less than either source, then \
+ * an overflow into the next word occurred. */ \
+ if ((Sextallp2(resultb) = Sextallp2(leftb)+Sextallp2(rightb)) < \
+ Sextallp2(rightb)) \
+ Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)+1; \
+ else Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)
+
+
+#define Sglext_arithrightshiftby1(srcdstA,srcdstB) \
+ Shiftdouble(Sextallp1(srcdstA),Sextallp2(srcdstB),1,Sextallp2(srcdstB)); \
+ Sextallp1(srcdstA) = (int)Sextallp1(srcdstA) >> 1
+
+#define Sglext_leftshiftby8(valA,valB) \
+ Shiftdouble(Sextallp1(valA),Sextallp2(valB),24,Sextallp1(valA)); \
+ Sextallp2(valB) <<= 8
+#define Sglext_leftshiftby4(valA,valB) \
+ Shiftdouble(Sextallp1(valA),Sextallp2(valB),28,Sextallp1(valA)); \
+ Sextallp2(valB) <<= 4
+#define Sglext_leftshiftby3(valA,valB) \
+ Shiftdouble(Sextallp1(valA),Sextallp2(valB),29,Sextallp1(valA)); \
+ Sextallp2(valB) <<= 3
+#define Sglext_leftshiftby2(valA,valB) \
+ Shiftdouble(Sextallp1(valA),Sextallp2(valB),30,Sextallp1(valA)); \
+ Sextallp2(valB) <<= 2
+#define Sglext_leftshiftby1(valA,valB) \
+ Shiftdouble(Sextallp1(valA),Sextallp2(valB),31,Sextallp1(valA)); \
+ Sextallp2(valB) <<= 1
+
+#define Sglext_rightshiftby4(valueA,valueB) \
+ Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),4,Sextallp2(valueB)); \
+ Sextallp1(valueA) >>= 4
+#define Sglext_rightshiftby3(valueA,valueB) \
+ Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),3,Sextallp2(valueB)); \
+ Sextallp1(valueA) >>= 3
+#define Sglext_rightshiftby1(valueA,valueB) \
+ Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),1,Sextallp2(valueB)); \
+ Sextallp1(valueA) >>= 1
+
+#define Sglext_xortointp1(left,right,result) Sgl_xortointp1(left,right,result)
+#define Sglext_xorfromintp1(left,right,result) \
+ Sgl_xorfromintp1(left,right,result)
+#define Sglext_copytoint_exponentmantissa(src,dest) \
+ Sgl_copytoint_exponentmantissa(src,dest)
+#define Sglext_ismagnitudeless(signlessleft,signlessright) \
+ Sgl_ismagnitudeless(signlessleft,signlessright)
+
+#define Sglext_set_sign(dbl_value,sign) Sgl_set_sign(dbl_value,sign)
+#define Sglext_clear_signexponent_set_hidden(srcdst) \
+ Sgl_clear_signexponent_set_hidden(srcdst)
+#define Sglext_clear_signexponent(srcdst) Sgl_clear_signexponent(srcdst)
+#define Sglext_clear_sign(srcdst) Sgl_clear_sign(srcdst)
+#define Sglext_isone_hidden(dbl_value) Sgl_isone_hidden(dbl_value)
+
+#define Sglext_denormalize(opndp1,opndp2,exponent,is_tiny) \
+ {int sticky; \
+ is_tiny = TRUE; \
+ if (exponent == 0 && Sextallp2(opndp2)) { \
+ switch (Rounding_mode()) { \
+ case ROUNDPLUS: \
+ if (Sgl_iszero_sign(opndp1)) \
+ if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
+ is_tiny = FALSE; \
+ break; \
+ case ROUNDMINUS: \
+ if (Sgl_isone_sign(opndp1)) { \
+ if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
+ is_tiny = FALSE; \
+ } \
+ break; \
+ case ROUNDNEAREST: \
+ if (Sglext_isone_highp2(opndp2) && \
+ (Sglext_isone_lowp1(opndp1) || \
+ Sglext_isnotzero_low31p2(opndp2))) \
+ if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
+ is_tiny = FALSE; \
+ break; \
+ } \
+ } \
+ Sglext_clear_signexponent_set_hidden(opndp1); \
+ if (exponent >= (1-DBL_P)) { \
+ if (exponent >= -31) { \
+ if (exponent > -31) { \
+ sticky = Sextallp2(opndp2) << 31+exponent; \
+ Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \
+ Sextallp1(opndp1) >>= 1-exponent; \
+ } \
+ else { \
+ sticky = Sextallp2(opndp2); \
+ Sextallp2(opndp2) = Sextallp1(opndp1); \
+ Sextallp1(opndp1) = 0; \
+ } \
+ } \
+ else { \
+ sticky = (Sextallp1(opndp1) << 31+exponent) | \
+ Sextallp2(opndp2); \
+ Sextallp2(opndp2) = Sextallp1(opndp1) >> -31-exponent; \
+ Sextallp1(opndp1) = 0; \
+ } \
+ } \
+ else { \
+ sticky = Sextallp1(opndp1) | Sextallp2(opndp2); \
+ Sglext_setzero(opndp1,opndp2); \
+ } \
+ if (sticky) Sglext_setone_lowmantissap2(opndp2); \
+ exponent = 0; \
+ }
diff --git a/arch/parisc/mm/Makefile b/arch/parisc/mm/Makefile
new file mode 100644
index 000000000000..758ceefb373a
--- /dev/null
+++ b/arch/parisc/mm/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for arch/parisc/mm
+#
+
+obj-y := init.o fault.o ioremap.o
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
new file mode 100644
index 000000000000..eaa701479f5f
--- /dev/null
+++ b/arch/parisc/mm/fault.c
@@ -0,0 +1,271 @@
+/* $Id: fault.c,v 1.5 2000/01/26 16:20:29 jsm Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
+ * Copyright 1999 Hewlett Packard Co.
+ *
+ */
+
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+#include <asm/traps.h>
+
+#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
+ /* dumped to the console via printk) */
+
+
+/* Defines for parisc_acctyp() */
+#define READ 0
+#define WRITE 1
+
+/* Various important other fields */
+#define bit22set(x) (x & 0x00000200)
+#define bits23_25set(x) (x & 0x000001c0)
+#define isGraphicsFlushRead(x) ((x & 0xfc003fdf) == 0x04001a80)
+ /* extended opcode is 0x6a */
+
+#define BITSSET 0x1c0 /* for identifying LDCW */
+
+
+DEFINE_PER_CPU(struct exception_data, exception_data);
+
+/*
+ * parisc_acctyp(unsigned int inst) --
+ * Given a PA-RISC memory access instruction, determine if the
+ * the instruction would perform a memory read or memory write
+ * operation.
+ *
+ * This function assumes that the given instruction is a memory access
+ * instruction (i.e. you should really only call it if you know that
+ * the instruction has generated some sort of a memory access fault).
+ *
+ * Returns:
+ * VM_READ if read operation
+ * VM_WRITE if write operation
+ * VM_EXEC if execute operation
+ */
+static unsigned long
+parisc_acctyp(unsigned long code, unsigned int inst)
+{
+ if (code == 6 || code == 16)
+ return VM_EXEC;
+
+ switch (inst & 0xf0000000) {
+ case 0x40000000: /* load */
+ case 0x50000000: /* new load */
+ return VM_READ;
+
+ case 0x60000000: /* store */
+ case 0x70000000: /* new store */
+ return VM_WRITE;
+
+ case 0x20000000: /* coproc */
+ case 0x30000000: /* coproc2 */
+ if (bit22set(inst))
+ return VM_WRITE;
+
+ case 0x0: /* indexed/memory management */
+ if (bit22set(inst)) {
+ /*
+ * Check for the 'Graphics Flush Read' instruction.
+ * It resembles an FDC instruction, except for bits
+ * 20 and 21. Any combination other than zero will
+ * utilize the block mover functionality on some
+ * older PA-RISC platforms. The case where a block
+ * move is performed from VM to graphics IO space
+ * should be treated as a READ.
+ *
+ * The significance of bits 20,21 in the FDC
+ * instruction is:
+ *
+ * 00 Flush data cache (normal instruction behavior)
+ * 01 Graphics flush write (IO space -> VM)
+ * 10 Graphics flush read (VM -> IO space)
+ * 11 Graphics flush read/write (VM <-> IO space)
+ */
+ if (isGraphicsFlushRead(inst))
+ return VM_READ;
+ return VM_WRITE;
+ } else {
+ /*
+ * Check for LDCWX and LDCWS (semaphore instructions).
+ * If bits 23 through 25 are all 1's it is one of
+ * the above two instructions and is a write.
+ *
+ * Note: With the limited bits we are looking at,
+ * this will also catch PROBEW and PROBEWI. However,
+ * these should never get in here because they don't
+ * generate exceptions of the type:
+ * Data TLB miss fault/data page fault
+ * Data memory protection trap
+ */
+ if (bits23_25set(inst) == BITSSET)
+ return VM_WRITE;
+ }
+ return VM_READ; /* Default */
+ }
+ return VM_READ; /* Default */
+}
+
+#undef bit22set
+#undef bits23_25set
+#undef isGraphicsFlushRead
+#undef BITSSET
+
+
+#if 0
+/* This is the treewalk to find a vma which is the highest that has
+ * a start < addr. We're using find_vma_prev instead right now, but
+ * we might want to use this at some point in the future. Probably
+ * not, but I want it committed to CVS so I don't lose it :-)
+ */
+ while (tree != vm_avl_empty) {
+ if (tree->vm_start > addr) {
+ tree = tree->vm_avl_left;
+ } else {
+ prev = tree;
+ if (prev->vm_next == NULL)
+ break;
+ if (prev->vm_next->vm_start > addr)
+ break;
+ tree = tree->vm_avl_right;
+ }
+ }
+#endif
+
+void do_page_fault(struct pt_regs *regs, unsigned long code,
+ unsigned long address)
+{
+ struct vm_area_struct *vma, *prev_vma;
+ struct task_struct *tsk = current;
+ struct mm_struct *mm = tsk->mm;
+ const struct exception_table_entry *fix;
+ unsigned long acc_type;
+
+ if (in_interrupt() || !mm)
+ goto no_context;
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma_prev(mm, address, &prev_vma);
+ if (!vma || address < vma->vm_start)
+ goto check_expansion;
+/*
+ * Ok, we have a good vm_area for this memory access. We still need to
+ * check the access permissions.
+ */
+
+good_area:
+
+ acc_type = parisc_acctyp(code,regs->iir);
+
+ if ((vma->vm_flags & acc_type) != acc_type)
+ goto bad_area;
+
+ /*
+ * If for any reason at all we couldn't handle the fault, make
+ * sure we exit gracefully rather than endlessly redo the
+ * fault.
+ */
+
+ switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) {
+ case 1:
+ ++current->min_flt;
+ break;
+ case 2:
+ ++current->maj_flt;
+ break;
+ case 0:
+ /*
+ * We ran out of memory, or some other thing happened
+ * to us that made us unable to handle the page fault
+ * gracefully.
+ */
+ goto bad_area;
+ default:
+ goto out_of_memory;
+ }
+ up_read(&mm->mmap_sem);
+ return;
+
+check_expansion:
+ vma = prev_vma;
+ if (vma && (expand_stack(vma, address) == 0))
+ goto good_area;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ */
+bad_area:
+ up_read(&mm->mmap_sem);
+
+ if (user_mode(regs)) {
+ struct siginfo si;
+
+#ifdef PRINT_USER_FAULTS
+ printk(KERN_DEBUG "\n");
+ printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n",
+ tsk->pid, tsk->comm, code, address);
+ if (vma) {
+ printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n",
+ vma->vm_start, vma->vm_end);
+ }
+ show_regs(regs);
+#endif
+ /* FIXME: actually we need to get the signo and code correct */
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SEGV_MAPERR;
+ si.si_addr = (void __user *) address;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+ }
+
+no_context:
+
+ if (!user_mode(regs)) {
+ fix = search_exception_tables(regs->iaoq[0]);
+
+ if (fix) {
+ struct exception_data *d;
+
+ d = &__get_cpu_var(exception_data);
+ d->fault_ip = regs->iaoq[0];
+ d->fault_space = regs->isr;
+ d->fault_addr = regs->ior;
+
+ regs->iaoq[0] = ((fix->fixup) & ~3);
+
+ /*
+ * NOTE: In some cases the faulting instruction
+ * may be in the delay slot of a branch. We
+ * don't want to take the branch, so we don't
+ * increment iaoq[1], instead we set it to be
+ * iaoq[0]+4, and clear the B bit in the PSW
+ */
+
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */
+
+ return;
+ }
+ }
+
+ parisc_terminate("Bad Address (null pointer deref?)", regs, code, address);
+
+ out_of_memory:
+ up_read(&mm->mmap_sem);
+ printk(KERN_CRIT "VM: killing process %s\n", current->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ goto no_context;
+}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
new file mode 100644
index 000000000000..cac37589e35c
--- /dev/null
+++ b/arch/parisc/mm/init.c
@@ -0,0 +1,1019 @@
+/*
+ * linux/arch/parisc/mm/init.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright 1999 SuSE GmbH
+ * changed by Philipp Rumpf
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ * Copyright 2004 Randolph Chung (tausq@debian.org)
+ *
+ */
+
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h> /* for hppa_dma_ops and pcxl_dma_ops */
+#include <linux/initrd.h>
+#include <linux/swap.h>
+#include <linux/unistd.h>
+#include <linux/nodemask.h> /* for node_online_map */
+#include <linux/pagemap.h> /* for release_pages and page_cache_release */
+
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/pdc_chassis.h>
+#include <asm/mmzone.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+extern char _text; /* start of kernel code, defined by linker */
+extern int data_start;
+extern char _end; /* end of BSS, defined by linker */
+extern char __init_begin, __init_end;
+
+#ifdef CONFIG_DISCONTIGMEM
+struct node_map_data node_data[MAX_NUMNODES];
+bootmem_data_t bmem_data[MAX_NUMNODES];
+unsigned char pfnnid_map[PFNNID_MAP_MAX];
+#endif
+
+static struct resource data_resource = {
+ .name = "Kernel data",
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource code_resource = {
+ .name = "Kernel code",
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource pdcdata_resource = {
+ .name = "PDC data (Page Zero)",
+ .start = 0,
+ .end = 0x9ff,
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource sysram_resources[MAX_PHYSMEM_RANGES];
+
+/* The following array is initialized from the firmware specific
+ * information retrieved in kernel/inventory.c.
+ */
+
+physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES];
+int npmem_ranges;
+
+#ifdef __LP64__
+#define MAX_MEM (~0UL)
+#else /* !__LP64__ */
+#define MAX_MEM (3584U*1024U*1024U)
+#endif /* !__LP64__ */
+
+static unsigned long mem_limit = MAX_MEM;
+
+static void __init mem_limit_func(void)
+{
+ char *cp, *end;
+ unsigned long limit;
+ extern char saved_command_line[];
+
+ /* We need this before __setup() functions are called */
+
+ limit = MAX_MEM;
+ for (cp = saved_command_line; *cp; ) {
+ if (memcmp(cp, "mem=", 4) == 0) {
+ cp += 4;
+ limit = memparse(cp, &end);
+ if (end != cp)
+ break;
+ cp = end;
+ } else {
+ while (*cp != ' ' && *cp)
+ ++cp;
+ while (*cp == ' ')
+ ++cp;
+ }
+ }
+
+ if (limit < mem_limit)
+ mem_limit = limit;
+}
+
+#define MAX_GAP (0x40000000UL >> PAGE_SHIFT)
+
+static void __init setup_bootmem(void)
+{
+ unsigned long bootmap_size;
+ unsigned long mem_max;
+ unsigned long bootmap_pages;
+ unsigned long bootmap_start_pfn;
+ unsigned long bootmap_pfn;
+#ifndef CONFIG_DISCONTIGMEM
+ physmem_range_t pmem_holes[MAX_PHYSMEM_RANGES - 1];
+ int npmem_holes;
+#endif
+ int i, sysram_resource_count;
+
+ disable_sr_hashing(); /* Turn off space register hashing */
+
+ /*
+ * Sort the ranges. Since the number of ranges is typically
+ * small, and performance is not an issue here, just do
+ * a simple insertion sort.
+ */
+
+ for (i = 1; i < npmem_ranges; i++) {
+ int j;
+
+ for (j = i; j > 0; j--) {
+ unsigned long tmp;
+
+ if (pmem_ranges[j-1].start_pfn <
+ pmem_ranges[j].start_pfn) {
+
+ break;
+ }
+ tmp = pmem_ranges[j-1].start_pfn;
+ pmem_ranges[j-1].start_pfn = pmem_ranges[j].start_pfn;
+ pmem_ranges[j].start_pfn = tmp;
+ tmp = pmem_ranges[j-1].pages;
+ pmem_ranges[j-1].pages = pmem_ranges[j].pages;
+ pmem_ranges[j].pages = tmp;
+ }
+ }
+
+#ifndef CONFIG_DISCONTIGMEM
+ /*
+ * Throw out ranges that are too far apart (controlled by
+ * MAX_GAP).
+ */
+
+ for (i = 1; i < npmem_ranges; i++) {
+ if (pmem_ranges[i].start_pfn -
+ (pmem_ranges[i-1].start_pfn +
+ pmem_ranges[i-1].pages) > MAX_GAP) {
+ npmem_ranges = i;
+ printk("Large gap in memory detected (%ld pages). "
+ "Consider turning on CONFIG_DISCONTIGMEM\n",
+ pmem_ranges[i].start_pfn -
+ (pmem_ranges[i-1].start_pfn +
+ pmem_ranges[i-1].pages));
+ break;
+ }
+ }
+#endif
+
+ if (npmem_ranges > 1) {
+
+ /* Print the memory ranges */
+
+ printk(KERN_INFO "Memory Ranges:\n");
+
+ for (i = 0; i < npmem_ranges; i++) {
+ unsigned long start;
+ unsigned long size;
+
+ size = (pmem_ranges[i].pages << PAGE_SHIFT);
+ start = (pmem_ranges[i].start_pfn << PAGE_SHIFT);
+ printk(KERN_INFO "%2d) Start 0x%016lx End 0x%016lx Size %6ld MB\n",
+ i,start, start + (size - 1), size >> 20);
+ }
+ }
+
+ sysram_resource_count = npmem_ranges;
+ for (i = 0; i < sysram_resource_count; i++) {
+ struct resource *res = &sysram_resources[i];
+ res->name = "System RAM";
+ res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT;
+ res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ request_resource(&iomem_resource, res);
+ }
+
+ /*
+ * For 32 bit kernels we limit the amount of memory we can
+ * support, in order to preserve enough kernel address space
+ * for other purposes. For 64 bit kernels we don't normally
+ * limit the memory, but this mechanism can be used to
+ * artificially limit the amount of memory (and it is written
+ * to work with multiple memory ranges).
+ */
+
+ mem_limit_func(); /* check for "mem=" argument */
+
+ mem_max = 0;
+ num_physpages = 0;
+ for (i = 0; i < npmem_ranges; i++) {
+ unsigned long rsize;
+
+ rsize = pmem_ranges[i].pages << PAGE_SHIFT;
+ if ((mem_max + rsize) > mem_limit) {
+ printk(KERN_WARNING "Memory truncated to %ld MB\n", mem_limit >> 20);
+ if (mem_max == mem_limit)
+ npmem_ranges = i;
+ else {
+ pmem_ranges[i].pages = (mem_limit >> PAGE_SHIFT)
+ - (mem_max >> PAGE_SHIFT);
+ npmem_ranges = i + 1;
+ mem_max = mem_limit;
+ }
+ num_physpages += pmem_ranges[i].pages;
+ break;
+ }
+ num_physpages += pmem_ranges[i].pages;
+ mem_max += rsize;
+ }
+
+ printk(KERN_INFO "Total Memory: %ld MB\n",mem_max >> 20);
+
+#ifndef CONFIG_DISCONTIGMEM
+ /* Merge the ranges, keeping track of the holes */
+
+ {
+ unsigned long end_pfn;
+ unsigned long hole_pages;
+
+ npmem_holes = 0;
+ end_pfn = pmem_ranges[0].start_pfn + pmem_ranges[0].pages;
+ for (i = 1; i < npmem_ranges; i++) {
+
+ hole_pages = pmem_ranges[i].start_pfn - end_pfn;
+ if (hole_pages) {
+ pmem_holes[npmem_holes].start_pfn = end_pfn;
+ pmem_holes[npmem_holes++].pages = hole_pages;
+ end_pfn += hole_pages;
+ }
+ end_pfn += pmem_ranges[i].pages;
+ }
+
+ pmem_ranges[0].pages = end_pfn - pmem_ranges[0].start_pfn;
+ npmem_ranges = 1;
+ }
+#endif
+
+ bootmap_pages = 0;
+ for (i = 0; i < npmem_ranges; i++)
+ bootmap_pages += bootmem_bootmap_pages(pmem_ranges[i].pages);
+
+ bootmap_start_pfn = PAGE_ALIGN(__pa((unsigned long) &_end)) >> PAGE_SHIFT;
+
+#ifdef CONFIG_DISCONTIGMEM
+ for (i = 0; i < MAX_PHYSMEM_RANGES; i++) {
+ memset(NODE_DATA(i), 0, sizeof(pg_data_t));
+ NODE_DATA(i)->bdata = &bmem_data[i];
+ }
+ memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
+
+ for (i = 0; i < npmem_ranges; i++)
+ node_set_online(i);
+#endif
+
+ /*
+ * Initialize and free the full range of memory in each range.
+ * Note that the only writing these routines do are to the bootmap,
+ * and we've made sure to locate the bootmap properly so that they
+ * won't be writing over anything important.
+ */
+
+ bootmap_pfn = bootmap_start_pfn;
+ max_pfn = 0;
+ for (i = 0; i < npmem_ranges; i++) {
+ unsigned long start_pfn;
+ unsigned long npages;
+
+ start_pfn = pmem_ranges[i].start_pfn;
+ npages = pmem_ranges[i].pages;
+
+ bootmap_size = init_bootmem_node(NODE_DATA(i),
+ bootmap_pfn,
+ start_pfn,
+ (start_pfn + npages) );
+ free_bootmem_node(NODE_DATA(i),
+ (start_pfn << PAGE_SHIFT),
+ (npages << PAGE_SHIFT) );
+ bootmap_pfn += (bootmap_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ if ((start_pfn + npages) > max_pfn)
+ max_pfn = start_pfn + npages;
+ }
+
+ if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) {
+ printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n");
+ BUG();
+ }
+
+ /* reserve PAGE0 pdc memory, kernel text/data/bss & bootmap */
+
+#define PDC_CONSOLE_IO_IODC_SIZE 32768
+
+ reserve_bootmem_node(NODE_DATA(0), 0UL,
+ (unsigned long)(PAGE0->mem_free + PDC_CONSOLE_IO_IODC_SIZE));
+ reserve_bootmem_node(NODE_DATA(0),__pa((unsigned long)&_text),
+ (unsigned long)(&_end - &_text));
+ reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
+ ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT));
+
+#ifndef CONFIG_DISCONTIGMEM
+
+ /* reserve the holes */
+
+ for (i = 0; i < npmem_holes; i++) {
+ reserve_bootmem_node(NODE_DATA(0),
+ (pmem_holes[i].start_pfn << PAGE_SHIFT),
+ (pmem_holes[i].pages << PAGE_SHIFT));
+ }
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start) {
+ printk(KERN_INFO "initrd: %08lx-%08lx\n", initrd_start, initrd_end);
+ if (__pa(initrd_start) < mem_max) {
+ unsigned long initrd_reserve;
+
+ if (__pa(initrd_end) > mem_max) {
+ initrd_reserve = mem_max - __pa(initrd_start);
+ } else {
+ initrd_reserve = initrd_end - initrd_start;
+ }
+ initrd_below_start_ok = 1;
+ printk(KERN_INFO "initrd: reserving %08lx-%08lx (mem_max %08lx)\n", __pa(initrd_start), __pa(initrd_start) + initrd_reserve, mem_max);
+
+ reserve_bootmem_node(NODE_DATA(0),__pa(initrd_start), initrd_reserve);
+ }
+ }
+#endif
+
+ data_resource.start = virt_to_phys(&data_start);
+ data_resource.end = virt_to_phys(&_end)-1;
+ code_resource.start = virt_to_phys(&_text);
+ code_resource.end = virt_to_phys(&data_start)-1;
+
+ /* We don't know which region the kernel will be in, so try
+ * all of them.
+ */
+ for (i = 0; i < sysram_resource_count; i++) {
+ struct resource *res = &sysram_resources[i];
+ request_resource(res, &code_resource);
+ request_resource(res, &data_resource);
+ }
+ request_resource(&sysram_resources[0], &pdcdata_resource);
+}
+
+void free_initmem(void)
+{
+ /* FIXME: */
+#if 0
+ printk(KERN_INFO "NOT FREEING INITMEM (%dk)\n",
+ (&__init_end - &__init_begin) >> 10);
+ return;
+#else
+ unsigned long addr;
+
+ printk(KERN_INFO "Freeing unused kernel memory: ");
+
+#if 1
+ /* Attempt to catch anyone trying to execute code here
+ * by filling the page with BRK insns.
+ *
+ * If we disable interrupts for all CPUs, then IPI stops working.
+ * Kinda breaks the global cache flushing.
+ */
+ local_irq_disable();
+
+ memset(&__init_begin, 0x00,
+ (unsigned long)&__init_end - (unsigned long)&__init_begin);
+
+ flush_data_cache();
+ asm volatile("sync" : : );
+ flush_icache_range((unsigned long)&__init_begin, (unsigned long)&__init_end);
+ asm volatile("sync" : : );
+
+ local_irq_enable();
+#endif
+
+ addr = (unsigned long)(&__init_begin);
+ for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ set_page_count(virt_to_page(addr), 1);
+ free_page(addr);
+ num_physpages++;
+ totalram_pages++;
+ }
+
+ /* set up a new led state on systems shipped LED State panel */
+ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
+
+ printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
+#endif
+}
+
+/*
+ * Just an arbitrary offset to serve as a "hole" between mapping areas
+ * (between top of physical memory and a potential pcxl dma mapping
+ * area, and below the vmalloc mapping area).
+ *
+ * The current 32K value just means that there will be a 32K "hole"
+ * between mapping areas. That means that any out-of-bounds memory
+ * accesses will hopefully be caught. The vmalloc() routines leaves
+ * a hole of 4kB between each vmalloced area for the same reason.
+ */
+
+ /* Leave room for gateway page expansion */
+#if KERNEL_MAP_START < GATEWAY_PAGE_SIZE
+#error KERNEL_MAP_START is in gateway reserved region
+#endif
+#define MAP_START (KERNEL_MAP_START)
+
+#define VM_MAP_OFFSET (32*1024)
+#define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
+ & ~(VM_MAP_OFFSET-1)))
+
+void *vmalloc_start;
+EXPORT_SYMBOL(vmalloc_start);
+
+#ifdef CONFIG_PA11
+unsigned long pcxl_dma_start;
+#endif
+
+void __init mem_init(void)
+{
+ high_memory = __va((max_pfn << PAGE_SHIFT));
+
+#ifndef CONFIG_DISCONTIGMEM
+ max_mapnr = page_to_pfn(virt_to_page(high_memory - 1)) + 1;
+ totalram_pages += free_all_bootmem();
+#else
+ {
+ int i;
+
+ for (i = 0; i < npmem_ranges; i++)
+ totalram_pages += free_all_bootmem_node(NODE_DATA(i));
+ }
+#endif
+
+ printk(KERN_INFO "Memory: %luk available\n", num_physpages << (PAGE_SHIFT-10));
+
+#ifdef CONFIG_PA11
+ if (hppa_dma_ops == &pcxl_dma_ops) {
+ pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(MAP_START);
+ vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE);
+ } else {
+ pcxl_dma_start = 0;
+ vmalloc_start = SET_MAP_OFFSET(MAP_START);
+ }
+#else
+ vmalloc_start = SET_MAP_OFFSET(MAP_START);
+#endif
+
+}
+
+int do_check_pgt_cache(int low, int high)
+{
+ return 0;
+}
+
+unsigned long *empty_zero_page;
+
+void show_mem(void)
+{
+ int i,free = 0,total = 0,reserved = 0;
+ int shared = 0, cached = 0;
+
+ printk(KERN_INFO "Mem-info:\n");
+ show_free_areas();
+ printk(KERN_INFO "Free swap: %6ldkB\n",
+ nr_swap_pages<<(PAGE_SHIFT-10));
+#ifndef CONFIG_DISCONTIGMEM
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ else if (!page_count(&mem_map[i]))
+ free++;
+ else
+ shared += page_count(&mem_map[i]) - 1;
+ }
+#else
+ for (i = 0; i < npmem_ranges; i++) {
+ int j;
+
+ for (j = node_start_pfn(i); j < node_end_pfn(i); j++) {
+ struct page *p;
+
+ p = node_mem_map(i) + j - node_start_pfn(i);
+
+ total++;
+ if (PageReserved(p))
+ reserved++;
+ else if (PageSwapCache(p))
+ cached++;
+ else if (!page_count(p))
+ free++;
+ else
+ shared += page_count(p) - 1;
+ }
+ }
+#endif
+ printk(KERN_INFO "%d pages of RAM\n", total);
+ printk(KERN_INFO "%d reserved pages\n", reserved);
+ printk(KERN_INFO "%d pages shared\n", shared);
+ printk(KERN_INFO "%d pages swap cached\n", cached);
+
+
+#ifdef CONFIG_DISCONTIGMEM
+ {
+ struct zonelist *zl;
+ int i, j, k;
+
+ for (i = 0; i < npmem_ranges; i++) {
+ for (j = 0; j < MAX_NR_ZONES; j++) {
+ zl = NODE_DATA(i)->node_zonelists + j;
+
+ printk("Zone list for zone %d on node %d: ", j, i);
+ for (k = 0; zl->zones[k] != NULL; k++)
+ printk("[%d/%s] ", zl->zones[k]->zone_pgdat->node_id, zl->zones[k]->name);
+ printk("\n");
+ }
+ }
+ }
+#endif
+}
+
+
+static void __init map_pages(unsigned long start_vaddr, unsigned long start_paddr, unsigned long size, pgprot_t pgprot)
+{
+ pgd_t *pg_dir;
+ pmd_t *pmd;
+ pte_t *pg_table;
+ unsigned long end_paddr;
+ unsigned long start_pmd;
+ unsigned long start_pte;
+ unsigned long tmp1;
+ unsigned long tmp2;
+ unsigned long address;
+ unsigned long ro_start;
+ unsigned long ro_end;
+ unsigned long fv_addr;
+ unsigned long gw_addr;
+ extern const unsigned long fault_vector_20;
+ extern void * const linux_gateway_page;
+
+ ro_start = __pa((unsigned long)&_text);
+ ro_end = __pa((unsigned long)&data_start);
+ fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
+ gw_addr = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK;
+
+ end_paddr = start_paddr + size;
+
+ pg_dir = pgd_offset_k(start_vaddr);
+
+#if PTRS_PER_PMD == 1
+ start_pmd = 0;
+#else
+ start_pmd = ((start_vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
+#endif
+ start_pte = ((start_vaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+
+ address = start_paddr;
+ while (address < end_paddr) {
+#if PTRS_PER_PMD == 1
+ pmd = (pmd_t *)__pa(pg_dir);
+#else
+ pmd = (pmd_t *)pgd_address(*pg_dir);
+
+ /*
+ * pmd is physical at this point
+ */
+
+ if (!pmd) {
+ pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE << PMD_ORDER);
+ pmd = (pmd_t *) __pa(pmd);
+ }
+
+ pgd_populate(NULL, pg_dir, __va(pmd));
+#endif
+ pg_dir++;
+
+ /* now change pmd to kernel virtual addresses */
+
+ pmd = (pmd_t *)__va(pmd) + start_pmd;
+ for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++,pmd++) {
+
+ /*
+ * pg_table is physical at this point
+ */
+
+ pg_table = (pte_t *)pmd_address(*pmd);
+ if (!pg_table) {
+ pg_table = (pte_t *)
+ alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE);
+ pg_table = (pte_t *) __pa(pg_table);
+ }
+
+ pmd_populate_kernel(NULL, pmd, __va(pg_table));
+
+ /* now change pg_table to kernel virtual addresses */
+
+ pg_table = (pte_t *) __va(pg_table) + start_pte;
+ for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
+ pte_t pte;
+
+ /*
+ * Map the fault vector writable so we can
+ * write the HPMC checksum.
+ */
+ if (address >= ro_start && address < ro_end
+ && address != fv_addr
+ && address != gw_addr)
+ pte = __mk_pte(address, PAGE_KERNEL_RO);
+ else
+ pte = __mk_pte(address, pgprot);
+
+ if (address >= end_paddr)
+ pte_val(pte) = 0;
+
+ set_pte(pg_table, pte);
+
+ address += PAGE_SIZE;
+ }
+ start_pte = 0;
+
+ if (address >= end_paddr)
+ break;
+ }
+ start_pmd = 0;
+ }
+}
+
+/*
+ * pagetable_init() sets up the page tables
+ *
+ * Note that gateway_init() places the Linux gateway page at page 0.
+ * Since gateway pages cannot be dereferenced this has the desirable
+ * side effect of trapping those pesky NULL-reference errors in the
+ * kernel.
+ */
+static void __init pagetable_init(void)
+{
+ int range;
+
+ /* Map each physical memory range to its kernel vaddr */
+
+ for (range = 0; range < npmem_ranges; range++) {
+ unsigned long start_paddr;
+ unsigned long end_paddr;
+ unsigned long size;
+
+ start_paddr = pmem_ranges[range].start_pfn << PAGE_SHIFT;
+ end_paddr = start_paddr + (pmem_ranges[range].pages << PAGE_SHIFT);
+ size = pmem_ranges[range].pages << PAGE_SHIFT;
+
+ map_pages((unsigned long)__va(start_paddr), start_paddr,
+ size, PAGE_KERNEL);
+ }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_end && initrd_end > mem_limit) {
+ printk("initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end);
+ map_pages(initrd_start, __pa(initrd_start),
+ initrd_end - initrd_start, PAGE_KERNEL);
+ }
+#endif
+
+ empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
+ memset(empty_zero_page, 0, PAGE_SIZE);
+}
+
+static void __init gateway_init(void)
+{
+ unsigned long linux_gateway_page_addr;
+ /* FIXME: This is 'const' in order to trick the compiler
+ into not treating it as DP-relative data. */
+ extern void * const linux_gateway_page;
+
+ linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK;
+
+ /*
+ * Setup Linux Gateway page.
+ *
+ * The Linux gateway page will reside in kernel space (on virtual
+ * page 0), so it doesn't need to be aliased into user space.
+ */
+
+ map_pages(linux_gateway_page_addr, __pa(&linux_gateway_page),
+ PAGE_SIZE, PAGE_GATEWAY);
+}
+
+#ifdef CONFIG_HPUX
+void
+map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm)
+{
+ pgd_t *pg_dir;
+ pmd_t *pmd;
+ pte_t *pg_table;
+ unsigned long start_pmd;
+ unsigned long start_pte;
+ unsigned long address;
+ unsigned long hpux_gw_page_addr;
+ /* FIXME: This is 'const' in order to trick the compiler
+ into not treating it as DP-relative data. */
+ extern void * const hpux_gateway_page;
+
+ hpux_gw_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK;
+
+ /*
+ * Setup HP-UX Gateway page.
+ *
+ * The HP-UX gateway page resides in the user address space,
+ * so it needs to be aliased into each process.
+ */
+
+ pg_dir = pgd_offset(mm,hpux_gw_page_addr);
+
+#if PTRS_PER_PMD == 1
+ start_pmd = 0;
+#else
+ start_pmd = ((hpux_gw_page_addr >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
+#endif
+ start_pte = ((hpux_gw_page_addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+
+ address = __pa(&hpux_gateway_page);
+#if PTRS_PER_PMD == 1
+ pmd = (pmd_t *)__pa(pg_dir);
+#else
+ pmd = (pmd_t *) pgd_address(*pg_dir);
+
+ /*
+ * pmd is physical at this point
+ */
+
+ if (!pmd) {
+ pmd = (pmd_t *) get_zeroed_page(GFP_KERNEL);
+ pmd = (pmd_t *) __pa(pmd);
+ }
+
+ __pgd_val_set(*pg_dir, PxD_FLAG_PRESENT | PxD_FLAG_VALID | (unsigned long) pmd);
+#endif
+ /* now change pmd to kernel virtual addresses */
+
+ pmd = (pmd_t *)__va(pmd) + start_pmd;
+
+ /*
+ * pg_table is physical at this point
+ */
+
+ pg_table = (pte_t *) pmd_address(*pmd);
+ if (!pg_table)
+ pg_table = (pte_t *) __pa(get_zeroed_page(GFP_KERNEL));
+
+ __pmd_val_set(*pmd, PxD_FLAG_PRESENT | PxD_FLAG_VALID | (unsigned long) pg_table);
+
+ /* now change pg_table to kernel virtual addresses */
+
+ pg_table = (pte_t *) __va(pg_table) + start_pte;
+ set_pte(pg_table, __mk_pte(address, PAGE_GATEWAY));
+}
+EXPORT_SYMBOL(map_hpux_gateway_page);
+#endif
+
+extern void flush_tlb_all_local(void);
+
+void __init paging_init(void)
+{
+ int i;
+
+ setup_bootmem();
+ pagetable_init();
+ gateway_init();
+ flush_cache_all_local(); /* start with known state */
+ flush_tlb_all_local();
+
+ for (i = 0; i < npmem_ranges; i++) {
+ unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0 };
+
+ /* We have an IOMMU, so all memory can go into a single
+ ZONE_DMA zone. */
+ zones_size[ZONE_DMA] = pmem_ranges[i].pages;
+
+#ifdef CONFIG_DISCONTIGMEM
+ /* Need to initialize the pfnnid_map before we can initialize
+ the zone */
+ {
+ int j;
+ for (j = (pmem_ranges[i].start_pfn >> PFNNID_SHIFT);
+ j <= ((pmem_ranges[i].start_pfn + pmem_ranges[i].pages) >> PFNNID_SHIFT);
+ j++) {
+ pfnnid_map[j] = i;
+ }
+ }
+#endif
+
+ free_area_init_node(i, NODE_DATA(i), zones_size,
+ pmem_ranges[i].start_pfn, NULL);
+ }
+}
+
+#ifdef CONFIG_PA20
+
+/*
+ * Currently, all PA20 chips have 18 bit protection id's, which is the
+ * limiting factor (space ids are 32 bits).
+ */
+
+#define NR_SPACE_IDS 262144
+
+#else
+
+/*
+ * Currently we have a one-to-one relationship between space id's and
+ * protection id's. Older parisc chips (PCXS, PCXT, PCXL, PCXL2) only
+ * support 15 bit protection id's, so that is the limiting factor.
+ * PCXT' has 18 bit protection id's, but only 16 bit spaceids, so it's
+ * probably not worth the effort for a special case here.
+ */
+
+#define NR_SPACE_IDS 32768
+
+#endif /* !CONFIG_PA20 */
+
+#define RECYCLE_THRESHOLD (NR_SPACE_IDS / 2)
+#define SID_ARRAY_SIZE (NR_SPACE_IDS / (8 * sizeof(long)))
+
+static unsigned long space_id[SID_ARRAY_SIZE] = { 1 }; /* disallow space 0 */
+static unsigned long dirty_space_id[SID_ARRAY_SIZE];
+static unsigned long space_id_index;
+static unsigned long free_space_ids = NR_SPACE_IDS - 1;
+static unsigned long dirty_space_ids = 0;
+
+static DEFINE_SPINLOCK(sid_lock);
+
+unsigned long alloc_sid(void)
+{
+ unsigned long index;
+
+ spin_lock(&sid_lock);
+
+ if (free_space_ids == 0) {
+ if (dirty_space_ids != 0) {
+ spin_unlock(&sid_lock);
+ flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */
+ spin_lock(&sid_lock);
+ }
+ if (free_space_ids == 0)
+ BUG();
+ }
+
+ free_space_ids--;
+
+ index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index);
+ space_id[index >> SHIFT_PER_LONG] |= (1L << (index & (BITS_PER_LONG - 1)));
+ space_id_index = index;
+
+ spin_unlock(&sid_lock);
+
+ return index << SPACEID_SHIFT;
+}
+
+void free_sid(unsigned long spaceid)
+{
+ unsigned long index = spaceid >> SPACEID_SHIFT;
+ unsigned long *dirty_space_offset;
+
+ dirty_space_offset = dirty_space_id + (index >> SHIFT_PER_LONG);
+ index &= (BITS_PER_LONG - 1);
+
+ spin_lock(&sid_lock);
+
+ if (*dirty_space_offset & (1L << index))
+ BUG(); /* attempt to free space id twice */
+
+ *dirty_space_offset |= (1L << index);
+ dirty_space_ids++;
+
+ spin_unlock(&sid_lock);
+}
+
+
+#ifdef CONFIG_SMP
+static void get_dirty_sids(unsigned long *ndirtyptr,unsigned long *dirty_array)
+{
+ int i;
+
+ /* NOTE: sid_lock must be held upon entry */
+
+ *ndirtyptr = dirty_space_ids;
+ if (dirty_space_ids != 0) {
+ for (i = 0; i < SID_ARRAY_SIZE; i++) {
+ dirty_array[i] = dirty_space_id[i];
+ dirty_space_id[i] = 0;
+ }
+ dirty_space_ids = 0;
+ }
+
+ return;
+}
+
+static void recycle_sids(unsigned long ndirty,unsigned long *dirty_array)
+{
+ int i;
+
+ /* NOTE: sid_lock must be held upon entry */
+
+ if (ndirty != 0) {
+ for (i = 0; i < SID_ARRAY_SIZE; i++) {
+ space_id[i] ^= dirty_array[i];
+ }
+
+ free_space_ids += ndirty;
+ space_id_index = 0;
+ }
+}
+
+#else /* CONFIG_SMP */
+
+static void recycle_sids(void)
+{
+ int i;
+
+ /* NOTE: sid_lock must be held upon entry */
+
+ if (dirty_space_ids != 0) {
+ for (i = 0; i < SID_ARRAY_SIZE; i++) {
+ space_id[i] ^= dirty_space_id[i];
+ dirty_space_id[i] = 0;
+ }
+
+ free_space_ids += dirty_space_ids;
+ dirty_space_ids = 0;
+ space_id_index = 0;
+ }
+}
+#endif
+
+/*
+ * flush_tlb_all() calls recycle_sids(), since whenever the entire tlb is
+ * purged, we can safely reuse the space ids that were released but
+ * not flushed from the tlb.
+ */
+
+#ifdef CONFIG_SMP
+
+static unsigned long recycle_ndirty;
+static unsigned long recycle_dirty_array[SID_ARRAY_SIZE];
+static unsigned int recycle_inuse = 0;
+
+void flush_tlb_all(void)
+{
+ int do_recycle;
+
+ do_recycle = 0;
+ spin_lock(&sid_lock);
+ if (dirty_space_ids > RECYCLE_THRESHOLD) {
+ if (recycle_inuse) {
+ BUG(); /* FIXME: Use a semaphore/wait queue here */
+ }
+ get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
+ recycle_inuse++;
+ do_recycle++;
+ }
+ spin_unlock(&sid_lock);
+ on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
+ if (do_recycle) {
+ spin_lock(&sid_lock);
+ recycle_sids(recycle_ndirty,recycle_dirty_array);
+ recycle_inuse = 0;
+ spin_unlock(&sid_lock);
+ }
+}
+#else
+void flush_tlb_all(void)
+{
+ spin_lock(&sid_lock);
+ flush_tlb_all_local();
+ recycle_sids();
+ spin_unlock(&sid_lock);
+}
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+#if 0
+ if (start < end)
+ printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(start));
+ set_page_count(virt_to_page(start), 1);
+ free_page(start);
+ num_physpages++;
+ totalram_pages++;
+ }
+#endif
+}
+#endif
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
new file mode 100644
index 000000000000..f2df502cdae3
--- /dev/null
+++ b/arch/parisc/mm/ioremap.c
@@ -0,0 +1,207 @@
+/*
+ * arch/parisc/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ * This is needed for high PCI addresses that aren't mapped in the
+ * 640k-1MB IO memory area on PC's
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ * (C) Copyright 2001 Helge Deller <deller@gmx.de>
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+ unsigned long phys_addr, unsigned long flags)
+{
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ if (address >= end)
+ BUG();
+ do {
+ if (!pte_none(*pte)) {
+ printk(KERN_ERR "remap_area_pte: page already exists\n");
+ BUG();
+ }
+ set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW |
+ _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
+ address += PAGE_SIZE;
+ phys_addr += PAGE_SIZE;
+ pte++;
+ } while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+ unsigned long phys_addr, unsigned long flags)
+{
+ unsigned long end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ phys_addr -= address;
+ if (address >= end)
+ BUG();
+ do {
+ pte_t * pte = pte_alloc_kernel(NULL, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+}
+
+#if (USE_HPPA_IOREMAP)
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+ unsigned long size, unsigned long flags)
+{
+ int error;
+ pgd_t * dir;
+ unsigned long end = address + size;
+
+ phys_addr -= address;
+ dir = pgd_offset(&init_mm, address);
+ flush_cache_all();
+ if (address >= end)
+ BUG();
+ spin_lock(&init_mm.page_table_lock);
+ do {
+ pmd_t *pmd;
+ pmd = pmd_alloc(dir, address);
+ error = -ENOMEM;
+ if (!pmd)
+ break;
+ if (remap_area_pmd(pmd, address, end - address,
+ phys_addr + address, flags))
+ break;
+ error = 0;
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ spin_unlock(&init_mm.page_table_lock);
+ flush_tlb_all();
+ return error;
+}
+#endif /* USE_HPPA_IOREMAP */
+
+#ifdef CONFIG_DEBUG_IOREMAP
+static unsigned long last = 0;
+
+void gsc_bad_addr(unsigned long addr)
+{
+ if (time_after(jiffies, last + HZ*10)) {
+ printk("gsc_foo() called with bad address 0x%lx\n", addr);
+ dump_stack();
+ last = jiffies;
+ }
+}
+EXPORT_SYMBOL(gsc_bad_addr);
+
+void __raw_bad_addr(const volatile void __iomem *addr)
+{
+ if (time_after(jiffies, last + HZ*10)) {
+ printk("__raw_foo() called with bad address 0x%p\n", addr);
+ dump_stack();
+ last = jiffies;
+ }
+}
+EXPORT_SYMBOL(__raw_bad_addr);
+#endif
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+#if !(USE_HPPA_IOREMAP)
+
+ unsigned long end = phys_addr + size - 1;
+ /* Support EISA addresses */
+ if ((phys_addr >= 0x00080000 && end < 0x000fffff)
+ || (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
+ phys_addr |= 0xfc000000;
+ }
+
+#ifdef CONFIG_DEBUG_IOREMAP
+ return (void __iomem *)(phys_addr - (0x1UL << NYBBLE_SHIFT));
+#else
+ return (void __iomem *)phys_addr;
+#endif
+
+#else
+ void * addr;
+ struct vm_struct * area;
+ unsigned long offset, last_addr;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Don't allow anybody to remap normal RAM that we're using..
+ */
+ if (phys_addr < virt_to_phys(high_memory)) {
+ char *t_addr, *t_end;
+ struct page *page;
+
+ t_addr = __va(phys_addr);
+ t_end = t_addr + (size - 1);
+
+ for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
+ if(!PageReserved(page))
+ return NULL;
+ }
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ addr = area->addr;
+ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+ return (void __iomem *) (offset + (char *)addr);
+#endif
+}
+
+void iounmap(void __iomem *addr)
+{
+#if !(USE_HPPA_IOREMAP)
+ return;
+#else
+ if (addr > high_memory)
+ return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
+#endif
+}
diff --git a/arch/parisc/mm/kmap.c b/arch/parisc/mm/kmap.c
new file mode 100644
index 000000000000..1b1acd5e2f6e
--- /dev/null
+++ b/arch/parisc/mm/kmap.c
@@ -0,0 +1,166 @@
+/*
+ * kmap/page table map and unmap support routines
+ *
+ * Copyright 1999,2000 Hewlett-Packard Company
+ * Copyright 2000 John Marvin <jsm at hp.com>
+ * Copyright 2000 Grant Grundler <grundler at parisc-linux.org>
+ * Copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+** Stolen mostly from arch/parisc/kernel/pci-dma.c
+*/
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#include <asm/io.h>
+#include <asm/page.h> /* get_order */
+
+#undef flush_cache_all
+#define flush_cache_all flush_all_caches
+
+typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg);
+
+#if 0
+/* XXX This routine could be used with iterate_page() to replace
+ * unmap_uncached_page() and save a little code space but I didn't
+ * do that since I'm not certain whether this is the right path. -PB
+ */
+static void unmap_cached_pte(pte_t * pte, unsigned long addr, unsigned long arg)
+{
+ pte_t page = *pte;
+ pte_clear(&init_mm, addr, pte);
+ if (!pte_none(page)) {
+ if (pte_present(page)) {
+ unsigned long map_nr = pte_pagenr(page);
+ if (map_nr < max_mapnr)
+ __free_page(mem_map + map_nr);
+ } else {
+ printk(KERN_CRIT
+ "Whee.. Swapped out page in kernel page table\n");
+ }
+ }
+}
+#endif
+
+/* These two routines should probably check a few things... */
+static void set_uncached(pte_t * pte, unsigned long arg)
+{
+ pte_val(*pte) |= _PAGE_NO_CACHE;
+}
+
+static void set_cached(pte_t * pte, unsigned long arg)
+{
+ pte_val(*pte) &= ~_PAGE_NO_CACHE;
+}
+
+static inline void iterate_pte(pmd_t * pmd, unsigned long address,
+ unsigned long size, pte_iterator_t op,
+ unsigned long arg)
+{
+ pte_t *pte;
+ unsigned long end;
+
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = pte_offset(pmd, address);
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ op(pte, arg);
+ address += PAGE_SIZE;
+ pte++;
+ } while (address < end);
+}
+
+static inline void iterate_pmd(pgd_t * dir, unsigned long address,
+ unsigned long size, pte_iterator_t op,
+ unsigned long arg)
+{
+ pmd_t *pmd;
+ unsigned long end;
+
+ if (pgd_none(*dir))
+ return;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return;
+ }
+ pmd = pmd_offset(dir, address);
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ iterate_pte(pmd, address, end - address, op, arg);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address < end);
+}
+
+static void iterate_pages(unsigned long address, unsigned long size,
+ pte_iterator_t op, unsigned long arg)
+{
+ pgd_t *dir;
+ unsigned long end = address + size;
+
+ dir = pgd_offset_k(address);
+ flush_cache_all();
+ do {
+ iterate_pmd(dir, address, end - address, op, arg);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ flush_tlb_all();
+}
+
+void
+kernel_set_cachemode(unsigned long vaddr, unsigned long size, int what)
+{
+ switch (what) {
+ case IOMAP_FULL_CACHING:
+ iterate_pages(vaddr, size, set_cached, 0);
+ flush_tlb_range(NULL, vaddr, size);
+ break;
+ case IOMAP_NOCACHE_SER:
+ iterate_pages(vaddr, size, set_uncached, 0);
+ flush_tlb_range(NULL, vaddr, size);
+ break;
+ default:
+ printk(KERN_CRIT
+ "kernel_set_cachemode mode %d not understood\n",
+ what);
+ break;
+ }
+}
diff --git a/arch/parisc/nm b/arch/parisc/nm
new file mode 100644
index 000000000000..c788308de33f
--- /dev/null
+++ b/arch/parisc/nm
@@ -0,0 +1,6 @@
+#!/bin/sh
+##
+# Hack to have an nm which removes the local symbols. We also rely
+# on this nm being hidden out of the ordinarily executable path
+##
+${CROSS_COMPILE}nm $* | grep -v '.LC*[0-9]*$'
diff --git a/arch/parisc/oprofile/Kconfig b/arch/parisc/oprofile/Kconfig
new file mode 100644
index 000000000000..5ade19801b97
--- /dev/null
+++ b/arch/parisc/oprofile/Kconfig
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+ depends on EXPERIMENTAL
+
+config PROFILING
+ bool "Profiling support (EXPERIMENTAL)"
+ help
+ Say Y here to enable the extended profiling support mechanisms used
+ by profilers such as OProfile.
+
+
+config OPROFILE
+ tristate "OProfile system profiling (EXPERIMENTAL)"
+ depends on PROFILING
+ help
+ OProfile is a profiling system capable of profiling the
+ whole system, include the kernel, kernel modules, libraries,
+ and applications.
+
+ If unsure, say N.
+
+endmenu
+
diff --git a/arch/parisc/oprofile/Makefile b/arch/parisc/oprofile/Makefile
new file mode 100644
index 000000000000..e9feca1ca28b
--- /dev/null
+++ b/arch/parisc/oprofile/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+ oprof.o cpu_buffer.o buffer_sync.o \
+ event_buffer.o oprofile_files.o \
+ oprofilefs.o oprofile_stats.o \
+ timer_int.o )
+
+oprofile-y := $(DRIVER_OBJS) init.o
diff --git a/arch/parisc/oprofile/init.c b/arch/parisc/oprofile/init.c
new file mode 100644
index 000000000000..a5b898c4d0b0
--- /dev/null
+++ b/arch/parisc/oprofile/init.c
@@ -0,0 +1,23 @@
+/**
+ * @file init.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/oprofile.h>
+
+int __init oprofile_arch_init(struct oprofile_operations * ops)
+{
+ return -ENODEV;
+}
+
+
+void oprofile_arch_exit()
+{
+}