aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/parisc
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
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 @@
1#
2# For a description of the syntax of this configuration file,
3# see Documentation/kbuild/kconfig-language.txt.
4#
5
6mainmenu "Linux/PA-RISC Kernel Configuration"
7
8config PARISC
9 def_bool y
10 help
11 The PA-RISC microprocessor is designed by Hewlett-Packard and used
12 in many of their workstations & servers (HP9000 700 and 800 series,
13 and later HP3000 series). The PA-RISC Linux project home page is
14 at <http://www.parisc-linux.org/>.
15
16config MMU
17 def_bool y
18
19config STACK_GROWSUP
20 def_bool y
21
22config UID16
23 bool
24
25config RWSEM_GENERIC_SPINLOCK
26 def_bool y
27
28config RWSEM_XCHGADD_ALGORITHM
29 bool
30
31config GENERIC_CALIBRATE_DELAY
32 bool
33 default y
34
35config GENERIC_ISA_DMA
36 bool
37
38config GENERIC_HARDIRQS
39 def_bool y
40
41config GENERIC_IRQ_PROBE
42 def_bool y
43
44# unless you want to implement ACPI on PA-RISC ... ;-)
45config PM
46 bool
47
48source "init/Kconfig"
49
50
51menu "Processor type and features"
52
53choice
54 prompt "Processor type"
55 default PA7000
56
57config PA7000
58 bool "PA7000/PA7100"
59 ---help---
60 This is the processor type of your CPU. This information is
61 used for optimizing purposes. In order to compile a kernel
62 that can run on all 32-bit PA CPUs (albeit not optimally fast),
63 you can specify "PA7000" here.
64
65 Specifying "PA8000" here will allow you to select a 64-bit kernel
66 which is required on some machines.
67
68config PA7100LC
69 bool "PA7100LC"
70 help
71 Select this option for the PCX-L processor, as used in the
72 712, 715/64, 715/80, 715/100, 715/100XC, 725/100, 743, 748,
73 D200, D210, D300, D310 and E-class
74
75config PA7200
76 bool "PA7200"
77 help
78 Select this option for the PCX-T' processor, as used in the
79 C100, C110, J100, J110, J210XC, D250, D260, D350, D360,
80 K100, K200, K210, K220, K400, K410 and K420
81
82config PA7300LC
83 bool "PA7300LC"
84 help
85 Select this option for the PCX-L2 processor, as used in the
86 744, A180, B132L, B160L, B180L, C132L, C160L, C180L,
87 D220, D230, D320 and D330.
88
89config PA8X00
90 bool "PA8000 and up"
91 help
92 Select this option for PCX-U to PCX-W2 processors.
93
94endchoice
95
96# Define implied options from the CPU selection here
97
98config PA20
99 def_bool y
100 depends on PA8X00
101
102config PA11
103 def_bool y
104 depends on PA7000 || PA7100LC || PA7200 || PA7300LC
105
106config PREFETCH
107 def_bool y
108 depends on PA8X00
109
110config 64BIT
111 bool "64-bit kernel"
112 depends on PA8X00
113 help
114 Enable this if you want to support 64bit kernel on PA-RISC platform.
115
116 At the moment, only people willing to use more than 2GB of RAM,
117 or having a 64bit-only capable PA-RISC machine should say Y here.
118
119 Since there is no 64bit userland on PA-RISC, there is no point to
120 enable this option otherwise. The 64bit kernel is significantly bigger
121 and slower than the 32bit one.
122
123config SMP
124 bool "Symmetric multi-processing support"
125 ---help---
126 This enables support for systems with more than one CPU. If you have
127 a system with only one CPU, like most personal computers, say N. If
128 you have a system with more than one CPU, say Y.
129
130 If you say N here, the kernel will run on single and multiprocessor
131 machines, but will use only one CPU of a multiprocessor machine. If
132 you say Y here, the kernel will run on many, but not all,
133 singleprocessor machines. On a singleprocessor machine, the kernel
134 will run faster if you say N here.
135
136 See also the <file:Documentation/smp.txt>,
137 <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available
138 at <http://www.tldp.org/docs.html#howto>.
139
140 If you don't know what to do here, say N.
141
142config HOTPLUG_CPU
143 bool
144 default y if SMP
145 select HOTPLUG
146
147config DISCONTIGMEM
148 bool "Discontiguous memory support (EXPERIMENTAL)"
149 depends on EXPERIMENTAL
150 help
151 Say Y to support efficient handling of discontiguous physical memory,
152 for architectures which are either NUMA (Non-Uniform Memory Access)
153 or have huge holes in the physical address space for other reasons.
154 See <file:Documentation/vm/numa> for more.
155
156config PREEMPT
157 bool
158# bool "Preemptible Kernel"
159 default n
160
161config COMPAT
162 def_bool y
163 depends on 64BIT
164
165config HPUX
166 bool "Support for HP-UX binaries"
167 depends on !64BIT
168
169config NR_CPUS
170 int "Maximum number of CPUs (2-32)"
171 range 2 32
172 depends on SMP
173 default "32"
174
175endmenu
176
177
178source "drivers/parisc/Kconfig"
179
180
181menu "Executable file formats"
182
183source "fs/Kconfig.binfmt"
184
185endmenu
186
187source "drivers/Kconfig"
188
189source "fs/Kconfig"
190
191source "arch/parisc/oprofile/Kconfig"
192
193source "arch/parisc/Kconfig.debug"
194
195source "security/Kconfig"
196
197source "crypto/Kconfig"
198
199source "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 @@
1menu "Kernel hacking"
2
3source "lib/Kconfig.debug"
4
5config DEBUG_RWLOCK
6 bool "Read-write spinlock debugging"
7 depends on DEBUG_KERNEL && SMP
8 help
9 If you say Y here then read-write lock processing will count how many
10 times it has tried to get the lock and issue an error message after
11 too many attempts. If you suspect a rwlock problem or a kernel
12 hacker asks for this option then say Y. Otherwise say N.
13
14endmenu
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 @@
1#
2# parisc/Makefile
3#
4# This file is included by the global makefile so that you can add your own
5# architecture-specific flags and dependencies. Remember to do have actions
6# for "archclean" and "archdep" for cleaning up and making dependencies for
7# this architecture
8#
9# This file is subject to the terms and conditions of the GNU General Public
10# License. See the file "COPYING" in the main directory of this archive
11# for more details.
12#
13# Copyright (C) 1994 by Linus Torvalds
14# Portions Copyright (C) 1999 The Puffin Group
15#
16# Modified for PA-RISC Linux by Paul Lahaie, Alex deVries,
17# Mike Shaver, Helge Deller and Martin K. Petersen
18#
19NM = sh $(srctree)/arch/parisc/nm
20CHECKFLAGS += -D__hppa__=1
21
22ifdef CONFIG_64BIT
23CROSS_COMPILE := hppa64-linux-
24UTS_MACHINE := parisc64
25CHECKFLAGS += -D__LP64__=1 -m64
26else
27MACHINE := $(subst 64,,$(shell uname -m))
28ifneq ($(MACHINE),parisc)
29CROSS_COMPILE := hppa-linux-
30endif
31endif
32
33FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align
34
35OBJCOPY_FLAGS =-O binary -R .note -R .comment -S
36
37cflags-y := -pipe
38
39# These flags should be implied by an hppa-linux configuration, but they
40# are not in gcc 3.2.
41cflags-y += -mno-space-regs -mfast-indirect-calls
42
43# Currently we save and restore fpregs on all kernel entry/interruption paths.
44# If that gets optimized, we might need to disable the use of fpregs in the
45# kernel.
46#cflags-y += -mdisable-fpregs
47
48# Without this, "ld -r" results in .text sections that are too big
49# (> 0x40000) for branches to reach stubs.
50cflags-y += -ffunction-sections
51
52# select which processor to optimise for
53cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100
54cflags-$(CONFIG_PA7200) += -march=1.1 -mschedule=7200
55cflags-$(CONFIG_PA7100LC) += -march=1.1 -mschedule=7100LC
56cflags-$(CONFIG_PA7300LC) += -march=1.1 -mschedule=7300
57cflags-$(CONFIG_PA8X00) += -march=2.0 -mschedule=8000
58
59head-y := arch/parisc/kernel/head.o
60
61CFLAGS += $(cflags-y)
62
63kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o
64kernel-$(CONFIG_HPUX) += hpux/
65
66core-y += $(addprefix arch/parisc/, $(kernel-y))
67libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`
68
69drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/
70
71PALO := $(shell if which palo; then : ; \
72 elif [ -x /sbin/palo ]; then echo /sbin/palo; \
73 fi)
74
75palo: vmlinux
76 @if [ -x $PALO ]; then \
77 echo 'ERROR: Please install palo first (apt-get install palo)';\
78 echo 'or build it from source and install it somewhere in your $$PATH';\
79 false; \
80 fi
81 @if [ ! -f ./palo.conf ]; then \
82 cp arch/parisc/defpalo.conf palo.conf; \
83 echo 'A generic palo config file (./palo.conf) has been created for you.'; \
84 echo 'You should check it and re-run "make palo".'; \
85 echo 'WARNING: the "lifimage" file is now placed in this directory by default!'; \
86 false; \
87 fi
88 $(PALO) -f ./palo.conf
89
90oldpalo: vmlinux
91 export TOPDIR=`pwd`; \
92 unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage
93
94# Shorthands for known targets not supported by parisc, use palo as default
95Image zImage bzImage: palo
96
97kernel_install: vmlinux
98 sh $(src)/arch/parisc/install.sh \
99 $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
100
101install: kernel_install modules_install
102
103prepare: include/asm-parisc/offsets.h
104
105arch/parisc/kernel/asm-offsets.s: include/asm include/linux/version.h \
106 include/config/MARKER
107
108include/asm-parisc/offsets.h: arch/parisc/kernel/asm-offsets.s
109 $(call filechk,gen-asm-offsets)
110
111CLEAN_FILES += lifimage include/asm-parisc/offsets.h
112MRPROPER_FILES += palo.conf
113
114define archhelp
115 @echo '* vmlinux - Uncompressed kernel image (./vmlinux)'
116 @echo ' palo - Bootable image (./lifimage)'
117 @echo ' install - Install kernel using'
118 @echo ' (your) ~/bin/installkernel or'
119 @echo ' (distribution) /sbin/installkernel or'
120 @echo ' copy to $$(INSTALL_PATH)'
121endef
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 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-pa5
4# Wed Jan 5 13:20:32 2005
5#
6CONFIG_PARISC=y
7CONFIG_MMU=y
8CONFIG_STACK_GROWSUP=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15# CONFIG_CLEAN_COMPILE is not set
16CONFIG_BROKEN=y
17CONFIG_BROKEN_ON_SMP=y
18
19#
20# General setup
21#
22CONFIG_LOCALVERSION=""
23CONFIG_SWAP=y
24CONFIG_SYSVIPC=y
25CONFIG_POSIX_MQUEUE=y
26# CONFIG_BSD_PROCESS_ACCT is not set
27CONFIG_SYSCTL=y
28# CONFIG_AUDIT is not set
29CONFIG_LOG_BUF_SHIFT=16
30CONFIG_HOTPLUG=y
31CONFIG_KOBJECT_UEVENT=y
32CONFIG_IKCONFIG=y
33CONFIG_IKCONFIG_PROC=y
34# CONFIG_EMBEDDED is not set
35CONFIG_KALLSYMS=y
36CONFIG_KALLSYMS_ALL=y
37# CONFIG_KALLSYMS_EXTRA_PASS is not set
38CONFIG_FUTEX=y
39CONFIG_EPOLL=y
40# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
41CONFIG_SHMEM=y
42CONFIG_CC_ALIGN_FUNCTIONS=0
43CONFIG_CC_ALIGN_LABELS=0
44CONFIG_CC_ALIGN_LOOPS=0
45CONFIG_CC_ALIGN_JUMPS=0
46# CONFIG_TINY_SHMEM is not set
47
48#
49# Loadable module support
50#
51CONFIG_MODULES=y
52CONFIG_MODULE_UNLOAD=y
53CONFIG_MODULE_FORCE_UNLOAD=y
54CONFIG_OBSOLETE_MODPARM=y
55# CONFIG_MODVERSIONS is not set
56# CONFIG_MODULE_SRCVERSION_ALL is not set
57CONFIG_KMOD=y
58
59#
60# Processor type and features
61#
62# CONFIG_PA7000 is not set
63CONFIG_PA7100LC=y
64# CONFIG_PA7200 is not set
65# CONFIG_PA7300LC is not set
66# CONFIG_PA8X00 is not set
67CONFIG_PA11=y
68# CONFIG_64BIT is not set
69# CONFIG_SMP is not set
70# CONFIG_DISCONTIGMEM is not set
71# CONFIG_PREEMPT is not set
72# CONFIG_HPUX is not set
73
74#
75# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
76#
77CONFIG_GSC=y
78# CONFIG_HPPB is not set
79# CONFIG_IOMMU_CCIO is not set
80CONFIG_GSC_LASI=y
81# CONFIG_GSC_WAX is not set
82# CONFIG_EISA is not set
83# CONFIG_PCI is not set
84CONFIG_CHASSIS_LCD_LED=y
85# CONFIG_PDC_CHASSIS is not set
86
87#
88# PCCARD (PCMCIA/CardBus) support
89#
90# CONFIG_PCCARD is not set
91
92#
93# PC-card bridges
94#
95
96#
97# PCI Hotplug Support
98#
99
100#
101# Executable file formats
102#
103CONFIG_BINFMT_ELF=y
104CONFIG_BINFMT_MISC=m
105
106#
107# Device Drivers
108#
109
110#
111# Generic Driver Options
112#
113# CONFIG_STANDALONE is not set
114# CONFIG_PREVENT_FIRMWARE_BUILD is not set
115CONFIG_FW_LOADER=y
116# CONFIG_DEBUG_DRIVER is not set
117
118#
119# Memory Technology Devices (MTD)
120#
121# CONFIG_MTD is not set
122
123#
124# Parallel port support
125#
126CONFIG_PARPORT=y
127CONFIG_PARPORT_PC=m
128CONFIG_PARPORT_PC_CML1=m
129# CONFIG_PARPORT_PC_FIFO is not set
130# CONFIG_PARPORT_PC_SUPERIO is not set
131CONFIG_PARPORT_GSC=y
132# CONFIG_PARPORT_OTHER is not set
133# CONFIG_PARPORT_1284 is not set
134
135#
136# Plug and Play support
137#
138
139#
140# Block devices
141#
142# CONFIG_BLK_DEV_FD is not set
143# CONFIG_PARIDE is not set
144CONFIG_BLK_DEV_LOOP=y
145CONFIG_BLK_DEV_CRYPTOLOOP=y
146# CONFIG_BLK_DEV_NBD is not set
147CONFIG_BLK_DEV_RAM=y
148CONFIG_BLK_DEV_RAM_COUNT=16
149CONFIG_BLK_DEV_RAM_SIZE=6144
150CONFIG_BLK_DEV_INITRD=y
151CONFIG_INITRAMFS_SOURCE=""
152# CONFIG_CDROM_PKTCDVD is not set
153
154#
155# IO Schedulers
156#
157CONFIG_IOSCHED_NOOP=y
158CONFIG_IOSCHED_AS=y
159CONFIG_IOSCHED_DEADLINE=y
160CONFIG_IOSCHED_CFQ=y
161
162#
163# ATA/ATAPI/MFM/RLL support
164#
165# CONFIG_IDE is not set
166
167#
168# SCSI device support
169#
170CONFIG_SCSI=y
171CONFIG_SCSI_PROC_FS=y
172
173#
174# SCSI support type (disk, tape, CD-ROM)
175#
176CONFIG_BLK_DEV_SD=y
177CONFIG_CHR_DEV_ST=y
178# CONFIG_CHR_DEV_OSST is not set
179CONFIG_BLK_DEV_SR=y
180# CONFIG_BLK_DEV_SR_VENDOR is not set
181CONFIG_CHR_DEV_SG=y
182
183#
184# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
185#
186# CONFIG_SCSI_MULTI_LUN is not set
187# CONFIG_SCSI_CONSTANTS is not set
188# CONFIG_SCSI_LOGGING is not set
189
190#
191# SCSI Transport Attributes
192#
193CONFIG_SCSI_SPI_ATTRS=y
194# CONFIG_SCSI_FC_ATTRS is not set
195
196#
197# SCSI low-level drivers
198#
199# CONFIG_SCSI_SATA is not set
200# CONFIG_SCSI_PPA is not set
201# CONFIG_SCSI_IMM is not set
202CONFIG_SCSI_LASI700=y
203CONFIG_53C700_MEM_MAPPED=y
204CONFIG_53C700_LE_ON_BE=y
205# CONFIG_SCSI_ZALON is not set
206CONFIG_SCSI_DEBUG=m
207
208#
209# Multi-device support (RAID and LVM)
210#
211CONFIG_MD=y
212CONFIG_BLK_DEV_MD=m
213CONFIG_MD_LINEAR=m
214CONFIG_MD_RAID0=m
215CONFIG_MD_RAID1=m
216# CONFIG_MD_RAID10 is not set
217# CONFIG_MD_RAID5 is not set
218# CONFIG_MD_RAID6 is not set
219# CONFIG_MD_MULTIPATH is not set
220# CONFIG_MD_FAULTY is not set
221# CONFIG_BLK_DEV_DM is not set
222
223#
224# Fusion MPT device support
225#
226
227#
228# IEEE 1394 (FireWire) support
229#
230# CONFIG_IEEE1394 is not set
231
232#
233# I2O device support
234#
235
236#
237# Networking support
238#
239CONFIG_NET=y
240
241#
242# Networking options
243#
244CONFIG_PACKET=y
245CONFIG_PACKET_MMAP=y
246CONFIG_NETLINK_DEV=y
247CONFIG_UNIX=y
248CONFIG_NET_KEY=m
249CONFIG_INET=y
250CONFIG_IP_MULTICAST=y
251# CONFIG_IP_ADVANCED_ROUTER is not set
252CONFIG_IP_PNP=y
253CONFIG_IP_PNP_DHCP=y
254CONFIG_IP_PNP_BOOTP=y
255# CONFIG_IP_PNP_RARP is not set
256# CONFIG_NET_IPIP is not set
257# CONFIG_NET_IPGRE is not set
258# CONFIG_IP_MROUTE is not set
259# CONFIG_ARPD is not set
260# CONFIG_SYN_COOKIES is not set
261CONFIG_INET_AH=m
262CONFIG_INET_ESP=m
263# CONFIG_INET_IPCOMP is not set
264CONFIG_INET_TUNNEL=m
265CONFIG_IP_TCPDIAG=y
266# CONFIG_IP_TCPDIAG_IPV6 is not set
267
268#
269# IP: Virtual Server Configuration
270#
271# CONFIG_IP_VS is not set
272# CONFIG_IPV6 is not set
273CONFIG_NETFILTER=y
274# CONFIG_NETFILTER_DEBUG is not set
275
276#
277# IP: Netfilter Configuration
278#
279CONFIG_IP_NF_CONNTRACK=m
280# CONFIG_IP_NF_CT_ACCT is not set
281CONFIG_IP_NF_CONNTRACK_MARK=y
282CONFIG_IP_NF_CT_PROTO_SCTP=m
283CONFIG_IP_NF_FTP=m
284CONFIG_IP_NF_IRC=m
285CONFIG_IP_NF_TFTP=m
286CONFIG_IP_NF_AMANDA=m
287CONFIG_IP_NF_QUEUE=m
288CONFIG_IP_NF_IPTABLES=m
289CONFIG_IP_NF_MATCH_LIMIT=m
290CONFIG_IP_NF_MATCH_IPRANGE=m
291CONFIG_IP_NF_MATCH_MAC=m
292CONFIG_IP_NF_MATCH_PKTTYPE=m
293CONFIG_IP_NF_MATCH_MARK=m
294CONFIG_IP_NF_MATCH_MULTIPORT=m
295CONFIG_IP_NF_MATCH_TOS=m
296CONFIG_IP_NF_MATCH_RECENT=m
297CONFIG_IP_NF_MATCH_ECN=m
298CONFIG_IP_NF_MATCH_DSCP=m
299CONFIG_IP_NF_MATCH_AH_ESP=m
300CONFIG_IP_NF_MATCH_LENGTH=m
301CONFIG_IP_NF_MATCH_TTL=m
302CONFIG_IP_NF_MATCH_TCPMSS=m
303CONFIG_IP_NF_MATCH_HELPER=m
304CONFIG_IP_NF_MATCH_STATE=m
305CONFIG_IP_NF_MATCH_CONNTRACK=m
306CONFIG_IP_NF_MATCH_OWNER=m
307# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
308# CONFIG_IP_NF_MATCH_REALM is not set
309CONFIG_IP_NF_MATCH_SCTP=m
310CONFIG_IP_NF_MATCH_COMMENT=m
311CONFIG_IP_NF_MATCH_CONNMARK=m
312CONFIG_IP_NF_MATCH_HASHLIMIT=m
313CONFIG_IP_NF_FILTER=m
314CONFIG_IP_NF_TARGET_REJECT=m
315CONFIG_IP_NF_TARGET_LOG=m
316CONFIG_IP_NF_TARGET_ULOG=m
317CONFIG_IP_NF_TARGET_TCPMSS=m
318CONFIG_IP_NF_NAT=m
319CONFIG_IP_NF_NAT_NEEDED=y
320CONFIG_IP_NF_TARGET_MASQUERADE=m
321CONFIG_IP_NF_TARGET_REDIRECT=m
322CONFIG_IP_NF_TARGET_NETMAP=m
323CONFIG_IP_NF_TARGET_SAME=m
324# CONFIG_IP_NF_NAT_LOCAL is not set
325CONFIG_IP_NF_NAT_SNMP_BASIC=m
326CONFIG_IP_NF_NAT_IRC=m
327CONFIG_IP_NF_NAT_FTP=m
328CONFIG_IP_NF_NAT_TFTP=m
329CONFIG_IP_NF_NAT_AMANDA=m
330CONFIG_IP_NF_MANGLE=m
331CONFIG_IP_NF_TARGET_TOS=m
332CONFIG_IP_NF_TARGET_ECN=m
333CONFIG_IP_NF_TARGET_DSCP=m
334CONFIG_IP_NF_TARGET_MARK=m
335CONFIG_IP_NF_TARGET_CLASSIFY=m
336CONFIG_IP_NF_TARGET_CONNMARK=m
337CONFIG_IP_NF_TARGET_CLUSTERIP=m
338CONFIG_IP_NF_RAW=m
339CONFIG_IP_NF_TARGET_NOTRACK=m
340CONFIG_IP_NF_ARPTABLES=m
341CONFIG_IP_NF_ARPFILTER=m
342CONFIG_IP_NF_ARP_MANGLE=m
343# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
344# CONFIG_IP_NF_COMPAT_IPFWADM is not set
345CONFIG_XFRM=y
346CONFIG_XFRM_USER=m
347
348#
349# SCTP Configuration (EXPERIMENTAL)
350#
351# CONFIG_IP_SCTP is not set
352# CONFIG_ATM is not set
353# CONFIG_BRIDGE is not set
354# CONFIG_VLAN_8021Q is not set
355# CONFIG_DECNET is not set
356CONFIG_LLC=m
357CONFIG_LLC2=m
358# CONFIG_IPX is not set
359# CONFIG_ATALK is not set
360# CONFIG_X25 is not set
361# CONFIG_LAPB is not set
362# CONFIG_NET_DIVERT is not set
363# CONFIG_ECONET is not set
364# CONFIG_WAN_ROUTER is not set
365
366#
367# QoS and/or fair queueing
368#
369# CONFIG_NET_SCHED is not set
370# CONFIG_NET_CLS_ROUTE is not set
371
372#
373# Network testing
374#
375CONFIG_NET_PKTGEN=m
376# CONFIG_NETPOLL is not set
377# CONFIG_NET_POLL_CONTROLLER is not set
378# CONFIG_HAMRADIO is not set
379# CONFIG_IRDA is not set
380# CONFIG_BT is not set
381CONFIG_NETDEVICES=y
382CONFIG_DUMMY=m
383CONFIG_BONDING=m
384# CONFIG_EQUALIZER is not set
385CONFIG_TUN=m
386# CONFIG_ETHERTAP is not set
387
388#
389# Ethernet (10 or 100Mbit)
390#
391CONFIG_NET_ETHERNET=y
392CONFIG_MII=m
393CONFIG_LASI_82596=y
394
395#
396# Ethernet (1000 Mbit)
397#
398
399#
400# Ethernet (10000 Mbit)
401#
402
403#
404# Token Ring devices
405#
406
407#
408# Wireless LAN (non-hamradio)
409#
410CONFIG_NET_RADIO=y
411
412#
413# Obsolete Wireless cards support (pre-802.11)
414#
415# CONFIG_STRIP is not set
416# CONFIG_ATMEL is not set
417
418#
419# Wan interfaces
420#
421# CONFIG_WAN is not set
422# CONFIG_PLIP is not set
423CONFIG_PPP=m
424# CONFIG_PPP_MULTILINK is not set
425# CONFIG_PPP_FILTER is not set
426CONFIG_PPP_ASYNC=m
427CONFIG_PPP_SYNC_TTY=m
428CONFIG_PPP_DEFLATE=m
429CONFIG_PPP_BSDCOMP=m
430CONFIG_PPPOE=m
431# CONFIG_SLIP is not set
432# CONFIG_SHAPER is not set
433# CONFIG_NETCONSOLE is not set
434
435#
436# ISDN subsystem
437#
438# CONFIG_ISDN is not set
439
440#
441# Telephony Support
442#
443# CONFIG_PHONE is not set
444
445#
446# Input device support
447#
448CONFIG_INPUT=y
449
450#
451# Userland interfaces
452#
453CONFIG_INPUT_MOUSEDEV=y
454CONFIG_INPUT_MOUSEDEV_PSAUX=y
455CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
456CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
457# CONFIG_INPUT_JOYDEV is not set
458# CONFIG_INPUT_TSDEV is not set
459# CONFIG_INPUT_EVDEV is not set
460# CONFIG_INPUT_EVBUG is not set
461
462#
463# Input I/O drivers
464#
465# CONFIG_GAMEPORT is not set
466CONFIG_SOUND_GAMEPORT=y
467CONFIG_SERIO=y
468CONFIG_SERIO_SERPORT=y
469# CONFIG_SERIO_PARKBD is not set
470CONFIG_SERIO_GSCPS2=y
471CONFIG_HP_SDC=y
472CONFIG_HIL_MLC=y
473# CONFIG_SERIO_RAW is not set
474
475#
476# Input Device Drivers
477#
478CONFIG_INPUT_KEYBOARD=y
479CONFIG_KEYBOARD_ATKBD=y
480CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
481# CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES is not set
482# CONFIG_KEYBOARD_SUNKBD is not set
483# CONFIG_KEYBOARD_LKKBD is not set
484# CONFIG_KEYBOARD_XTKBD is not set
485# CONFIG_KEYBOARD_NEWTON is not set
486# CONFIG_KEYBOARD_HIL is not set
487CONFIG_INPUT_MOUSE=y
488CONFIG_MOUSE_PS2=y
489CONFIG_MOUSE_SERIAL=m
490# CONFIG_MOUSE_VSXXXAA is not set
491CONFIG_MOUSE_HIL=m
492# CONFIG_INPUT_JOYSTICK is not set
493# CONFIG_INPUT_TOUCHSCREEN is not set
494# CONFIG_INPUT_MISC is not set
495
496#
497# Character devices
498#
499CONFIG_VT=y
500CONFIG_VT_CONSOLE=y
501CONFIG_HW_CONSOLE=y
502# CONFIG_SERIAL_NONSTANDARD is not set
503
504#
505# Serial drivers
506#
507CONFIG_SERIAL_8250=y
508CONFIG_SERIAL_8250_CONSOLE=y
509CONFIG_SERIAL_8250_NR_UARTS=8
510CONFIG_SERIAL_8250_EXTENDED=y
511CONFIG_SERIAL_8250_MANY_PORTS=y
512CONFIG_SERIAL_8250_SHARE_IRQ=y
513# CONFIG_SERIAL_8250_DETECT_IRQ is not set
514# CONFIG_SERIAL_8250_MULTIPORT is not set
515# CONFIG_SERIAL_8250_RSA is not set
516
517#
518# Non-8250 serial port support
519#
520# CONFIG_SERIAL_MUX is not set
521CONFIG_PDC_CONSOLE=y
522CONFIG_SERIAL_CORE=y
523CONFIG_SERIAL_CORE_CONSOLE=y
524CONFIG_UNIX98_PTYS=y
525CONFIG_LEGACY_PTYS=y
526CONFIG_LEGACY_PTY_COUNT=64
527CONFIG_PRINTER=m
528# CONFIG_LP_CONSOLE is not set
529CONFIG_PPDEV=m
530# CONFIG_TIPAR is not set
531
532#
533# IPMI
534#
535# CONFIG_IPMI_HANDLER is not set
536
537#
538# Watchdog Cards
539#
540# CONFIG_WATCHDOG is not set
541CONFIG_GEN_RTC=y
542CONFIG_GEN_RTC_X=y
543# CONFIG_DTLK is not set
544# CONFIG_R3964 is not set
545
546#
547# Ftape, the floppy tape device driver
548#
549# CONFIG_AGP is not set
550# CONFIG_DRM is not set
551CONFIG_RAW_DRIVER=y
552CONFIG_MAX_RAW_DEVS=256
553
554#
555# I2C support
556#
557# CONFIG_I2C is not set
558
559#
560# Dallas's 1-wire bus
561#
562# CONFIG_W1 is not set
563
564#
565# Misc devices
566#
567
568#
569# Multimedia devices
570#
571# CONFIG_VIDEO_DEV is not set
572
573#
574# Digital Video Broadcasting Devices
575#
576# CONFIG_DVB is not set
577
578#
579# Graphics support
580#
581CONFIG_FB=y
582CONFIG_FB_MODE_HELPERS=y
583CONFIG_FB_TILEBLITTING=y
584CONFIG_FB_STI=y
585# CONFIG_FB_VIRTUAL is not set
586
587#
588# Console display driver support
589#
590CONFIG_STI_CONSOLE=y
591CONFIG_DUMMY_CONSOLE_COLUMNS=128
592CONFIG_DUMMY_CONSOLE_ROWS=48
593CONFIG_DUMMY_CONSOLE=y
594CONFIG_FRAMEBUFFER_CONSOLE=y
595CONFIG_FONTS=y
596CONFIG_FONT_8x8=y
597CONFIG_FONT_8x16=y
598# CONFIG_FONT_6x11 is not set
599# CONFIG_FONT_PEARL_8x8 is not set
600# CONFIG_FONT_ACORN_8x8 is not set
601# CONFIG_FONT_MINI_4x6 is not set
602# CONFIG_FONT_SUN8x16 is not set
603# CONFIG_FONT_SUN12x22 is not set
604
605#
606# Logo configuration
607#
608CONFIG_LOGO=y
609# CONFIG_LOGO_LINUX_MONO is not set
610# CONFIG_LOGO_LINUX_VGA16 is not set
611# CONFIG_LOGO_LINUX_CLUT224 is not set
612CONFIG_LOGO_PARISC_CLUT224=y
613
614#
615# Sound
616#
617CONFIG_SOUND=y
618
619#
620# Advanced Linux Sound Architecture
621#
622CONFIG_SND=y
623CONFIG_SND_TIMER=y
624CONFIG_SND_PCM=y
625CONFIG_SND_SEQUENCER=y
626# CONFIG_SND_SEQ_DUMMY is not set
627CONFIG_SND_OSSEMUL=y
628CONFIG_SND_MIXER_OSS=y
629CONFIG_SND_PCM_OSS=y
630CONFIG_SND_SEQUENCER_OSS=y
631# CONFIG_SND_VERBOSE_PRINTK is not set
632# CONFIG_SND_DEBUG is not set
633
634#
635# Generic devices
636#
637# CONFIG_SND_DUMMY is not set
638# CONFIG_SND_VIRMIDI is not set
639# CONFIG_SND_MTPAV is not set
640# CONFIG_SND_SERIAL_U16550 is not set
641# CONFIG_SND_MPU401 is not set
642
643#
644# GSC devices
645#
646CONFIG_SND_HARMONY=y
647
648#
649# Open Sound System
650#
651# CONFIG_SOUND_PRIME is not set
652
653#
654# USB support
655#
656# CONFIG_USB_ARCH_HAS_HCD is not set
657# CONFIG_USB_ARCH_HAS_OHCI is not set
658
659#
660# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
661#
662
663#
664# USB Gadget Support
665#
666# CONFIG_USB_GADGET is not set
667
668#
669# MMC/SD Card support
670#
671# CONFIG_MMC is not set
672
673#
674# File systems
675#
676CONFIG_EXT2_FS=y
677# CONFIG_EXT2_FS_XATTR is not set
678CONFIG_EXT3_FS=y
679# CONFIG_EXT3_FS_XATTR is not set
680CONFIG_JBD=y
681# CONFIG_JBD_DEBUG is not set
682# CONFIG_REISERFS_FS is not set
683CONFIG_JFS_FS=m
684# CONFIG_JFS_POSIX_ACL is not set
685# CONFIG_JFS_DEBUG is not set
686# CONFIG_JFS_STATISTICS is not set
687CONFIG_FS_POSIX_ACL=y
688CONFIG_XFS_FS=m
689# CONFIG_XFS_RT is not set
690# CONFIG_XFS_QUOTA is not set
691# CONFIG_XFS_SECURITY is not set
692# CONFIG_XFS_POSIX_ACL is not set
693# CONFIG_MINIX_FS is not set
694# CONFIG_ROMFS_FS is not set
695# CONFIG_QUOTA is not set
696CONFIG_DNOTIFY=y
697# CONFIG_AUTOFS_FS is not set
698CONFIG_AUTOFS4_FS=y
699
700#
701# CD-ROM/DVD Filesystems
702#
703CONFIG_ISO9660_FS=y
704CONFIG_JOLIET=y
705# CONFIG_ZISOFS is not set
706CONFIG_UDF_FS=m
707CONFIG_UDF_NLS=y
708
709#
710# DOS/FAT/NT Filesystems
711#
712CONFIG_FAT_FS=m
713CONFIG_MSDOS_FS=m
714CONFIG_VFAT_FS=m
715CONFIG_FAT_DEFAULT_CODEPAGE=437
716CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
717# CONFIG_NTFS_FS is not set
718
719#
720# Pseudo filesystems
721#
722CONFIG_PROC_FS=y
723CONFIG_PROC_KCORE=y
724CONFIG_SYSFS=y
725# CONFIG_DEVFS_FS is not set
726# CONFIG_DEVPTS_FS_XATTR is not set
727CONFIG_TMPFS=y
728CONFIG_TMPFS_XATTR=y
729# CONFIG_TMPFS_SECURITY is not set
730# CONFIG_HUGETLBFS is not set
731# CONFIG_HUGETLB_PAGE is not set
732CONFIG_RAMFS=y
733
734#
735# Miscellaneous filesystems
736#
737# CONFIG_ADFS_FS is not set
738# CONFIG_AFFS_FS is not set
739# CONFIG_HFS_FS is not set
740# CONFIG_HFSPLUS_FS is not set
741# CONFIG_BEFS_FS is not set
742# CONFIG_BFS_FS is not set
743# CONFIG_EFS_FS is not set
744# CONFIG_CRAMFS is not set
745# CONFIG_VXFS_FS is not set
746# CONFIG_HPFS_FS is not set
747# CONFIG_QNX4FS_FS is not set
748# CONFIG_SYSV_FS is not set
749CONFIG_UFS_FS=m
750# CONFIG_UFS_FS_WRITE is not set
751
752#
753# Network File Systems
754#
755CONFIG_NFS_FS=y
756CONFIG_NFS_V3=y
757CONFIG_NFS_V4=y
758CONFIG_NFS_DIRECTIO=y
759CONFIG_NFSD=m
760CONFIG_NFSD_V3=y
761CONFIG_NFSD_V4=y
762CONFIG_NFSD_TCP=y
763CONFIG_ROOT_NFS=y
764CONFIG_LOCKD=y
765CONFIG_LOCKD_V4=y
766CONFIG_EXPORTFS=m
767CONFIG_SUNRPC=y
768CONFIG_SUNRPC_GSS=y
769CONFIG_RPCSEC_GSS_KRB5=y
770CONFIG_RPCSEC_GSS_SPKM3=m
771CONFIG_SMB_FS=m
772CONFIG_SMB_NLS_DEFAULT=y
773CONFIG_SMB_NLS_REMOTE="cp437"
774CONFIG_CIFS=m
775# CONFIG_CIFS_STATS is not set
776# CONFIG_CIFS_XATTR is not set
777# CONFIG_CIFS_EXPERIMENTAL is not set
778# CONFIG_NCP_FS is not set
779# CONFIG_CODA_FS is not set
780# CONFIG_AFS_FS is not set
781
782#
783# Partition Types
784#
785# CONFIG_PARTITION_ADVANCED is not set
786CONFIG_MSDOS_PARTITION=y
787
788#
789# Native Language Support
790#
791CONFIG_NLS=y
792CONFIG_NLS_DEFAULT="iso8859-1"
793CONFIG_NLS_CODEPAGE_437=m
794CONFIG_NLS_CODEPAGE_737=m
795CONFIG_NLS_CODEPAGE_775=m
796CONFIG_NLS_CODEPAGE_850=m
797CONFIG_NLS_CODEPAGE_852=m
798CONFIG_NLS_CODEPAGE_855=m
799CONFIG_NLS_CODEPAGE_857=m
800CONFIG_NLS_CODEPAGE_860=m
801CONFIG_NLS_CODEPAGE_861=m
802CONFIG_NLS_CODEPAGE_862=m
803CONFIG_NLS_CODEPAGE_863=m
804CONFIG_NLS_CODEPAGE_864=m
805CONFIG_NLS_CODEPAGE_865=m
806CONFIG_NLS_CODEPAGE_866=m
807CONFIG_NLS_CODEPAGE_869=m
808CONFIG_NLS_CODEPAGE_936=m
809CONFIG_NLS_CODEPAGE_950=m
810CONFIG_NLS_CODEPAGE_932=m
811CONFIG_NLS_CODEPAGE_949=m
812CONFIG_NLS_CODEPAGE_874=m
813CONFIG_NLS_ISO8859_8=m
814CONFIG_NLS_CODEPAGE_1250=m
815CONFIG_NLS_CODEPAGE_1251=m
816CONFIG_NLS_ASCII=m
817CONFIG_NLS_ISO8859_1=m
818CONFIG_NLS_ISO8859_2=m
819CONFIG_NLS_ISO8859_3=m
820CONFIG_NLS_ISO8859_4=m
821CONFIG_NLS_ISO8859_5=m
822CONFIG_NLS_ISO8859_6=m
823CONFIG_NLS_ISO8859_7=m
824CONFIG_NLS_ISO8859_9=m
825CONFIG_NLS_ISO8859_13=m
826CONFIG_NLS_ISO8859_14=m
827CONFIG_NLS_ISO8859_15=m
828CONFIG_NLS_KOI8_R=m
829CONFIG_NLS_KOI8_U=m
830CONFIG_NLS_UTF8=m
831
832#
833# Profiling support
834#
835CONFIG_PROFILING=y
836CONFIG_OPROFILE=m
837
838#
839# Kernel hacking
840#
841CONFIG_DEBUG_KERNEL=y
842CONFIG_MAGIC_SYSRQ=y
843# CONFIG_SCHEDSTATS is not set
844# CONFIG_DEBUG_SLAB is not set
845# CONFIG_DEBUG_SPINLOCK is not set
846# CONFIG_DEBUG_KOBJECT is not set
847# CONFIG_DEBUG_INFO is not set
848
849#
850# Security options
851#
852CONFIG_KEYS=y
853CONFIG_KEYS_DEBUG_PROC_KEYS=y
854# CONFIG_SECURITY is not set
855
856#
857# Cryptographic options
858#
859CONFIG_CRYPTO=y
860CONFIG_CRYPTO_HMAC=y
861CONFIG_CRYPTO_NULL=m
862CONFIG_CRYPTO_MD4=m
863CONFIG_CRYPTO_MD5=y
864CONFIG_CRYPTO_SHA1=m
865CONFIG_CRYPTO_SHA256=m
866CONFIG_CRYPTO_SHA512=m
867CONFIG_CRYPTO_WP512=m
868CONFIG_CRYPTO_DES=y
869CONFIG_CRYPTO_BLOWFISH=m
870CONFIG_CRYPTO_TWOFISH=m
871CONFIG_CRYPTO_SERPENT=m
872CONFIG_CRYPTO_AES=m
873CONFIG_CRYPTO_CAST5=m
874CONFIG_CRYPTO_CAST6=m
875CONFIG_CRYPTO_TEA=m
876CONFIG_CRYPTO_ARC4=m
877CONFIG_CRYPTO_KHAZAD=m
878CONFIG_CRYPTO_ANUBIS=m
879CONFIG_CRYPTO_DEFLATE=m
880CONFIG_CRYPTO_MICHAEL_MIC=m
881CONFIG_CRYPTO_CRC32C=m
882CONFIG_CRYPTO_TEST=m
883
884#
885# Library routines
886#
887CONFIG_CRC_CCITT=m
888CONFIG_CRC32=y
889CONFIG_LIBCRC32C=m
890CONFIG_ZLIB_INFLATE=m
891CONFIG_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 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.11-rc4-pa1
4# Wed Feb 16 11:32:49 2005
5#
6CONFIG_PARISC=y
7CONFIG_MMU=y
8CONFIG_STACK_GROWSUP=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10CONFIG_GENERIC_CALIBRATE_DELAY=y
11CONFIG_GENERIC_HARDIRQS=y
12CONFIG_GENERIC_IRQ_PROBE=y
13
14#
15# Code maturity level options
16#
17CONFIG_EXPERIMENTAL=y
18# CONFIG_CLEAN_COMPILE is not set
19CONFIG_BROKEN=y
20CONFIG_BROKEN_ON_SMP=y
21CONFIG_LOCK_KERNEL=y
22
23#
24# General setup
25#
26CONFIG_LOCALVERSION=""
27CONFIG_SWAP=y
28CONFIG_SYSVIPC=y
29CONFIG_POSIX_MQUEUE=y
30# CONFIG_BSD_PROCESS_ACCT is not set
31CONFIG_SYSCTL=y
32# CONFIG_AUDIT is not set
33CONFIG_LOG_BUF_SHIFT=16
34CONFIG_HOTPLUG=y
35CONFIG_KOBJECT_UEVENT=y
36CONFIG_IKCONFIG=y
37CONFIG_IKCONFIG_PROC=y
38CONFIG_EMBEDDED=y
39CONFIG_KALLSYMS=y
40CONFIG_KALLSYMS_ALL=y
41# CONFIG_KALLSYMS_EXTRA_PASS is not set
42CONFIG_FUTEX=y
43CONFIG_EPOLL=y
44# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
45CONFIG_SHMEM=y
46CONFIG_CC_ALIGN_FUNCTIONS=0
47CONFIG_CC_ALIGN_LABELS=0
48CONFIG_CC_ALIGN_LOOPS=0
49CONFIG_CC_ALIGN_JUMPS=0
50# CONFIG_TINY_SHMEM is not set
51
52#
53# Loadable module support
54#
55CONFIG_MODULES=y
56CONFIG_MODULE_UNLOAD=y
57CONFIG_MODULE_FORCE_UNLOAD=y
58CONFIG_OBSOLETE_MODPARM=y
59# CONFIG_MODVERSIONS is not set
60# CONFIG_MODULE_SRCVERSION_ALL is not set
61CONFIG_KMOD=y
62CONFIG_STOP_MACHINE=y
63
64#
65# Processor type and features
66#
67# CONFIG_PA7000 is not set
68# CONFIG_PA7100LC is not set
69# CONFIG_PA7200 is not set
70# CONFIG_PA7300LC is not set
71CONFIG_PA8X00=y
72CONFIG_PA20=y
73CONFIG_PREFETCH=y
74CONFIG_64BIT=y
75CONFIG_SMP=y
76CONFIG_HOTPLUG_CPU=y
77CONFIG_DISCONTIGMEM=y
78# CONFIG_PREEMPT is not set
79CONFIG_COMPAT=y
80CONFIG_NR_CPUS=8
81
82#
83# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
84#
85# CONFIG_GSC is not set
86CONFIG_PCI=y
87CONFIG_PCI_LEGACY_PROC=y
88CONFIG_PCI_NAMES=y
89CONFIG_PCI_LBA=y
90CONFIG_IOSAPIC=y
91CONFIG_IOMMU_SBA=y
92
93#
94# PCCARD (PCMCIA/CardBus) support
95#
96CONFIG_PCCARD=m
97# CONFIG_PCMCIA_DEBUG is not set
98CONFIG_PCMCIA=m
99CONFIG_CARDBUS=y
100
101#
102# PC-card bridges
103#
104CONFIG_YENTA=m
105CONFIG_PD6729=m
106CONFIG_I82092=m
107CONFIG_TCIC=m
108CONFIG_PCCARD_NONSTATIC=m
109
110#
111# PCI Hotplug Support
112#
113# CONFIG_HOTPLUG_PCI is not set
114
115#
116# PA-RISC specific drivers
117#
118# CONFIG_SUPERIO is not set
119# CONFIG_CHASSIS_LCD_LED is not set
120CONFIG_PDC_CHASSIS=y
121CONFIG_PDC_STABLE=y
122
123#
124# Executable file formats
125#
126CONFIG_BINFMT_ELF=y
127# CONFIG_BINFMT_MISC is not set
128
129#
130# Device Drivers
131#
132
133#
134# Generic Driver Options
135#
136# CONFIG_STANDALONE is not set
137# CONFIG_PREVENT_FIRMWARE_BUILD is not set
138CONFIG_FW_LOADER=y
139# CONFIG_DEBUG_DRIVER is not set
140
141#
142# Memory Technology Devices (MTD)
143#
144# CONFIG_MTD is not set
145
146#
147# Parallel port support
148#
149# CONFIG_PARPORT is not set
150
151#
152# Plug and Play support
153#
154
155#
156# Block devices
157#
158# CONFIG_BLK_DEV_FD is not set
159# CONFIG_BLK_CPQ_DA is not set
160# CONFIG_BLK_CPQ_CISS_DA is not set
161# CONFIG_BLK_DEV_DAC960 is not set
162CONFIG_BLK_DEV_UMEM=m
163# CONFIG_BLK_DEV_COW_COMMON is not set
164CONFIG_BLK_DEV_LOOP=y
165# CONFIG_BLK_DEV_CRYPTOLOOP is not set
166# CONFIG_BLK_DEV_NBD is not set
167# CONFIG_BLK_DEV_SX8 is not set
168CONFIG_BLK_DEV_RAM=y
169CONFIG_BLK_DEV_RAM_COUNT=16
170CONFIG_BLK_DEV_RAM_SIZE=6144
171CONFIG_BLK_DEV_INITRD=y
172CONFIG_INITRAMFS_SOURCE=""
173# CONFIG_CDROM_PKTCDVD is not set
174
175#
176# IO Schedulers
177#
178CONFIG_IOSCHED_NOOP=y
179CONFIG_IOSCHED_AS=y
180CONFIG_IOSCHED_DEADLINE=y
181CONFIG_IOSCHED_CFQ=y
182# CONFIG_ATA_OVER_ETH is not set
183
184#
185# ATA/ATAPI/MFM/RLL support
186#
187# CONFIG_IDE is not set
188
189#
190# SCSI device support
191#
192CONFIG_SCSI=y
193CONFIG_SCSI_PROC_FS=y
194
195#
196# SCSI support type (disk, tape, CD-ROM)
197#
198CONFIG_BLK_DEV_SD=y
199CONFIG_CHR_DEV_ST=y
200# CONFIG_CHR_DEV_OSST is not set
201CONFIG_BLK_DEV_SR=y
202# CONFIG_BLK_DEV_SR_VENDOR is not set
203CONFIG_CHR_DEV_SG=y
204
205#
206# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
207#
208CONFIG_SCSI_MULTI_LUN=y
209# CONFIG_SCSI_CONSTANTS is not set
210# CONFIG_SCSI_LOGGING is not set
211
212#
213# SCSI Transport Attributes
214#
215CONFIG_SCSI_SPI_ATTRS=y
216CONFIG_SCSI_FC_ATTRS=m
217CONFIG_SCSI_ISCSI_ATTRS=m
218
219#
220# SCSI low-level drivers
221#
222# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
223# CONFIG_SCSI_3W_9XXX is not set
224# CONFIG_SCSI_ACARD is not set
225# CONFIG_SCSI_AACRAID is not set
226# CONFIG_SCSI_AIC7XXX is not set
227# CONFIG_SCSI_AIC7XXX_OLD is not set
228# CONFIG_SCSI_AIC79XX is not set
229# CONFIG_SCSI_ADVANSYS is not set
230# CONFIG_MEGARAID_NEWGEN is not set
231# CONFIG_MEGARAID_LEGACY is not set
232# CONFIG_SCSI_SATA is not set
233# CONFIG_SCSI_BUSLOGIC is not set
234# CONFIG_SCSI_CPQFCTS is not set
235# CONFIG_SCSI_DMX3191D is not set
236# CONFIG_SCSI_EATA is not set
237# CONFIG_SCSI_EATA_PIO is not set
238# CONFIG_SCSI_FUTURE_DOMAIN is not set
239# CONFIG_SCSI_GDTH is not set
240# CONFIG_SCSI_IPS is not set
241# CONFIG_SCSI_INITIO is not set
242# CONFIG_SCSI_INIA100 is not set
243CONFIG_SCSI_SYM53C8XX_2=y
244CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
245CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
246CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
247# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
248# CONFIG_SCSI_IPR is not set
249# CONFIG_SCSI_PCI2000 is not set
250# CONFIG_SCSI_PCI2220I is not set
251# CONFIG_SCSI_QLOGIC_ISP is not set
252CONFIG_SCSI_QLOGIC_FC=m
253# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
254CONFIG_SCSI_QLOGIC_1280=m
255# CONFIG_SCSI_QLOGIC_1280_1040 is not set
256CONFIG_SCSI_QLA2XXX=y
257# CONFIG_SCSI_QLA21XX is not set
258# CONFIG_SCSI_QLA22XX is not set
259CONFIG_SCSI_QLA2300=m
260CONFIG_SCSI_QLA2322=m
261CONFIG_SCSI_QLA6312=m
262# CONFIG_SCSI_DC395x is not set
263# CONFIG_SCSI_DC390T is not set
264CONFIG_SCSI_DEBUG=m
265
266#
267# PCMCIA SCSI adapter support
268#
269CONFIG_PCMCIA_FDOMAIN=m
270CONFIG_PCMCIA_QLOGIC=m
271CONFIG_PCMCIA_SYM53C500=m
272
273#
274# Multi-device support (RAID and LVM)
275#
276CONFIG_MD=y
277CONFIG_BLK_DEV_MD=y
278CONFIG_MD_LINEAR=y
279CONFIG_MD_RAID0=y
280CONFIG_MD_RAID1=y
281# CONFIG_MD_RAID10 is not set
282# CONFIG_MD_RAID5 is not set
283# CONFIG_MD_RAID6 is not set
284# CONFIG_MD_MULTIPATH is not set
285# CONFIG_MD_FAULTY is not set
286# CONFIG_BLK_DEV_DM is not set
287
288#
289# Fusion MPT device support
290#
291CONFIG_FUSION=m
292CONFIG_FUSION_MAX_SGE=40
293CONFIG_FUSION_CTL=m
294
295#
296# IEEE 1394 (FireWire) support
297#
298# CONFIG_IEEE1394 is not set
299
300#
301# I2O device support
302#
303# CONFIG_I2O is not set
304
305#
306# Networking support
307#
308CONFIG_NET=y
309
310#
311# Networking options
312#
313CONFIG_PACKET=y
314CONFIG_PACKET_MMAP=y
315CONFIG_NETLINK_DEV=y
316CONFIG_UNIX=y
317CONFIG_NET_KEY=m
318CONFIG_INET=y
319CONFIG_IP_MULTICAST=y
320# CONFIG_IP_ADVANCED_ROUTER is not set
321CONFIG_IP_PNP=y
322CONFIG_IP_PNP_DHCP=y
323CONFIG_IP_PNP_BOOTP=y
324# CONFIG_IP_PNP_RARP is not set
325# CONFIG_NET_IPIP is not set
326# CONFIG_NET_IPGRE is not set
327# CONFIG_IP_MROUTE is not set
328# CONFIG_ARPD is not set
329# CONFIG_SYN_COOKIES is not set
330CONFIG_INET_AH=m
331CONFIG_INET_ESP=m
332# CONFIG_INET_IPCOMP is not set
333CONFIG_INET_TUNNEL=m
334CONFIG_IP_TCPDIAG=y
335# CONFIG_IP_TCPDIAG_IPV6 is not set
336
337#
338# IP: Virtual Server Configuration
339#
340# CONFIG_IP_VS is not set
341# CONFIG_IPV6 is not set
342CONFIG_NETFILTER=y
343# CONFIG_NETFILTER_DEBUG is not set
344
345#
346# IP: Netfilter Configuration
347#
348CONFIG_IP_NF_CONNTRACK=m
349# CONFIG_IP_NF_CT_ACCT is not set
350CONFIG_IP_NF_CONNTRACK_MARK=y
351CONFIG_IP_NF_CT_PROTO_SCTP=m
352CONFIG_IP_NF_FTP=m
353CONFIG_IP_NF_IRC=m
354CONFIG_IP_NF_TFTP=m
355CONFIG_IP_NF_AMANDA=m
356CONFIG_IP_NF_QUEUE=m
357CONFIG_IP_NF_IPTABLES=m
358CONFIG_IP_NF_MATCH_LIMIT=m
359CONFIG_IP_NF_MATCH_IPRANGE=m
360CONFIG_IP_NF_MATCH_MAC=m
361CONFIG_IP_NF_MATCH_PKTTYPE=m
362CONFIG_IP_NF_MATCH_MARK=m
363CONFIG_IP_NF_MATCH_MULTIPORT=m
364CONFIG_IP_NF_MATCH_TOS=m
365CONFIG_IP_NF_MATCH_RECENT=m
366CONFIG_IP_NF_MATCH_ECN=m
367CONFIG_IP_NF_MATCH_DSCP=m
368CONFIG_IP_NF_MATCH_AH_ESP=m
369CONFIG_IP_NF_MATCH_LENGTH=m
370CONFIG_IP_NF_MATCH_TTL=m
371CONFIG_IP_NF_MATCH_TCPMSS=m
372CONFIG_IP_NF_MATCH_HELPER=m
373CONFIG_IP_NF_MATCH_STATE=m
374CONFIG_IP_NF_MATCH_CONNTRACK=m
375CONFIG_IP_NF_MATCH_OWNER=m
376# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
377# CONFIG_IP_NF_MATCH_REALM is not set
378CONFIG_IP_NF_MATCH_SCTP=m
379CONFIG_IP_NF_MATCH_COMMENT=m
380CONFIG_IP_NF_MATCH_CONNMARK=m
381CONFIG_IP_NF_MATCH_HASHLIMIT=m
382CONFIG_IP_NF_FILTER=m
383CONFIG_IP_NF_TARGET_REJECT=m
384CONFIG_IP_NF_TARGET_LOG=m
385CONFIG_IP_NF_TARGET_ULOG=m
386CONFIG_IP_NF_TARGET_TCPMSS=m
387CONFIG_IP_NF_NAT=m
388CONFIG_IP_NF_NAT_NEEDED=y
389CONFIG_IP_NF_TARGET_MASQUERADE=m
390CONFIG_IP_NF_TARGET_REDIRECT=m
391CONFIG_IP_NF_TARGET_NETMAP=m
392CONFIG_IP_NF_TARGET_SAME=m
393CONFIG_IP_NF_NAT_SNMP_BASIC=m
394CONFIG_IP_NF_NAT_IRC=m
395CONFIG_IP_NF_NAT_FTP=m
396CONFIG_IP_NF_NAT_TFTP=m
397CONFIG_IP_NF_NAT_AMANDA=m
398CONFIG_IP_NF_MANGLE=m
399CONFIG_IP_NF_TARGET_TOS=m
400CONFIG_IP_NF_TARGET_ECN=m
401CONFIG_IP_NF_TARGET_DSCP=m
402CONFIG_IP_NF_TARGET_MARK=m
403CONFIG_IP_NF_TARGET_CLASSIFY=m
404CONFIG_IP_NF_TARGET_CONNMARK=m
405CONFIG_IP_NF_TARGET_CLUSTERIP=m
406CONFIG_IP_NF_RAW=m
407CONFIG_IP_NF_TARGET_NOTRACK=m
408CONFIG_IP_NF_ARPTABLES=m
409CONFIG_IP_NF_ARPFILTER=m
410CONFIG_IP_NF_ARP_MANGLE=m
411CONFIG_XFRM=y
412CONFIG_XFRM_USER=m
413
414#
415# SCTP Configuration (EXPERIMENTAL)
416#
417# CONFIG_IP_SCTP is not set
418# CONFIG_ATM is not set
419# CONFIG_BRIDGE is not set
420# CONFIG_VLAN_8021Q is not set
421# CONFIG_DECNET is not set
422CONFIG_LLC=m
423CONFIG_LLC2=m
424# CONFIG_IPX is not set
425# CONFIG_ATALK is not set
426# CONFIG_X25 is not set
427# CONFIG_LAPB is not set
428# CONFIG_NET_DIVERT is not set
429# CONFIG_ECONET is not set
430# CONFIG_WAN_ROUTER is not set
431
432#
433# QoS and/or fair queueing
434#
435# CONFIG_NET_SCHED is not set
436# CONFIG_NET_CLS_ROUTE is not set
437
438#
439# Network testing
440#
441CONFIG_NET_PKTGEN=m
442# CONFIG_NETPOLL is not set
443# CONFIG_NET_POLL_CONTROLLER is not set
444# CONFIG_HAMRADIO is not set
445# CONFIG_IRDA is not set
446# CONFIG_BT is not set
447CONFIG_NETDEVICES=y
448CONFIG_DUMMY=m
449CONFIG_BONDING=m
450# CONFIG_EQUALIZER is not set
451CONFIG_TUN=m
452# CONFIG_ETHERTAP is not set
453
454#
455# ARCnet devices
456#
457# CONFIG_ARCNET is not set
458
459#
460# Ethernet (10 or 100Mbit)
461#
462CONFIG_NET_ETHERNET=y
463CONFIG_MII=m
464# CONFIG_HAPPYMEAL is not set
465# CONFIG_SUNGEM is not set
466CONFIG_NET_VENDOR_3COM=y
467CONFIG_VORTEX=m
468CONFIG_TYPHOON=m
469
470#
471# Tulip family network device support
472#
473CONFIG_NET_TULIP=y
474CONFIG_DE2104X=m
475CONFIG_TULIP=y
476# CONFIG_TULIP_MWI is not set
477CONFIG_TULIP_MMIO=y
478# CONFIG_TULIP_NAPI is not set
479# CONFIG_DE4X5 is not set
480# CONFIG_WINBOND_840 is not set
481# CONFIG_DM9102 is not set
482CONFIG_PCMCIA_XIRCOM=m
483# CONFIG_PCMCIA_XIRTULIP is not set
484CONFIG_HP100=m
485CONFIG_NET_PCI=y
486CONFIG_PCNET32=m
487# CONFIG_AMD8111_ETH is not set
488# CONFIG_ADAPTEC_STARFIRE is not set
489# CONFIG_B44 is not set
490# CONFIG_FORCEDETH is not set
491# CONFIG_DGRS is not set
492CONFIG_EEPRO100=m
493CONFIG_E100=m
494CONFIG_E100_NAPI=y
495# CONFIG_FEALNX is not set
496CONFIG_NATSEMI=m
497# CONFIG_NE2K_PCI is not set
498# CONFIG_8139CP is not set
499CONFIG_8139TOO=m
500# CONFIG_8139TOO_PIO is not set
501# CONFIG_8139TOO_TUNE_TWISTER is not set
502# CONFIG_8139TOO_8129 is not set
503# CONFIG_8139_OLD_RX_RESET is not set
504# CONFIG_SIS900 is not set
505CONFIG_EPIC100=m
506# CONFIG_SUNDANCE is not set
507CONFIG_VIA_RHINE=m
508CONFIG_VIA_RHINE_MMIO=y
509
510#
511# Ethernet (1000 Mbit)
512#
513CONFIG_ACENIC=m
514CONFIG_ACENIC_OMIT_TIGON_I=y
515CONFIG_DL2K=m
516CONFIG_E1000=m
517CONFIG_E1000_NAPI=y
518# CONFIG_NS83820 is not set
519# CONFIG_HAMACHI is not set
520# CONFIG_YELLOWFIN is not set
521# CONFIG_R8169 is not set
522# CONFIG_SK98LIN is not set
523# CONFIG_VIA_VELOCITY is not set
524CONFIG_TIGON3=m
525
526#
527# Ethernet (10000 Mbit)
528#
529CONFIG_IXGB=m
530CONFIG_IXGB_NAPI=y
531CONFIG_S2IO=m
532CONFIG_S2IO_NAPI=y
533# CONFIG_2BUFF_MODE is not set
534
535#
536# Token Ring devices
537#
538# CONFIG_TR is not set
539
540#
541# Wireless LAN (non-hamradio)
542#
543CONFIG_NET_RADIO=y
544
545#
546# Obsolete Wireless cards support (pre-802.11)
547#
548# CONFIG_STRIP is not set
549# CONFIG_PCMCIA_WAVELAN is not set
550CONFIG_PCMCIA_NETWAVE=m
551
552#
553# Wireless 802.11 Frequency Hopping cards support
554#
555CONFIG_PCMCIA_RAYCS=m
556
557#
558# Wireless 802.11b ISA/PCI cards support
559#
560CONFIG_HERMES=m
561CONFIG_PLX_HERMES=m
562CONFIG_TMD_HERMES=m
563CONFIG_PCI_HERMES=m
564# CONFIG_ATMEL is not set
565
566#
567# Wireless 802.11b Pcmcia/Cardbus cards support
568#
569CONFIG_PCMCIA_HERMES=m
570CONFIG_AIRO_CS=m
571CONFIG_PCMCIA_WL3501=m
572
573#
574# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
575#
576# CONFIG_PRISM54 is not set
577CONFIG_NET_WIRELESS=y
578
579#
580# PCMCIA network device support
581#
582CONFIG_NET_PCMCIA=y
583CONFIG_PCMCIA_3C589=m
584CONFIG_PCMCIA_3C574=m
585# CONFIG_PCMCIA_FMVJ18X is not set
586# CONFIG_PCMCIA_PCNET is not set
587# CONFIG_PCMCIA_NMCLAN is not set
588CONFIG_PCMCIA_SMC91C92=m
589CONFIG_PCMCIA_XIRC2PS=m
590# CONFIG_PCMCIA_AXNET is not set
591
592#
593# Wan interfaces
594#
595# CONFIG_WAN is not set
596# CONFIG_FDDI is not set
597# CONFIG_HIPPI is not set
598CONFIG_PPP=m
599# CONFIG_PPP_MULTILINK is not set
600# CONFIG_PPP_FILTER is not set
601CONFIG_PPP_ASYNC=m
602CONFIG_PPP_SYNC_TTY=m
603CONFIG_PPP_DEFLATE=m
604CONFIG_PPP_BSDCOMP=m
605# CONFIG_PPPOE is not set
606# CONFIG_SLIP is not set
607# CONFIG_NET_FC is not set
608# CONFIG_SHAPER is not set
609# CONFIG_NETCONSOLE is not set
610
611#
612# ISDN subsystem
613#
614# CONFIG_ISDN is not set
615
616#
617# Telephony Support
618#
619# CONFIG_PHONE is not set
620
621#
622# Input device support
623#
624CONFIG_INPUT=y
625
626#
627# Userland interfaces
628#
629# CONFIG_INPUT_MOUSEDEV is not set
630# CONFIG_INPUT_JOYDEV is not set
631# CONFIG_INPUT_TSDEV is not set
632# CONFIG_INPUT_EVDEV is not set
633# CONFIG_INPUT_EVBUG is not set
634
635#
636# Input I/O drivers
637#
638# CONFIG_GAMEPORT is not set
639CONFIG_SOUND_GAMEPORT=y
640# CONFIG_SERIO is not set
641
642#
643# Input Device Drivers
644#
645# CONFIG_INPUT_KEYBOARD is not set
646# CONFIG_INPUT_MOUSE is not set
647# CONFIG_INPUT_JOYSTICK is not set
648# CONFIG_INPUT_TOUCHSCREEN is not set
649# CONFIG_INPUT_MISC is not set
650
651#
652# Character devices
653#
654CONFIG_VT=y
655CONFIG_VT_CONSOLE=y
656CONFIG_HW_CONSOLE=y
657# CONFIG_SERIAL_NONSTANDARD is not set
658
659#
660# Serial drivers
661#
662CONFIG_SERIAL_8250=y
663CONFIG_SERIAL_8250_CONSOLE=y
664CONFIG_SERIAL_8250_CS=m
665CONFIG_SERIAL_8250_NR_UARTS=8
666CONFIG_SERIAL_8250_EXTENDED=y
667CONFIG_SERIAL_8250_MANY_PORTS=y
668CONFIG_SERIAL_8250_SHARE_IRQ=y
669# CONFIG_SERIAL_8250_DETECT_IRQ is not set
670# CONFIG_SERIAL_8250_MULTIPORT is not set
671# CONFIG_SERIAL_8250_RSA is not set
672
673#
674# Non-8250 serial port support
675#
676# CONFIG_SERIAL_MUX is not set
677CONFIG_PDC_CONSOLE=y
678CONFIG_SERIAL_CORE=y
679CONFIG_SERIAL_CORE_CONSOLE=y
680CONFIG_UNIX98_PTYS=y
681# CONFIG_LEGACY_PTYS is not set
682
683#
684# IPMI
685#
686# CONFIG_IPMI_HANDLER is not set
687
688#
689# Watchdog Cards
690#
691# CONFIG_WATCHDOG is not set
692CONFIG_GEN_RTC=y
693CONFIG_GEN_RTC_X=y
694# CONFIG_DTLK is not set
695# CONFIG_R3964 is not set
696# CONFIG_APPLICOM is not set
697
698#
699# Ftape, the floppy tape device driver
700#
701# CONFIG_DRM is not set
702
703#
704# PCMCIA character devices
705#
706# CONFIG_SYNCLINK_CS is not set
707CONFIG_RAW_DRIVER=y
708CONFIG_MAX_RAW_DEVS=256
709
710#
711# I2C support
712#
713# CONFIG_I2C is not set
714
715#
716# Dallas's 1-wire bus
717#
718# CONFIG_W1 is not set
719
720#
721# Misc devices
722#
723
724#
725# Multimedia devices
726#
727# CONFIG_VIDEO_DEV is not set
728
729#
730# Digital Video Broadcasting Devices
731#
732# CONFIG_DVB is not set
733
734#
735# Graphics support
736#
737# CONFIG_FB is not set
738
739#
740# Console display driver support
741#
742CONFIG_DUMMY_CONSOLE=y
743CONFIG_DUMMY_CONSOLE_COLUMNS=160
744CONFIG_DUMMY_CONSOLE_ROWS=64
745
746#
747# Sound
748#
749# CONFIG_SOUND is not set
750
751#
752# USB support
753#
754# CONFIG_USB is not set
755CONFIG_USB_ARCH_HAS_HCD=y
756CONFIG_USB_ARCH_HAS_OHCI=y
757
758#
759# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
760#
761
762#
763# USB Gadget Support
764#
765# CONFIG_USB_GADGET is not set
766
767#
768# MMC/SD Card support
769#
770# CONFIG_MMC is not set
771
772#
773# InfiniBand support
774#
775CONFIG_INFINIBAND=m
776CONFIG_INFINIBAND_MTHCA=m
777# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
778CONFIG_INFINIBAND_IPOIB=m
779# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
780
781#
782# File systems
783#
784CONFIG_EXT2_FS=y
785# CONFIG_EXT2_FS_XATTR is not set
786CONFIG_EXT3_FS=y
787# CONFIG_EXT3_FS_XATTR is not set
788CONFIG_JBD=y
789# CONFIG_JBD_DEBUG is not set
790# CONFIG_REISERFS_FS is not set
791CONFIG_JFS_FS=m
792# CONFIG_JFS_POSIX_ACL is not set
793# CONFIG_JFS_SECURITY is not set
794# CONFIG_JFS_DEBUG is not set
795# CONFIG_JFS_STATISTICS is not set
796CONFIG_FS_POSIX_ACL=y
797
798#
799# XFS support
800#
801CONFIG_XFS_FS=m
802CONFIG_XFS_EXPORT=y
803# CONFIG_XFS_RT is not set
804# CONFIG_XFS_QUOTA is not set
805# CONFIG_XFS_SECURITY is not set
806# CONFIG_XFS_POSIX_ACL is not set
807# CONFIG_MINIX_FS is not set
808# CONFIG_ROMFS_FS is not set
809# CONFIG_QUOTA is not set
810CONFIG_DNOTIFY=y
811# CONFIG_AUTOFS_FS is not set
812CONFIG_AUTOFS4_FS=y
813
814#
815# CD-ROM/DVD Filesystems
816#
817CONFIG_ISO9660_FS=y
818CONFIG_JOLIET=y
819# CONFIG_ZISOFS is not set
820CONFIG_UDF_FS=m
821CONFIG_UDF_NLS=y
822
823#
824# DOS/FAT/NT Filesystems
825#
826CONFIG_FAT_FS=m
827CONFIG_MSDOS_FS=m
828CONFIG_VFAT_FS=m
829CONFIG_FAT_DEFAULT_CODEPAGE=437
830CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
831# CONFIG_NTFS_FS is not set
832
833#
834# Pseudo filesystems
835#
836CONFIG_PROC_FS=y
837CONFIG_PROC_KCORE=y
838CONFIG_SYSFS=y
839# CONFIG_DEVFS_FS is not set
840# CONFIG_DEVPTS_FS_XATTR is not set
841CONFIG_TMPFS=y
842# CONFIG_TMPFS_XATTR is not set
843# CONFIG_HUGETLBFS is not set
844# CONFIG_HUGETLB_PAGE is not set
845CONFIG_RAMFS=y
846
847#
848# Miscellaneous filesystems
849#
850# CONFIG_ADFS_FS is not set
851# CONFIG_AFFS_FS is not set
852# CONFIG_HFS_FS is not set
853# CONFIG_HFSPLUS_FS is not set
854# CONFIG_BEFS_FS is not set
855# CONFIG_BFS_FS is not set
856# CONFIG_EFS_FS is not set
857# CONFIG_CRAMFS is not set
858# CONFIG_VXFS_FS is not set
859# CONFIG_HPFS_FS is not set
860# CONFIG_QNX4FS_FS is not set
861# CONFIG_SYSV_FS is not set
862CONFIG_UFS_FS=m
863# CONFIG_UFS_FS_WRITE is not set
864
865#
866# Network File Systems
867#
868CONFIG_NFS_FS=m
869CONFIG_NFS_V3=y
870CONFIG_NFS_V4=y
871CONFIG_NFS_DIRECTIO=y
872CONFIG_NFSD=m
873CONFIG_NFSD_V3=y
874CONFIG_NFSD_V4=y
875CONFIG_NFSD_TCP=y
876CONFIG_LOCKD=m
877CONFIG_LOCKD_V4=y
878CONFIG_EXPORTFS=m
879CONFIG_SUNRPC=m
880CONFIG_SUNRPC_GSS=m
881CONFIG_RPCSEC_GSS_KRB5=m
882CONFIG_RPCSEC_GSS_SPKM3=m
883CONFIG_SMB_FS=m
884CONFIG_SMB_NLS_DEFAULT=y
885CONFIG_SMB_NLS_REMOTE="cp437"
886CONFIG_CIFS=m
887# CONFIG_CIFS_STATS is not set
888# CONFIG_CIFS_XATTR is not set
889# CONFIG_CIFS_EXPERIMENTAL is not set
890# CONFIG_NCP_FS is not set
891# CONFIG_CODA_FS is not set
892# CONFIG_AFS_FS is not set
893
894#
895# Partition Types
896#
897# CONFIG_PARTITION_ADVANCED is not set
898CONFIG_MSDOS_PARTITION=y
899
900#
901# Native Language Support
902#
903CONFIG_NLS=y
904CONFIG_NLS_DEFAULT="iso8859-1"
905CONFIG_NLS_CODEPAGE_437=m
906# CONFIG_NLS_CODEPAGE_737 is not set
907# CONFIG_NLS_CODEPAGE_775 is not set
908CONFIG_NLS_CODEPAGE_850=m
909CONFIG_NLS_CODEPAGE_852=m
910# CONFIG_NLS_CODEPAGE_855 is not set
911# CONFIG_NLS_CODEPAGE_857 is not set
912# CONFIG_NLS_CODEPAGE_860 is not set
913# CONFIG_NLS_CODEPAGE_861 is not set
914# CONFIG_NLS_CODEPAGE_862 is not set
915CONFIG_NLS_CODEPAGE_863=m
916# CONFIG_NLS_CODEPAGE_864 is not set
917CONFIG_NLS_CODEPAGE_865=m
918# CONFIG_NLS_CODEPAGE_866 is not set
919# CONFIG_NLS_CODEPAGE_869 is not set
920# CONFIG_NLS_CODEPAGE_936 is not set
921# CONFIG_NLS_CODEPAGE_950 is not set
922# CONFIG_NLS_CODEPAGE_932 is not set
923# CONFIG_NLS_CODEPAGE_949 is not set
924# CONFIG_NLS_CODEPAGE_874 is not set
925# CONFIG_NLS_ISO8859_8 is not set
926# CONFIG_NLS_CODEPAGE_1250 is not set
927# CONFIG_NLS_CODEPAGE_1251 is not set
928# CONFIG_NLS_ASCII is not set
929CONFIG_NLS_ISO8859_1=m
930CONFIG_NLS_ISO8859_2=m
931CONFIG_NLS_ISO8859_3=m
932CONFIG_NLS_ISO8859_4=m
933# CONFIG_NLS_ISO8859_5 is not set
934# CONFIG_NLS_ISO8859_6 is not set
935# CONFIG_NLS_ISO8859_7 is not set
936# CONFIG_NLS_ISO8859_9 is not set
937# CONFIG_NLS_ISO8859_13 is not set
938# CONFIG_NLS_ISO8859_14 is not set
939CONFIG_NLS_ISO8859_15=m
940# CONFIG_NLS_KOI8_R is not set
941# CONFIG_NLS_KOI8_U is not set
942CONFIG_NLS_UTF8=m
943
944#
945# Profiling support
946#
947CONFIG_PROFILING=y
948CONFIG_OPROFILE=m
949
950#
951# Kernel hacking
952#
953CONFIG_DEBUG_KERNEL=y
954CONFIG_MAGIC_SYSRQ=y
955# CONFIG_SCHEDSTATS is not set
956# CONFIG_DEBUG_SLAB is not set
957# CONFIG_DEBUG_SPINLOCK is not set
958# CONFIG_DEBUG_KOBJECT is not set
959# CONFIG_DEBUG_INFO is not set
960# CONFIG_DEBUG_IOREMAP is not set
961# CONFIG_DEBUG_FS is not set
962# CONFIG_DEBUG_RWLOCK is not set
963
964#
965# Security options
966#
967CONFIG_KEYS=y
968CONFIG_KEYS_DEBUG_PROC_KEYS=y
969# CONFIG_SECURITY is not set
970
971#
972# Cryptographic options
973#
974CONFIG_CRYPTO=y
975CONFIG_CRYPTO_HMAC=y
976CONFIG_CRYPTO_NULL=m
977CONFIG_CRYPTO_MD4=m
978CONFIG_CRYPTO_MD5=m
979CONFIG_CRYPTO_SHA1=m
980CONFIG_CRYPTO_SHA256=m
981CONFIG_CRYPTO_SHA512=m
982CONFIG_CRYPTO_WP512=m
983CONFIG_CRYPTO_DES=m
984CONFIG_CRYPTO_BLOWFISH=m
985CONFIG_CRYPTO_TWOFISH=m
986CONFIG_CRYPTO_SERPENT=m
987CONFIG_CRYPTO_AES=m
988CONFIG_CRYPTO_CAST5=m
989CONFIG_CRYPTO_CAST6=m
990CONFIG_CRYPTO_TEA=m
991CONFIG_CRYPTO_ARC4=m
992CONFIG_CRYPTO_KHAZAD=m
993CONFIG_CRYPTO_ANUBIS=m
994CONFIG_CRYPTO_DEFLATE=m
995CONFIG_CRYPTO_MICHAEL_MIC=m
996CONFIG_CRYPTO_CRC32C=m
997CONFIG_CRYPTO_TEST=m
998
999#
1000# Hardware crypto devices
1001#
1002
1003#
1004# Library routines
1005#
1006CONFIG_CRC_CCITT=m
1007CONFIG_CRC32=y
1008CONFIG_LIBCRC32C=m
1009CONFIG_ZLIB_INFLATE=m
1010CONFIG_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 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-pa5
4# Wed Jan 5 13:35:54 2005
5#
6CONFIG_PARISC=y
7CONFIG_MMU=y
8CONFIG_STACK_GROWSUP=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14# CONFIG_EXPERIMENTAL is not set
15CONFIG_CLEAN_COMPILE=y
16CONFIG_BROKEN_ON_SMP=y
17
18#
19# General setup
20#
21CONFIG_LOCALVERSION=""
22CONFIG_SWAP=y
23CONFIG_SYSVIPC=y
24# CONFIG_BSD_PROCESS_ACCT is not set
25CONFIG_SYSCTL=y
26# CONFIG_AUDIT is not set
27CONFIG_LOG_BUF_SHIFT=16
28# CONFIG_HOTPLUG is not set
29CONFIG_KOBJECT_UEVENT=y
30# CONFIG_IKCONFIG is not set
31# CONFIG_EMBEDDED is not set
32CONFIG_KALLSYMS=y
33# CONFIG_KALLSYMS_ALL is not set
34# CONFIG_KALLSYMS_EXTRA_PASS is not set
35CONFIG_FUTEX=y
36CONFIG_EPOLL=y
37# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
38CONFIG_SHMEM=y
39CONFIG_CC_ALIGN_FUNCTIONS=0
40CONFIG_CC_ALIGN_LABELS=0
41CONFIG_CC_ALIGN_LOOPS=0
42CONFIG_CC_ALIGN_JUMPS=0
43# CONFIG_TINY_SHMEM is not set
44
45#
46# Loadable module support
47#
48CONFIG_MODULES=y
49# CONFIG_MODULE_UNLOAD is not set
50CONFIG_OBSOLETE_MODPARM=y
51# CONFIG_MODULE_SRCVERSION_ALL is not set
52# CONFIG_KMOD is not set
53
54#
55# Processor type and features
56#
57# CONFIG_PA7000 is not set
58CONFIG_PA7100LC=y
59# CONFIG_PA7200 is not set
60# CONFIG_PA7300LC is not set
61# CONFIG_PA8X00 is not set
62CONFIG_PA11=y
63# CONFIG_64BIT is not set
64# CONFIG_SMP is not set
65# CONFIG_PREEMPT is not set
66# CONFIG_HPUX is not set
67
68#
69# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
70#
71CONFIG_GSC=y
72# CONFIG_HPPB is not set
73# CONFIG_IOMMU_CCIO is not set
74CONFIG_GSC_LASI=y
75CONFIG_GSC_WAX=y
76CONFIG_EISA=y
77CONFIG_EISA_NAMES=y
78CONFIG_ISA=y
79CONFIG_PCI=y
80CONFIG_PCI_LEGACY_PROC=y
81CONFIG_PCI_NAMES=y
82CONFIG_GSC_DINO=y
83# CONFIG_PCI_LBA is not set
84CONFIG_CHASSIS_LCD_LED=y
85# CONFIG_PDC_CHASSIS is not set
86
87#
88# Executable file formats
89#
90CONFIG_BINFMT_ELF=y
91# CONFIG_BINFMT_MISC is not set
92
93#
94# Device Drivers
95#
96
97#
98# Generic Driver Options
99#
100CONFIG_STANDALONE=y
101# CONFIG_PREVENT_FIRMWARE_BUILD is not set
102# CONFIG_DEBUG_DRIVER is not set
103
104#
105# Memory Technology Devices (MTD)
106#
107# CONFIG_MTD is not set
108
109#
110# Parallel port support
111#
112CONFIG_PARPORT=y
113CONFIG_PARPORT_PC=y
114CONFIG_PARPORT_PC_CML1=y
115# CONFIG_PARPORT_SERIAL is not set
116CONFIG_PARPORT_GSC=y
117# CONFIG_PARPORT_OTHER is not set
118# CONFIG_PARPORT_1284 is not set
119
120#
121# Plug and Play support
122#
123# CONFIG_PNP is not set
124
125#
126# Block devices
127#
128# CONFIG_BLK_DEV_FD is not set
129# CONFIG_BLK_DEV_XD is not set
130# CONFIG_PARIDE is not set
131# CONFIG_BLK_CPQ_DA is not set
132# CONFIG_BLK_CPQ_CISS_DA is not set
133# CONFIG_BLK_DEV_DAC960 is not set
134CONFIG_BLK_DEV_LOOP=y
135CONFIG_BLK_DEV_CRYPTOLOOP=y
136# CONFIG_BLK_DEV_NBD is not set
137# CONFIG_BLK_DEV_SX8 is not set
138# CONFIG_BLK_DEV_RAM is not set
139CONFIG_BLK_DEV_RAM_COUNT=16
140CONFIG_INITRAMFS_SOURCE=""
141CONFIG_CDROM_PKTCDVD=m
142CONFIG_CDROM_PKTCDVD_BUFFERS=8
143# CONFIG_CDROM_PKTCDVD_WCACHE is not set
144
145#
146# IO Schedulers
147#
148CONFIG_IOSCHED_NOOP=y
149CONFIG_IOSCHED_AS=y
150CONFIG_IOSCHED_DEADLINE=y
151CONFIG_IOSCHED_CFQ=y
152
153#
154# ATA/ATAPI/MFM/RLL support
155#
156# CONFIG_IDE is not set
157
158#
159# SCSI device support
160#
161CONFIG_SCSI=y
162CONFIG_SCSI_PROC_FS=y
163
164#
165# SCSI support type (disk, tape, CD-ROM)
166#
167CONFIG_BLK_DEV_SD=y
168CONFIG_CHR_DEV_ST=y
169# CONFIG_CHR_DEV_OSST is not set
170CONFIG_BLK_DEV_SR=y
171# CONFIG_BLK_DEV_SR_VENDOR is not set
172CONFIG_CHR_DEV_SG=y
173
174#
175# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
176#
177# CONFIG_SCSI_MULTI_LUN is not set
178# CONFIG_SCSI_CONSTANTS is not set
179# CONFIG_SCSI_LOGGING is not set
180
181#
182# SCSI Transport Attributes
183#
184CONFIG_SCSI_SPI_ATTRS=y
185# CONFIG_SCSI_FC_ATTRS is not set
186
187#
188# SCSI low-level drivers
189#
190# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
191# CONFIG_SCSI_3W_9XXX is not set
192# CONFIG_SCSI_7000FASST is not set
193# CONFIG_SCSI_ACARD is not set
194# CONFIG_SCSI_AHA152X is not set
195# CONFIG_SCSI_AHA1542 is not set
196# CONFIG_SCSI_AHA1740 is not set
197# CONFIG_SCSI_AACRAID is not set
198# CONFIG_SCSI_AIC7XXX is not set
199# CONFIG_SCSI_AIC7XXX_OLD is not set
200# CONFIG_SCSI_AIC79XX is not set
201# CONFIG_SCSI_DPT_I2O is not set
202# CONFIG_SCSI_IN2000 is not set
203# CONFIG_MEGARAID_NEWGEN is not set
204# CONFIG_MEGARAID_LEGACY is not set
205# CONFIG_SCSI_SATA is not set
206# CONFIG_SCSI_BUSLOGIC is not set
207# CONFIG_SCSI_DMX3191D is not set
208# CONFIG_SCSI_DTC3280 is not set
209# CONFIG_SCSI_EATA is not set
210# CONFIG_SCSI_EATA_PIO is not set
211# CONFIG_SCSI_FUTURE_DOMAIN is not set
212# CONFIG_SCSI_GDTH is not set
213# CONFIG_SCSI_GENERIC_NCR5380 is not set
214# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
215# CONFIG_SCSI_IPS is not set
216# CONFIG_SCSI_INITIO is not set
217# CONFIG_SCSI_INIA100 is not set
218# CONFIG_SCSI_PPA is not set
219# CONFIG_SCSI_IMM is not set
220# CONFIG_SCSI_NCR53C406A is not set
221CONFIG_SCSI_LASI700=y
222CONFIG_53C700_MEM_MAPPED=y
223CONFIG_53C700_LE_ON_BE=y
224CONFIG_SCSI_SYM53C8XX_2=y
225CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
226CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
227CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
228# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
229# CONFIG_SCSI_IPR is not set
230# CONFIG_SCSI_ZALON is not set
231# CONFIG_SCSI_PAS16 is not set
232# CONFIG_SCSI_PSI240I is not set
233# CONFIG_SCSI_QLOGIC_FAS is not set
234# CONFIG_SCSI_QLOGIC_ISP is not set
235# CONFIG_SCSI_QLOGIC_FC is not set
236# CONFIG_SCSI_QLOGIC_1280 is not set
237CONFIG_SCSI_QLA2XXX=y
238# CONFIG_SCSI_QLA21XX is not set
239# CONFIG_SCSI_QLA22XX is not set
240# CONFIG_SCSI_QLA2300 is not set
241# CONFIG_SCSI_QLA2322 is not set
242# CONFIG_SCSI_QLA6312 is not set
243# CONFIG_SCSI_QLA6322 is not set
244# CONFIG_SCSI_SIM710 is not set
245# CONFIG_SCSI_SYM53C416 is not set
246# CONFIG_SCSI_DC390T is not set
247# CONFIG_SCSI_T128 is not set
248# CONFIG_SCSI_U14_34F is not set
249# CONFIG_SCSI_NSP32 is not set
250# CONFIG_SCSI_DEBUG is not set
251
252#
253# Old CD-ROM drivers (not SCSI, not IDE)
254#
255# CONFIG_CD_NO_IDESCSI is not set
256
257#
258# Multi-device support (RAID and LVM)
259#
260CONFIG_MD=y
261CONFIG_BLK_DEV_MD=y
262CONFIG_MD_LINEAR=y
263CONFIG_MD_RAID0=y
264CONFIG_MD_RAID1=y
265CONFIG_MD_RAID5=y
266# CONFIG_MD_MULTIPATH is not set
267# CONFIG_MD_FAULTY is not set
268# CONFIG_BLK_DEV_DM is not set
269
270#
271# Fusion MPT device support
272#
273# CONFIG_FUSION is not set
274
275#
276# IEEE 1394 (FireWire) support
277#
278# CONFIG_IEEE1394 is not set
279
280#
281# I2O device support
282#
283# CONFIG_I2O is not set
284
285#
286# Networking support
287#
288CONFIG_NET=y
289
290#
291# Networking options
292#
293CONFIG_PACKET=y
294CONFIG_PACKET_MMAP=y
295CONFIG_NETLINK_DEV=y
296CONFIG_UNIX=y
297# CONFIG_NET_KEY is not set
298CONFIG_INET=y
299CONFIG_IP_MULTICAST=y
300# CONFIG_IP_ADVANCED_ROUTER is not set
301CONFIG_IP_PNP=y
302# CONFIG_IP_PNP_DHCP is not set
303CONFIG_IP_PNP_BOOTP=y
304# CONFIG_IP_PNP_RARP is not set
305# CONFIG_NET_IPIP is not set
306# CONFIG_NET_IPGRE is not set
307# CONFIG_IP_MROUTE is not set
308# CONFIG_SYN_COOKIES is not set
309# CONFIG_INET_AH is not set
310# CONFIG_INET_ESP is not set
311# CONFIG_INET_IPCOMP is not set
312# CONFIG_INET_TUNNEL is not set
313CONFIG_IP_TCPDIAG=y
314# CONFIG_IP_TCPDIAG_IPV6 is not set
315# CONFIG_NETFILTER is not set
316# CONFIG_BRIDGE is not set
317# CONFIG_VLAN_8021Q is not set
318# CONFIG_DECNET is not set
319# CONFIG_LLC2 is not set
320# CONFIG_IPX is not set
321# CONFIG_ATALK is not set
322
323#
324# QoS and/or fair queueing
325#
326# CONFIG_NET_SCHED is not set
327# CONFIG_NET_CLS_ROUTE is not set
328
329#
330# Network testing
331#
332# CONFIG_NET_PKTGEN is not set
333# CONFIG_NETPOLL is not set
334# CONFIG_NET_POLL_CONTROLLER is not set
335# CONFIG_HAMRADIO is not set
336# CONFIG_IRDA is not set
337# CONFIG_BT is not set
338CONFIG_NETDEVICES=y
339# CONFIG_DUMMY is not set
340# CONFIG_BONDING is not set
341# CONFIG_EQUALIZER is not set
342# CONFIG_TUN is not set
343
344#
345# ARCnet devices
346#
347# CONFIG_ARCNET is not set
348
349#
350# Ethernet (10 or 100Mbit)
351#
352CONFIG_NET_ETHERNET=y
353# CONFIG_MII is not set
354# CONFIG_LASI_82596 is not set
355# CONFIG_HAPPYMEAL is not set
356# CONFIG_SUNGEM is not set
357# CONFIG_NET_VENDOR_3COM is not set
358# CONFIG_LANCE is not set
359# CONFIG_NET_VENDOR_SMC is not set
360# CONFIG_NET_VENDOR_RACAL is not set
361
362#
363# Tulip family network device support
364#
365CONFIG_NET_TULIP=y
366CONFIG_TULIP=y
367# CONFIG_TULIP_MMIO is not set
368# CONFIG_TULIP_NAPI is not set
369# CONFIG_DE4X5 is not set
370# CONFIG_WINBOND_840 is not set
371# CONFIG_DM9102 is not set
372# CONFIG_DEPCA is not set
373# CONFIG_HP100 is not set
374# CONFIG_NET_ISA is not set
375# CONFIG_NET_PCI is not set
376# CONFIG_NET_POCKET is not set
377
378#
379# Ethernet (1000 Mbit)
380#
381# CONFIG_ACENIC is not set
382# CONFIG_DL2K is not set
383# CONFIG_E1000 is not set
384# CONFIG_NS83820 is not set
385# CONFIG_HAMACHI is not set
386# CONFIG_R8169 is not set
387# CONFIG_SK98LIN is not set
388# CONFIG_TIGON3 is not set
389
390#
391# Ethernet (10000 Mbit)
392#
393# CONFIG_IXGB is not set
394# CONFIG_S2IO is not set
395
396#
397# Token Ring devices
398#
399# CONFIG_TR is not set
400
401#
402# Wireless LAN (non-hamradio)
403#
404CONFIG_NET_RADIO=y
405
406#
407# Obsolete Wireless cards support (pre-802.11)
408#
409# CONFIG_STRIP is not set
410# CONFIG_ARLAN is not set
411# CONFIG_WAVELAN is not set
412
413#
414# Wireless 802.11b ISA/PCI cards support
415#
416# CONFIG_AIRO is not set
417# CONFIG_HERMES is not set
418
419#
420# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
421#
422CONFIG_NET_WIRELESS=y
423
424#
425# Wan interfaces
426#
427# CONFIG_WAN is not set
428# CONFIG_FDDI is not set
429# CONFIG_PLIP is not set
430CONFIG_PPP=y
431# CONFIG_PPP_FILTER is not set
432# CONFIG_PPP_ASYNC is not set
433# CONFIG_PPP_SYNC_TTY is not set
434# CONFIG_PPP_DEFLATE is not set
435# CONFIG_PPP_BSDCOMP is not set
436# CONFIG_SLIP is not set
437# CONFIG_NET_FC is not set
438
439#
440# ISDN subsystem
441#
442# CONFIG_ISDN is not set
443
444#
445# Telephony Support
446#
447# CONFIG_PHONE is not set
448
449#
450# Input device support
451#
452CONFIG_INPUT=y
453
454#
455# Userland interfaces
456#
457CONFIG_INPUT_MOUSEDEV=y
458CONFIG_INPUT_MOUSEDEV_PSAUX=y
459CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
460CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
461# CONFIG_INPUT_JOYDEV is not set
462# CONFIG_INPUT_TSDEV is not set
463CONFIG_INPUT_EVDEV=y
464# CONFIG_INPUT_EVBUG is not set
465
466#
467# Input I/O drivers
468#
469# CONFIG_GAMEPORT is not set
470CONFIG_SOUND_GAMEPORT=y
471CONFIG_SERIO=y
472# CONFIG_SERIO_SERPORT is not set
473# CONFIG_SERIO_PARKBD is not set
474CONFIG_SERIO_GSCPS2=y
475# CONFIG_HP_SDC is not set
476# CONFIG_SERIO_PCIPS2 is not set
477# CONFIG_SERIO_RAW is not set
478
479#
480# Input Device Drivers
481#
482CONFIG_INPUT_KEYBOARD=y
483# CONFIG_KEYBOARD_ATKBD is not set
484# CONFIG_KEYBOARD_SUNKBD is not set
485# CONFIG_KEYBOARD_LKKBD is not set
486# CONFIG_KEYBOARD_XTKBD is not set
487# CONFIG_KEYBOARD_NEWTON is not set
488# CONFIG_KEYBOARD_HIL_OLD is not set
489# CONFIG_KEYBOARD_HIL is not set
490CONFIG_INPUT_MOUSE=y
491# CONFIG_MOUSE_PS2 is not set
492# CONFIG_MOUSE_SERIAL is not set
493# CONFIG_MOUSE_INPORT is not set
494# CONFIG_MOUSE_LOGIBM is not set
495# CONFIG_MOUSE_PC110PAD is not set
496# CONFIG_MOUSE_VSXXXAA is not set
497# CONFIG_MOUSE_HIL is not set
498# CONFIG_INPUT_JOYSTICK is not set
499# CONFIG_INPUT_TOUCHSCREEN is not set
500CONFIG_INPUT_MISC=y
501# CONFIG_INPUT_UINPUT is not set
502# CONFIG_HP_SDC_RTC is not set
503
504#
505# Character devices
506#
507CONFIG_VT=y
508CONFIG_VT_CONSOLE=y
509CONFIG_HW_CONSOLE=y
510# CONFIG_SERIAL_NONSTANDARD is not set
511
512#
513# Serial drivers
514#
515CONFIG_SERIAL_8250=y
516CONFIG_SERIAL_8250_CONSOLE=y
517CONFIG_SERIAL_8250_NR_UARTS=4
518CONFIG_SERIAL_8250_EXTENDED=y
519CONFIG_SERIAL_8250_MANY_PORTS=y
520CONFIG_SERIAL_8250_SHARE_IRQ=y
521# CONFIG_SERIAL_8250_DETECT_IRQ is not set
522# CONFIG_SERIAL_8250_MULTIPORT is not set
523# CONFIG_SERIAL_8250_RSA is not set
524
525#
526# Non-8250 serial port support
527#
528# CONFIG_SERIAL_MUX is not set
529# CONFIG_PDC_CONSOLE is not set
530CONFIG_SERIAL_CORE=y
531CONFIG_SERIAL_CORE_CONSOLE=y
532CONFIG_UNIX98_PTYS=y
533CONFIG_LEGACY_PTYS=y
534CONFIG_LEGACY_PTY_COUNT=256
535CONFIG_PRINTER=y
536# CONFIG_LP_CONSOLE is not set
537# CONFIG_PPDEV is not set
538# CONFIG_TIPAR is not set
539
540#
541# IPMI
542#
543# CONFIG_IPMI_HANDLER is not set
544
545#
546# Watchdog Cards
547#
548# CONFIG_WATCHDOG is not set
549CONFIG_GEN_RTC=y
550# CONFIG_GEN_RTC_X is not set
551# CONFIG_DTLK is not set
552# CONFIG_R3964 is not set
553# CONFIG_APPLICOM is not set
554
555#
556# Ftape, the floppy tape device driver
557#
558# CONFIG_AGP is not set
559# CONFIG_DRM is not set
560# CONFIG_RAW_DRIVER is not set
561
562#
563# I2C support
564#
565# CONFIG_I2C is not set
566
567#
568# Dallas's 1-wire bus
569#
570# CONFIG_W1 is not set
571
572#
573# Misc devices
574#
575
576#
577# Multimedia devices
578#
579# CONFIG_VIDEO_DEV is not set
580
581#
582# Digital Video Broadcasting Devices
583#
584# CONFIG_DVB is not set
585
586#
587# Graphics support
588#
589CONFIG_FB=y
590# CONFIG_FB_MODE_HELPERS is not set
591# CONFIG_FB_TILEBLITTING is not set
592# CONFIG_FB_CIRRUS is not set
593# CONFIG_FB_PM2 is not set
594# CONFIG_FB_CYBER2000 is not set
595# CONFIG_FB_ASILIANT is not set
596# CONFIG_FB_IMSTT is not set
597CONFIG_FB_STI=y
598# CONFIG_FB_RIVA is not set
599# CONFIG_FB_MATROX is not set
600# CONFIG_FB_RADEON_OLD is not set
601# CONFIG_FB_RADEON is not set
602# CONFIG_FB_ATY128 is not set
603# CONFIG_FB_ATY is not set
604# CONFIG_FB_SIS is not set
605# CONFIG_FB_NEOMAGIC is not set
606# CONFIG_FB_KYRO is not set
607# CONFIG_FB_3DFX is not set
608# CONFIG_FB_VOODOO1 is not set
609# CONFIG_FB_TRIDENT is not set
610# CONFIG_FB_VIRTUAL is not set
611
612#
613# Console display driver support
614#
615# CONFIG_MDA_CONSOLE is not set
616CONFIG_STI_CONSOLE=y
617CONFIG_DUMMY_CONSOLE_COLUMNS=160
618CONFIG_DUMMY_CONSOLE_ROWS=64
619CONFIG_DUMMY_CONSOLE=y
620CONFIG_FRAMEBUFFER_CONSOLE=y
621# CONFIG_FONTS is not set
622CONFIG_FONT_8x8=y
623CONFIG_FONT_8x16=y
624
625#
626# Logo configuration
627#
628CONFIG_LOGO=y
629CONFIG_LOGO_LINUX_MONO=y
630CONFIG_LOGO_LINUX_VGA16=y
631CONFIG_LOGO_LINUX_CLUT224=y
632CONFIG_LOGO_PARISC_CLUT224=y
633
634#
635# Sound
636#
637# CONFIG_SOUND is not set
638
639#
640# USB support
641#
642# CONFIG_USB is not set
643CONFIG_USB_ARCH_HAS_HCD=y
644CONFIG_USB_ARCH_HAS_OHCI=y
645
646#
647# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
648#
649
650#
651# USB Gadget Support
652#
653# CONFIG_USB_GADGET is not set
654
655#
656# MMC/SD Card support
657#
658# CONFIG_MMC is not set
659
660#
661# File systems
662#
663CONFIG_EXT2_FS=y
664# CONFIG_EXT2_FS_XATTR is not set
665CONFIG_EXT3_FS=y
666# CONFIG_EXT3_FS_XATTR is not set
667CONFIG_JBD=y
668# CONFIG_JBD_DEBUG is not set
669# CONFIG_REISERFS_FS is not set
670# CONFIG_JFS_FS is not set
671# CONFIG_XFS_FS is not set
672# CONFIG_MINIX_FS is not set
673# CONFIG_ROMFS_FS is not set
674# CONFIG_QUOTA is not set
675CONFIG_DNOTIFY=y
676# CONFIG_AUTOFS_FS is not set
677CONFIG_AUTOFS4_FS=y
678
679#
680# CD-ROM/DVD Filesystems
681#
682CONFIG_ISO9660_FS=y
683CONFIG_JOLIET=y
684# CONFIG_ZISOFS is not set
685# CONFIG_UDF_FS is not set
686
687#
688# DOS/FAT/NT Filesystems
689#
690# CONFIG_MSDOS_FS is not set
691# CONFIG_VFAT_FS is not set
692# CONFIG_NTFS_FS is not set
693
694#
695# Pseudo filesystems
696#
697CONFIG_PROC_FS=y
698CONFIG_PROC_KCORE=y
699CONFIG_SYSFS=y
700# CONFIG_DEVPTS_FS_XATTR is not set
701CONFIG_TMPFS=y
702# CONFIG_TMPFS_XATTR is not set
703# CONFIG_HUGETLB_PAGE is not set
704CONFIG_RAMFS=y
705
706#
707# Miscellaneous filesystems
708#
709# CONFIG_HFSPLUS_FS is not set
710# CONFIG_CRAMFS is not set
711# CONFIG_VXFS_FS is not set
712# CONFIG_HPFS_FS is not set
713# CONFIG_QNX4FS_FS is not set
714# CONFIG_SYSV_FS is not set
715# CONFIG_UFS_FS is not set
716
717#
718# Network File Systems
719#
720CONFIG_NFS_FS=y
721CONFIG_NFS_V3=y
722CONFIG_NFSD=y
723CONFIG_NFSD_V3=y
724CONFIG_NFSD_TCP=y
725CONFIG_ROOT_NFS=y
726CONFIG_LOCKD=y
727CONFIG_LOCKD_V4=y
728CONFIG_EXPORTFS=y
729CONFIG_SUNRPC=y
730# CONFIG_SMB_FS is not set
731# CONFIG_CIFS is not set
732# CONFIG_NCP_FS is not set
733# CONFIG_CODA_FS is not set
734
735#
736# Partition Types
737#
738# CONFIG_PARTITION_ADVANCED is not set
739CONFIG_MSDOS_PARTITION=y
740
741#
742# Native Language Support
743#
744CONFIG_NLS=y
745CONFIG_NLS_DEFAULT="iso8859-1"
746# CONFIG_NLS_CODEPAGE_437 is not set
747# CONFIG_NLS_CODEPAGE_737 is not set
748# CONFIG_NLS_CODEPAGE_775 is not set
749# CONFIG_NLS_CODEPAGE_850 is not set
750# CONFIG_NLS_CODEPAGE_852 is not set
751# CONFIG_NLS_CODEPAGE_855 is not set
752# CONFIG_NLS_CODEPAGE_857 is not set
753# CONFIG_NLS_CODEPAGE_860 is not set
754# CONFIG_NLS_CODEPAGE_861 is not set
755# CONFIG_NLS_CODEPAGE_862 is not set
756# CONFIG_NLS_CODEPAGE_863 is not set
757# CONFIG_NLS_CODEPAGE_864 is not set
758# CONFIG_NLS_CODEPAGE_865 is not set
759# CONFIG_NLS_CODEPAGE_866 is not set
760# CONFIG_NLS_CODEPAGE_869 is not set
761# CONFIG_NLS_CODEPAGE_936 is not set
762# CONFIG_NLS_CODEPAGE_950 is not set
763# CONFIG_NLS_CODEPAGE_932 is not set
764# CONFIG_NLS_CODEPAGE_949 is not set
765# CONFIG_NLS_CODEPAGE_874 is not set
766# CONFIG_NLS_ISO8859_8 is not set
767# CONFIG_NLS_CODEPAGE_1250 is not set
768# CONFIG_NLS_CODEPAGE_1251 is not set
769# CONFIG_NLS_ASCII is not set
770# CONFIG_NLS_ISO8859_1 is not set
771# CONFIG_NLS_ISO8859_2 is not set
772# CONFIG_NLS_ISO8859_3 is not set
773# CONFIG_NLS_ISO8859_4 is not set
774# CONFIG_NLS_ISO8859_5 is not set
775# CONFIG_NLS_ISO8859_6 is not set
776# CONFIG_NLS_ISO8859_7 is not set
777# CONFIG_NLS_ISO8859_9 is not set
778# CONFIG_NLS_ISO8859_13 is not set
779# CONFIG_NLS_ISO8859_14 is not set
780# CONFIG_NLS_ISO8859_15 is not set
781# CONFIG_NLS_KOI8_R is not set
782# CONFIG_NLS_KOI8_U is not set
783# CONFIG_NLS_UTF8 is not set
784
785#
786# Kernel hacking
787#
788CONFIG_DEBUG_KERNEL=y
789CONFIG_MAGIC_SYSRQ=y
790# CONFIG_SCHEDSTATS is not set
791# CONFIG_DEBUG_SLAB is not set
792# CONFIG_DEBUG_SPINLOCK is not set
793# CONFIG_DEBUG_KOBJECT is not set
794# CONFIG_DEBUG_INFO is not set
795
796#
797# Security options
798#
799# CONFIG_KEYS is not set
800CONFIG_SECURITY=y
801# CONFIG_SECURITY_NETWORK is not set
802CONFIG_SECURITY_CAPABILITIES=y
803# CONFIG_SECURITY_SECLVL is not set
804# CONFIG_SECURITY_SELINUX is not set
805
806#
807# Cryptographic options
808#
809CONFIG_CRYPTO=y
810# CONFIG_CRYPTO_HMAC is not set
811# CONFIG_CRYPTO_NULL is not set
812# CONFIG_CRYPTO_MD4 is not set
813# CONFIG_CRYPTO_MD5 is not set
814# CONFIG_CRYPTO_SHA1 is not set
815# CONFIG_CRYPTO_SHA256 is not set
816# CONFIG_CRYPTO_SHA512 is not set
817# CONFIG_CRYPTO_WP512 is not set
818# CONFIG_CRYPTO_DES is not set
819# CONFIG_CRYPTO_BLOWFISH is not set
820# CONFIG_CRYPTO_TWOFISH is not set
821# CONFIG_CRYPTO_SERPENT is not set
822# CONFIG_CRYPTO_AES is not set
823# CONFIG_CRYPTO_CAST5 is not set
824# CONFIG_CRYPTO_CAST6 is not set
825# CONFIG_CRYPTO_TEA is not set
826# CONFIG_CRYPTO_ARC4 is not set
827# CONFIG_CRYPTO_KHAZAD is not set
828# CONFIG_CRYPTO_ANUBIS is not set
829# CONFIG_CRYPTO_DEFLATE is not set
830# CONFIG_CRYPTO_MICHAEL_MIC is not set
831# CONFIG_CRYPTO_CRC32C is not set
832# CONFIG_CRYPTO_TEST is not set
833
834#
835# Library routines
836#
837# CONFIG_CRC_CCITT is not set
838CONFIG_CRC32=y
839# 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 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.10-pa5
4# Wed Jan 5 13:26:49 2005
5#
6CONFIG_PARISC=y
7CONFIG_MMU=y
8CONFIG_STACK_GROWSUP=y
9CONFIG_RWSEM_GENERIC_SPINLOCK=y
10
11#
12# Code maturity level options
13#
14CONFIG_EXPERIMENTAL=y
15# CONFIG_CLEAN_COMPILE is not set
16CONFIG_BROKEN=y
17CONFIG_BROKEN_ON_SMP=y
18
19#
20# General setup
21#
22CONFIG_LOCALVERSION=""
23CONFIG_SWAP=y
24CONFIG_SYSVIPC=y
25# CONFIG_POSIX_MQUEUE is not set
26# CONFIG_BSD_PROCESS_ACCT is not set
27CONFIG_SYSCTL=y
28# CONFIG_AUDIT is not set
29CONFIG_LOG_BUF_SHIFT=16
30CONFIG_HOTPLUG=y
31CONFIG_KOBJECT_UEVENT=y
32CONFIG_IKCONFIG=y
33CONFIG_IKCONFIG_PROC=y
34CONFIG_EMBEDDED=y
35CONFIG_KALLSYMS=y
36CONFIG_KALLSYMS_ALL=y
37# CONFIG_KALLSYMS_EXTRA_PASS is not set
38CONFIG_FUTEX=y
39CONFIG_EPOLL=y
40# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
41CONFIG_SHMEM=y
42CONFIG_CC_ALIGN_FUNCTIONS=0
43CONFIG_CC_ALIGN_LABELS=0
44CONFIG_CC_ALIGN_LOOPS=0
45CONFIG_CC_ALIGN_JUMPS=0
46# CONFIG_TINY_SHMEM is not set
47
48#
49# Loadable module support
50#
51CONFIG_MODULES=y
52CONFIG_MODULE_UNLOAD=y
53CONFIG_MODULE_FORCE_UNLOAD=y
54CONFIG_OBSOLETE_MODPARM=y
55# CONFIG_MODVERSIONS is not set
56# CONFIG_MODULE_SRCVERSION_ALL is not set
57CONFIG_KMOD=y
58
59#
60# Processor type and features
61#
62# CONFIG_PA7000 is not set
63# CONFIG_PA7100LC is not set
64# CONFIG_PA7200 is not set
65# CONFIG_PA7300LC is not set
66CONFIG_PA8X00=y
67CONFIG_PA20=y
68CONFIG_PREFETCH=y
69# CONFIG_PARISC64 is not set
70# CONFIG_64BIT is not set
71# CONFIG_SMP is not set
72# CONFIG_DISCONTIGMEM is not set
73# CONFIG_PREEMPT is not set
74# CONFIG_HPUX is not set
75
76#
77# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
78#
79# CONFIG_GSC is not set
80CONFIG_PCI=y
81CONFIG_PCI_LEGACY_PROC=y
82CONFIG_PCI_NAMES=y
83CONFIG_PCI_LBA=y
84CONFIG_IOSAPIC=y
85CONFIG_IOMMU_SBA=y
86CONFIG_SUPERIO=y
87CONFIG_CHASSIS_LCD_LED=y
88# CONFIG_PDC_CHASSIS is not set
89
90#
91# PCCARD (PCMCIA/CardBus) support
92#
93# CONFIG_PCCARD is not set
94
95#
96# PC-card bridges
97#
98
99#
100# PCI Hotplug Support
101#
102# CONFIG_HOTPLUG_PCI is not set
103
104#
105# Executable file formats
106#
107CONFIG_BINFMT_ELF=y
108# CONFIG_BINFMT_MISC is not set
109
110#
111# Device Drivers
112#
113
114#
115# Generic Driver Options
116#
117# CONFIG_STANDALONE is not set
118# CONFIG_PREVENT_FIRMWARE_BUILD is not set
119CONFIG_FW_LOADER=y
120# CONFIG_DEBUG_DRIVER is not set
121
122#
123# Memory Technology Devices (MTD)
124#
125# CONFIG_MTD is not set
126
127#
128# Parallel port support
129#
130# CONFIG_PARPORT is not set
131
132#
133# Plug and Play support
134#
135
136#
137# Block devices
138#
139# CONFIG_BLK_DEV_FD is not set
140# CONFIG_BLK_CPQ_DA is not set
141# CONFIG_BLK_CPQ_CISS_DA is not set
142# CONFIG_BLK_DEV_DAC960 is not set
143CONFIG_BLK_DEV_UMEM=m
144CONFIG_BLK_DEV_LOOP=y
145# CONFIG_BLK_DEV_CRYPTOLOOP is not set
146# CONFIG_BLK_DEV_NBD is not set
147# CONFIG_BLK_DEV_SX8 is not set
148# CONFIG_BLK_DEV_UB is not set
149# CONFIG_BLK_DEV_RAM is not set
150CONFIG_BLK_DEV_RAM_COUNT=16
151CONFIG_INITRAMFS_SOURCE=""
152# CONFIG_CDROM_PKTCDVD is not set
153
154#
155# IO Schedulers
156#
157CONFIG_IOSCHED_NOOP=y
158CONFIG_IOSCHED_AS=y
159CONFIG_IOSCHED_DEADLINE=y
160CONFIG_IOSCHED_CFQ=y
161
162#
163# ATA/ATAPI/MFM/RLL support
164#
165CONFIG_IDE=y
166CONFIG_BLK_DEV_IDE=y
167
168#
169# Please see Documentation/ide.txt for help/info on IDE drives
170#
171# CONFIG_BLK_DEV_IDE_SATA is not set
172CONFIG_BLK_DEV_IDEDISK=m
173# CONFIG_IDEDISK_MULTI_MODE is not set
174CONFIG_BLK_DEV_IDECD=y
175# CONFIG_BLK_DEV_IDETAPE is not set
176# CONFIG_BLK_DEV_IDEFLOPPY is not set
177CONFIG_BLK_DEV_IDESCSI=y
178# CONFIG_IDE_TASK_IOCTL is not set
179
180#
181# IDE chipset support/bugfixes
182#
183CONFIG_IDE_GENERIC=y
184CONFIG_BLK_DEV_IDEPCI=y
185CONFIG_IDEPCI_SHARE_IRQ=y
186# CONFIG_BLK_DEV_OFFBOARD is not set
187# CONFIG_BLK_DEV_GENERIC is not set
188# CONFIG_BLK_DEV_OPTI621 is not set
189CONFIG_BLK_DEV_IDEDMA_PCI=y
190# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
191# CONFIG_IDEDMA_PCI_AUTO is not set
192# CONFIG_BLK_DEV_AEC62XX is not set
193# CONFIG_BLK_DEV_ALI15X3 is not set
194# CONFIG_BLK_DEV_AMD74XX is not set
195# CONFIG_BLK_DEV_CMD64X is not set
196# CONFIG_BLK_DEV_TRIFLEX is not set
197# CONFIG_BLK_DEV_CY82C693 is not set
198# CONFIG_BLK_DEV_CS5520 is not set
199# CONFIG_BLK_DEV_CS5530 is not set
200# CONFIG_BLK_DEV_HPT34X is not set
201# CONFIG_BLK_DEV_HPT366 is not set
202# CONFIG_BLK_DEV_SC1200 is not set
203# CONFIG_BLK_DEV_PIIX is not set
204CONFIG_BLK_DEV_NS87415=y
205# CONFIG_BLK_DEV_PDC202XX_OLD is not set
206# CONFIG_BLK_DEV_PDC202XX_NEW is not set
207# CONFIG_BLK_DEV_SVWKS is not set
208CONFIG_BLK_DEV_SIIMAGE=m
209# CONFIG_BLK_DEV_SLC90E66 is not set
210# CONFIG_BLK_DEV_TRM290 is not set
211# CONFIG_BLK_DEV_VIA82CXXX is not set
212# CONFIG_IDE_ARM is not set
213CONFIG_BLK_DEV_IDEDMA=y
214# CONFIG_IDEDMA_IVB is not set
215# CONFIG_IDEDMA_AUTO is not set
216# CONFIG_BLK_DEV_HD is not set
217
218#
219# SCSI device support
220#
221CONFIG_SCSI=y
222CONFIG_SCSI_PROC_FS=y
223
224#
225# SCSI support type (disk, tape, CD-ROM)
226#
227CONFIG_BLK_DEV_SD=y
228CONFIG_CHR_DEV_ST=y
229# CONFIG_CHR_DEV_OSST is not set
230CONFIG_BLK_DEV_SR=y
231# CONFIG_BLK_DEV_SR_VENDOR is not set
232CONFIG_CHR_DEV_SG=y
233
234#
235# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
236#
237CONFIG_SCSI_MULTI_LUN=y
238# CONFIG_SCSI_CONSTANTS is not set
239# CONFIG_SCSI_LOGGING is not set
240
241#
242# SCSI Transport Attributes
243#
244CONFIG_SCSI_SPI_ATTRS=y
245CONFIG_SCSI_FC_ATTRS=m
246
247#
248# SCSI low-level drivers
249#
250# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
251# CONFIG_SCSI_3W_9XXX is not set
252# CONFIG_SCSI_ACARD is not set
253# CONFIG_SCSI_AACRAID is not set
254# CONFIG_SCSI_AIC7XXX is not set
255# CONFIG_SCSI_AIC7XXX_OLD is not set
256# CONFIG_SCSI_AIC79XX is not set
257# CONFIG_SCSI_DPT_I2O is not set
258# CONFIG_SCSI_ADVANSYS is not set
259# CONFIG_MEGARAID_NEWGEN is not set
260# CONFIG_MEGARAID_LEGACY is not set
261CONFIG_SCSI_SATA=y
262# CONFIG_SCSI_SATA_AHCI is not set
263# CONFIG_SCSI_SATA_SVW is not set
264CONFIG_SCSI_ATA_PIIX=m
265# CONFIG_SCSI_SATA_NV is not set
266CONFIG_SCSI_SATA_PROMISE=m
267# CONFIG_SCSI_SATA_SX4 is not set
268CONFIG_SCSI_SATA_SIL=m
269# CONFIG_SCSI_SATA_SIS is not set
270# CONFIG_SCSI_SATA_ULI is not set
271CONFIG_SCSI_SATA_VIA=m
272# CONFIG_SCSI_SATA_VITESSE is not set
273# CONFIG_SCSI_BUSLOGIC is not set
274# CONFIG_SCSI_CPQFCTS is not set
275# CONFIG_SCSI_DMX3191D is not set
276# CONFIG_SCSI_EATA is not set
277# CONFIG_SCSI_EATA_PIO is not set
278# CONFIG_SCSI_FUTURE_DOMAIN is not set
279# CONFIG_SCSI_GDTH is not set
280# CONFIG_SCSI_IPS is not set
281# CONFIG_SCSI_INITIO is not set
282# CONFIG_SCSI_INIA100 is not set
283CONFIG_SCSI_SYM53C8XX_2=y
284CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
285CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
286CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
287# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
288# CONFIG_SCSI_IPR is not set
289# CONFIG_SCSI_PCI2000 is not set
290# CONFIG_SCSI_PCI2220I is not set
291# CONFIG_SCSI_QLOGIC_ISP is not set
292CONFIG_SCSI_QLOGIC_FC=m
293# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
294CONFIG_SCSI_QLOGIC_1280=m
295# CONFIG_SCSI_QLOGIC_1280_1040 is not set
296CONFIG_SCSI_QLA2XXX=y
297# CONFIG_SCSI_QLA21XX is not set
298# CONFIG_SCSI_QLA22XX is not set
299CONFIG_SCSI_QLA2300=m
300CONFIG_SCSI_QLA2322=m
301CONFIG_SCSI_QLA6312=m
302CONFIG_SCSI_QLA6322=m
303# CONFIG_SCSI_DC395x is not set
304# CONFIG_SCSI_DC390T is not set
305# CONFIG_SCSI_NSP32 is not set
306CONFIG_SCSI_DEBUG=m
307
308#
309# Multi-device support (RAID and LVM)
310#
311CONFIG_MD=y
312CONFIG_BLK_DEV_MD=y
313CONFIG_MD_LINEAR=y
314CONFIG_MD_RAID0=y
315CONFIG_MD_RAID1=y
316# CONFIG_MD_RAID10 is not set
317# CONFIG_MD_RAID5 is not set
318# CONFIG_MD_RAID6 is not set
319CONFIG_MD_MULTIPATH=y
320# CONFIG_MD_FAULTY is not set
321CONFIG_BLK_DEV_DM=y
322# CONFIG_DM_CRYPT is not set
323# CONFIG_DM_SNAPSHOT is not set
324# CONFIG_DM_MIRROR is not set
325# CONFIG_DM_ZERO is not set
326
327#
328# Fusion MPT device support
329#
330CONFIG_FUSION=m
331CONFIG_FUSION_MAX_SGE=40
332CONFIG_FUSION_CTL=m
333
334#
335# IEEE 1394 (FireWire) support
336#
337# CONFIG_IEEE1394 is not set
338
339#
340# I2O device support
341#
342# CONFIG_I2O is not set
343
344#
345# Networking support
346#
347CONFIG_NET=y
348
349#
350# Networking options
351#
352CONFIG_PACKET=y
353CONFIG_PACKET_MMAP=y
354CONFIG_NETLINK_DEV=y
355CONFIG_UNIX=y
356CONFIG_NET_KEY=m
357CONFIG_INET=y
358CONFIG_IP_MULTICAST=y
359# CONFIG_IP_ADVANCED_ROUTER is not set
360CONFIG_IP_PNP=y
361# CONFIG_IP_PNP_DHCP is not set
362CONFIG_IP_PNP_BOOTP=y
363# CONFIG_IP_PNP_RARP is not set
364# CONFIG_NET_IPIP is not set
365# CONFIG_NET_IPGRE is not set
366# CONFIG_IP_MROUTE is not set
367# CONFIG_ARPD is not set
368# CONFIG_SYN_COOKIES is not set
369CONFIG_INET_AH=m
370CONFIG_INET_ESP=m
371# CONFIG_INET_IPCOMP is not set
372# CONFIG_INET_TUNNEL is not set
373CONFIG_IP_TCPDIAG=y
374# CONFIG_IP_TCPDIAG_IPV6 is not set
375
376#
377# IP: Virtual Server Configuration
378#
379# CONFIG_IP_VS is not set
380# CONFIG_IPV6 is not set
381CONFIG_NETFILTER=y
382CONFIG_NETFILTER_DEBUG=y
383
384#
385# IP: Netfilter Configuration
386#
387CONFIG_IP_NF_CONNTRACK=m
388# CONFIG_IP_NF_CT_ACCT is not set
389# CONFIG_IP_NF_CONNTRACK_MARK is not set
390# CONFIG_IP_NF_CT_PROTO_SCTP is not set
391CONFIG_IP_NF_FTP=m
392CONFIG_IP_NF_IRC=m
393CONFIG_IP_NF_TFTP=m
394CONFIG_IP_NF_AMANDA=m
395CONFIG_IP_NF_QUEUE=m
396CONFIG_IP_NF_IPTABLES=m
397CONFIG_IP_NF_MATCH_LIMIT=m
398CONFIG_IP_NF_MATCH_IPRANGE=m
399CONFIG_IP_NF_MATCH_MAC=m
400CONFIG_IP_NF_MATCH_PKTTYPE=m
401CONFIG_IP_NF_MATCH_MARK=m
402CONFIG_IP_NF_MATCH_MULTIPORT=m
403CONFIG_IP_NF_MATCH_TOS=m
404CONFIG_IP_NF_MATCH_RECENT=m
405CONFIG_IP_NF_MATCH_ECN=m
406CONFIG_IP_NF_MATCH_DSCP=m
407CONFIG_IP_NF_MATCH_AH_ESP=m
408CONFIG_IP_NF_MATCH_LENGTH=m
409CONFIG_IP_NF_MATCH_TTL=m
410CONFIG_IP_NF_MATCH_TCPMSS=m
411CONFIG_IP_NF_MATCH_HELPER=m
412CONFIG_IP_NF_MATCH_STATE=m
413CONFIG_IP_NF_MATCH_CONNTRACK=m
414CONFIG_IP_NF_MATCH_OWNER=m
415# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
416# CONFIG_IP_NF_MATCH_REALM is not set
417# CONFIG_IP_NF_MATCH_SCTP is not set
418# CONFIG_IP_NF_MATCH_COMMENT is not set
419# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
420CONFIG_IP_NF_FILTER=m
421CONFIG_IP_NF_TARGET_REJECT=m
422CONFIG_IP_NF_TARGET_LOG=m
423CONFIG_IP_NF_TARGET_ULOG=m
424CONFIG_IP_NF_TARGET_TCPMSS=m
425CONFIG_IP_NF_NAT=m
426CONFIG_IP_NF_NAT_NEEDED=y
427CONFIG_IP_NF_TARGET_MASQUERADE=m
428CONFIG_IP_NF_TARGET_REDIRECT=m
429CONFIG_IP_NF_TARGET_NETMAP=m
430CONFIG_IP_NF_TARGET_SAME=m
431CONFIG_IP_NF_NAT_SNMP_BASIC=m
432CONFIG_IP_NF_NAT_IRC=m
433CONFIG_IP_NF_NAT_FTP=m
434CONFIG_IP_NF_NAT_TFTP=m
435CONFIG_IP_NF_NAT_AMANDA=m
436CONFIG_IP_NF_MANGLE=m
437CONFIG_IP_NF_TARGET_TOS=m
438CONFIG_IP_NF_TARGET_ECN=m
439CONFIG_IP_NF_TARGET_DSCP=m
440CONFIG_IP_NF_TARGET_MARK=m
441CONFIG_IP_NF_TARGET_CLASSIFY=m
442# CONFIG_IP_NF_RAW is not set
443CONFIG_IP_NF_ARPTABLES=m
444CONFIG_IP_NF_ARPFILTER=m
445CONFIG_IP_NF_ARP_MANGLE=m
446CONFIG_IP_NF_COMPAT_IPCHAINS=m
447CONFIG_IP_NF_COMPAT_IPFWADM=m
448CONFIG_XFRM=y
449CONFIG_XFRM_USER=m
450
451#
452# SCTP Configuration (EXPERIMENTAL)
453#
454# CONFIG_IP_SCTP is not set
455# CONFIG_ATM is not set
456# CONFIG_BRIDGE is not set
457# CONFIG_VLAN_8021Q is not set
458# CONFIG_DECNET is not set
459CONFIG_LLC=m
460CONFIG_LLC2=m
461# CONFIG_IPX is not set
462# CONFIG_ATALK is not set
463# CONFIG_X25 is not set
464# CONFIG_LAPB is not set
465# CONFIG_NET_DIVERT is not set
466# CONFIG_ECONET is not set
467# CONFIG_WAN_ROUTER is not set
468
469#
470# QoS and/or fair queueing
471#
472# CONFIG_NET_SCHED is not set
473# CONFIG_NET_CLS_ROUTE is not set
474
475#
476# Network testing
477#
478# CONFIG_NET_PKTGEN is not set
479# CONFIG_NETPOLL is not set
480# CONFIG_NET_POLL_CONTROLLER is not set
481# CONFIG_HAMRADIO is not set
482# CONFIG_IRDA is not set
483# CONFIG_BT is not set
484CONFIG_NETDEVICES=y
485CONFIG_DUMMY=m
486CONFIG_BONDING=m
487# CONFIG_EQUALIZER is not set
488CONFIG_TUN=m
489# CONFIG_ETHERTAP is not set
490
491#
492# ARCnet devices
493#
494# CONFIG_ARCNET is not set
495
496#
497# Ethernet (10 or 100Mbit)
498#
499CONFIG_NET_ETHERNET=y
500CONFIG_MII=m
501CONFIG_HAPPYMEAL=m
502# CONFIG_SUNGEM is not set
503# CONFIG_NET_VENDOR_3COM is not set
504
505#
506# Tulip family network device support
507#
508CONFIG_NET_TULIP=y
509CONFIG_DE2104X=m
510CONFIG_TULIP=y
511# CONFIG_TULIP_MWI is not set
512CONFIG_TULIP_MMIO=y
513# CONFIG_TULIP_NAPI is not set
514# CONFIG_DE4X5 is not set
515# CONFIG_WINBOND_840 is not set
516# CONFIG_DM9102 is not set
517# CONFIG_HP100 is not set
518CONFIG_NET_PCI=y
519CONFIG_PCNET32=m
520# CONFIG_AMD8111_ETH is not set
521CONFIG_ADAPTEC_STARFIRE=m
522# CONFIG_ADAPTEC_STARFIRE_NAPI is not set
523CONFIG_B44=m
524# CONFIG_FORCEDETH is not set
525# CONFIG_DGRS is not set
526CONFIG_EEPRO100=m
527# CONFIG_EEPRO100_PIO is not set
528CONFIG_E100=m
529# CONFIG_E100_NAPI is not set
530# CONFIG_FEALNX is not set
531CONFIG_NATSEMI=m
532# CONFIG_NE2K_PCI is not set
533# CONFIG_8139CP is not set
534CONFIG_8139TOO=m
535# CONFIG_8139TOO_PIO is not set
536# CONFIG_8139TOO_TUNE_TWISTER is not set
537# CONFIG_8139TOO_8129 is not set
538# CONFIG_8139_OLD_RX_RESET is not set
539# CONFIG_SIS900 is not set
540# CONFIG_EPIC100 is not set
541# CONFIG_SUNDANCE is not set
542# CONFIG_TLAN is not set
543# CONFIG_VIA_RHINE is not set
544
545#
546# Ethernet (1000 Mbit)
547#
548CONFIG_ACENIC=m
549# CONFIG_ACENIC_OMIT_TIGON_I is not set
550# CONFIG_DL2K is not set
551CONFIG_E1000=m
552# CONFIG_E1000_NAPI is not set
553# CONFIG_NS83820 is not set
554# CONFIG_HAMACHI is not set
555# CONFIG_YELLOWFIN is not set
556# CONFIG_R8169 is not set
557# CONFIG_SK98LIN is not set
558# CONFIG_VIA_VELOCITY is not set
559CONFIG_TIGON3=m
560
561#
562# Ethernet (10000 Mbit)
563#
564CONFIG_IXGB=y
565CONFIG_IXGB_NAPI=y
566# CONFIG_S2IO is not set
567
568#
569# Token Ring devices
570#
571# CONFIG_TR is not set
572
573#
574# Wireless LAN (non-hamradio)
575#
576# CONFIG_NET_RADIO is not set
577
578#
579# Wan interfaces
580#
581# CONFIG_WAN is not set
582# CONFIG_FDDI is not set
583# CONFIG_HIPPI is not set
584CONFIG_PPP=m
585# CONFIG_PPP_MULTILINK is not set
586# CONFIG_PPP_FILTER is not set
587CONFIG_PPP_ASYNC=m
588CONFIG_PPP_SYNC_TTY=m
589CONFIG_PPP_DEFLATE=m
590CONFIG_PPP_BSDCOMP=m
591CONFIG_PPPOE=m
592# CONFIG_SLIP is not set
593# CONFIG_NET_FC is not set
594# CONFIG_SHAPER is not set
595# CONFIG_NETCONSOLE is not set
596
597#
598# ISDN subsystem
599#
600# CONFIG_ISDN is not set
601
602#
603# Telephony Support
604#
605# CONFIG_PHONE is not set
606
607#
608# Input device support
609#
610CONFIG_INPUT=y
611
612#
613# Userland interfaces
614#
615CONFIG_INPUT_MOUSEDEV=y
616# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
617CONFIG_INPUT_MOUSEDEV_SCREEN_X=1600
618CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1200
619# CONFIG_INPUT_JOYDEV is not set
620# CONFIG_INPUT_TSDEV is not set
621# CONFIG_INPUT_EVDEV is not set
622# CONFIG_INPUT_EVBUG is not set
623
624#
625# Input I/O drivers
626#
627# CONFIG_GAMEPORT is not set
628CONFIG_SOUND_GAMEPORT=y
629CONFIG_SERIO=m
630CONFIG_SERIO_SERPORT=m
631# CONFIG_SERIO_PCIPS2 is not set
632# CONFIG_SERIO_RAW is not set
633
634#
635# Input Device Drivers
636#
637CONFIG_INPUT_KEYBOARD=y
638# CONFIG_KEYBOARD_ATKBD is not set
639# CONFIG_KEYBOARD_SUNKBD is not set
640# CONFIG_KEYBOARD_LKKBD is not set
641# CONFIG_KEYBOARD_XTKBD is not set
642# CONFIG_KEYBOARD_NEWTON is not set
643CONFIG_INPUT_MOUSE=y
644# CONFIG_MOUSE_PS2 is not set
645# CONFIG_MOUSE_SERIAL is not set
646# CONFIG_MOUSE_VSXXXAA is not set
647# CONFIG_INPUT_JOYSTICK is not set
648# CONFIG_INPUT_TOUCHSCREEN is not set
649# CONFIG_INPUT_MISC is not set
650
651#
652# Character devices
653#
654CONFIG_VT=y
655CONFIG_VT_CONSOLE=y
656CONFIG_HW_CONSOLE=y
657# CONFIG_SERIAL_NONSTANDARD is not set
658
659#
660# Serial drivers
661#
662CONFIG_SERIAL_8250=y
663CONFIG_SERIAL_8250_CONSOLE=y
664CONFIG_SERIAL_8250_NR_UARTS=4
665CONFIG_SERIAL_8250_EXTENDED=y
666CONFIG_SERIAL_8250_MANY_PORTS=y
667CONFIG_SERIAL_8250_SHARE_IRQ=y
668# CONFIG_SERIAL_8250_DETECT_IRQ is not set
669# CONFIG_SERIAL_8250_MULTIPORT is not set
670# CONFIG_SERIAL_8250_RSA is not set
671
672#
673# Non-8250 serial port support
674#
675# CONFIG_SERIAL_MUX is not set
676# CONFIG_PDC_CONSOLE is not set
677CONFIG_SERIAL_CORE=y
678CONFIG_SERIAL_CORE_CONSOLE=y
679CONFIG_UNIX98_PTYS=y
680CONFIG_LEGACY_PTYS=y
681CONFIG_LEGACY_PTY_COUNT=256
682
683#
684# IPMI
685#
686# CONFIG_IPMI_HANDLER is not set
687
688#
689# Watchdog Cards
690#
691# CONFIG_WATCHDOG is not set
692CONFIG_GEN_RTC=y
693CONFIG_GEN_RTC_X=y
694# CONFIG_DTLK is not set
695# CONFIG_R3964 is not set
696# CONFIG_APPLICOM is not set
697
698#
699# Ftape, the floppy tape device driver
700#
701# CONFIG_AGP is not set
702# CONFIG_DRM is not set
703CONFIG_RAW_DRIVER=y
704CONFIG_MAX_RAW_DEVS=256
705
706#
707# I2C support
708#
709# CONFIG_I2C is not set
710
711#
712# Dallas's 1-wire bus
713#
714# CONFIG_W1 is not set
715
716#
717# Misc devices
718#
719
720#
721# Multimedia devices
722#
723# CONFIG_VIDEO_DEV is not set
724
725#
726# Digital Video Broadcasting Devices
727#
728# CONFIG_DVB is not set
729
730#
731# Graphics support
732#
733CONFIG_FB=y
734# CONFIG_FB_MODE_HELPERS is not set
735# CONFIG_FB_TILEBLITTING is not set
736# CONFIG_FB_CIRRUS is not set
737# CONFIG_FB_PM2 is not set
738# CONFIG_FB_CYBER2000 is not set
739# CONFIG_FB_ASILIANT is not set
740# CONFIG_FB_IMSTT is not set
741CONFIG_FB_STI=y
742# CONFIG_FB_RIVA is not set
743# CONFIG_FB_MATROX is not set
744# CONFIG_FB_RADEON_OLD is not set
745# CONFIG_FB_RADEON is not set
746# CONFIG_FB_ATY128 is not set
747# CONFIG_FB_ATY is not set
748# CONFIG_FB_SAVAGE is not set
749# CONFIG_FB_SIS is not set
750# CONFIG_FB_NEOMAGIC is not set
751# CONFIG_FB_KYRO is not set
752# CONFIG_FB_3DFX is not set
753# CONFIG_FB_VOODOO1 is not set
754# CONFIG_FB_TRIDENT is not set
755# CONFIG_FB_PM3 is not set
756# CONFIG_FB_VIRTUAL is not set
757
758#
759# Console display driver support
760#
761CONFIG_STI_CONSOLE=y
762CONFIG_DUMMY_CONSOLE_COLUMNS=160
763CONFIG_DUMMY_CONSOLE_ROWS=64
764CONFIG_DUMMY_CONSOLE=y
765CONFIG_FRAMEBUFFER_CONSOLE=y
766# CONFIG_FONTS is not set
767CONFIG_FONT_8x8=y
768CONFIG_FONT_8x16=y
769
770#
771# Logo configuration
772#
773CONFIG_LOGO=y
774# CONFIG_LOGO_LINUX_MONO is not set
775# CONFIG_LOGO_LINUX_VGA16 is not set
776# CONFIG_LOGO_LINUX_CLUT224 is not set
777CONFIG_LOGO_PARISC_CLUT224=y
778
779#
780# Sound
781#
782CONFIG_SOUND=y
783
784#
785# Advanced Linux Sound Architecture
786#
787# CONFIG_SND is not set
788
789#
790# Open Sound System
791#
792# CONFIG_SOUND_PRIME is not set
793
794#
795# USB support
796#
797CONFIG_USB=y
798CONFIG_USB_DEBUG=y
799
800#
801# Miscellaneous USB options
802#
803CONFIG_USB_DEVICEFS=y
804# CONFIG_USB_BANDWIDTH is not set
805# CONFIG_USB_DYNAMIC_MINORS is not set
806# CONFIG_USB_OTG is not set
807CONFIG_USB_ARCH_HAS_HCD=y
808CONFIG_USB_ARCH_HAS_OHCI=y
809
810#
811# USB Host Controller Drivers
812#
813# CONFIG_USB_EHCI_HCD is not set
814CONFIG_USB_OHCI_HCD=y
815# CONFIG_USB_UHCI_HCD is not set
816# CONFIG_USB_SL811_HCD is not set
817
818#
819# USB Device Class drivers
820#
821# CONFIG_USB_AUDIO is not set
822# CONFIG_USB_BLUETOOTH_TTY is not set
823# CONFIG_USB_MIDI is not set
824# CONFIG_USB_ACM is not set
825CONFIG_USB_PRINTER=m
826
827#
828# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
829#
830CONFIG_USB_STORAGE=m
831# CONFIG_USB_STORAGE_DEBUG is not set
832# CONFIG_USB_STORAGE_RW_DETECT is not set
833CONFIG_USB_STORAGE_DATAFAB=y
834CONFIG_USB_STORAGE_FREECOM=y
835# CONFIG_USB_STORAGE_ISD200 is not set
836CONFIG_USB_STORAGE_DPCM=y
837CONFIG_USB_STORAGE_HP8200e=y
838CONFIG_USB_STORAGE_SDDR09=y
839CONFIG_USB_STORAGE_SDDR55=y
840CONFIG_USB_STORAGE_JUMPSHOT=y
841
842#
843# USB Input Devices
844#
845CONFIG_USB_HID=y
846CONFIG_USB_HIDINPUT=y
847# CONFIG_HID_FF is not set
848CONFIG_USB_HIDDEV=y
849CONFIG_USB_AIPTEK=m
850CONFIG_USB_WACOM=m
851CONFIG_USB_KBTAB=m
852# CONFIG_USB_POWERMATE is not set
853# CONFIG_USB_MTOUCH is not set
854# CONFIG_USB_EGALAX is not set
855# CONFIG_USB_XPAD is not set
856# CONFIG_USB_ATI_REMOTE is not set
857
858#
859# USB Imaging devices
860#
861CONFIG_USB_MDC800=m
862CONFIG_USB_MICROTEK=m
863CONFIG_USB_HPUSBSCSI=m
864
865#
866# USB Multimedia devices
867#
868# CONFIG_USB_DABUSB is not set
869
870#
871# Video4Linux support is needed for USB Multimedia device support
872#
873
874#
875# USB Network Adapters
876#
877# CONFIG_USB_CATC is not set
878# CONFIG_USB_KAWETH is not set
879# CONFIG_USB_PEGASUS is not set
880# CONFIG_USB_RTL8150 is not set
881# CONFIG_USB_USBNET is not set
882
883#
884# USB port drivers
885#
886
887#
888# USB Serial Converter support
889#
890# CONFIG_USB_SERIAL is not set
891
892#
893# USB Miscellaneous drivers
894#
895# CONFIG_USB_EMI62 is not set
896# CONFIG_USB_EMI26 is not set
897# CONFIG_USB_TIGL is not set
898# CONFIG_USB_AUERSWALD is not set
899# CONFIG_USB_RIO500 is not set
900CONFIG_USB_LEGOTOWER=m
901# CONFIG_USB_LCD is not set
902# CONFIG_USB_LED is not set
903# CONFIG_USB_CYTHERM is not set
904# CONFIG_USB_PHIDGETKIT is not set
905# CONFIG_USB_PHIDGETSERVO is not set
906# CONFIG_USB_TEST is not set
907
908#
909# USB ATM/DSL drivers
910#
911
912#
913# USB Gadget Support
914#
915# CONFIG_USB_GADGET is not set
916
917#
918# MMC/SD Card support
919#
920# CONFIG_MMC is not set
921
922#
923# File systems
924#
925CONFIG_EXT2_FS=y
926# CONFIG_EXT2_FS_XATTR is not set
927CONFIG_EXT3_FS=y
928# CONFIG_EXT3_FS_XATTR is not set
929CONFIG_JBD=y
930# CONFIG_JBD_DEBUG is not set
931# CONFIG_REISERFS_FS is not set
932# CONFIG_JFS_FS is not set
933CONFIG_XFS_FS=m
934# CONFIG_XFS_RT is not set
935# CONFIG_XFS_QUOTA is not set
936# CONFIG_XFS_SECURITY is not set
937# CONFIG_XFS_POSIX_ACL is not set
938# CONFIG_MINIX_FS is not set
939# CONFIG_ROMFS_FS is not set
940# CONFIG_QUOTA is not set
941CONFIG_DNOTIFY=y
942# CONFIG_AUTOFS_FS is not set
943CONFIG_AUTOFS4_FS=y
944
945#
946# CD-ROM/DVD Filesystems
947#
948CONFIG_ISO9660_FS=y
949CONFIG_JOLIET=y
950# CONFIG_ZISOFS is not set
951# CONFIG_UDF_FS is not set
952
953#
954# DOS/FAT/NT Filesystems
955#
956CONFIG_FAT_FS=m
957CONFIG_MSDOS_FS=m
958CONFIG_VFAT_FS=m
959CONFIG_FAT_DEFAULT_CODEPAGE=437
960CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
961# CONFIG_NTFS_FS is not set
962
963#
964# Pseudo filesystems
965#
966CONFIG_PROC_FS=y
967CONFIG_PROC_KCORE=y
968CONFIG_SYSFS=y
969# CONFIG_DEVFS_FS is not set
970# CONFIG_DEVPTS_FS_XATTR is not set
971CONFIG_TMPFS=y
972# CONFIG_TMPFS_XATTR is not set
973# CONFIG_HUGETLBFS is not set
974# CONFIG_HUGETLB_PAGE is not set
975CONFIG_RAMFS=y
976
977#
978# Miscellaneous filesystems
979#
980# CONFIG_ADFS_FS is not set
981# CONFIG_AFFS_FS is not set
982# CONFIG_HFS_FS is not set
983# CONFIG_HFSPLUS_FS is not set
984# CONFIG_BEFS_FS is not set
985# CONFIG_BFS_FS is not set
986# CONFIG_EFS_FS is not set
987# CONFIG_CRAMFS is not set
988# CONFIG_VXFS_FS is not set
989# CONFIG_HPFS_FS is not set
990# CONFIG_QNX4FS_FS is not set
991# CONFIG_SYSV_FS is not set
992# CONFIG_UFS_FS is not set
993
994#
995# Network File Systems
996#
997CONFIG_NFS_FS=y
998CONFIG_NFS_V3=y
999# CONFIG_NFS_V4 is not set
1000# CONFIG_NFS_DIRECTIO is not set
1001CONFIG_NFSD=y
1002CONFIG_NFSD_V3=y
1003# CONFIG_NFSD_V4 is not set
1004# CONFIG_NFSD_TCP is not set
1005CONFIG_ROOT_NFS=y
1006CONFIG_LOCKD=y
1007CONFIG_LOCKD_V4=y
1008CONFIG_EXPORTFS=y
1009CONFIG_SUNRPC=y
1010# CONFIG_RPCSEC_GSS_KRB5 is not set
1011# CONFIG_RPCSEC_GSS_SPKM3 is not set
1012# CONFIG_SMB_FS is not set
1013# CONFIG_CIFS is not set
1014# CONFIG_NCP_FS is not set
1015# CONFIG_CODA_FS is not set
1016# CONFIG_AFS_FS is not set
1017
1018#
1019# Partition Types
1020#
1021# CONFIG_PARTITION_ADVANCED is not set
1022CONFIG_MSDOS_PARTITION=y
1023
1024#
1025# Native Language Support
1026#
1027CONFIG_NLS=y
1028CONFIG_NLS_DEFAULT="iso8859-1"
1029# CONFIG_NLS_CODEPAGE_437 is not set
1030# CONFIG_NLS_CODEPAGE_737 is not set
1031# CONFIG_NLS_CODEPAGE_775 is not set
1032# CONFIG_NLS_CODEPAGE_850 is not set
1033# CONFIG_NLS_CODEPAGE_852 is not set
1034# CONFIG_NLS_CODEPAGE_855 is not set
1035# CONFIG_NLS_CODEPAGE_857 is not set
1036# CONFIG_NLS_CODEPAGE_860 is not set
1037# CONFIG_NLS_CODEPAGE_861 is not set
1038# CONFIG_NLS_CODEPAGE_862 is not set
1039# CONFIG_NLS_CODEPAGE_863 is not set
1040# CONFIG_NLS_CODEPAGE_864 is not set
1041# CONFIG_NLS_CODEPAGE_865 is not set
1042# CONFIG_NLS_CODEPAGE_866 is not set
1043# CONFIG_NLS_CODEPAGE_869 is not set
1044# CONFIG_NLS_CODEPAGE_936 is not set
1045# CONFIG_NLS_CODEPAGE_950 is not set
1046# CONFIG_NLS_CODEPAGE_932 is not set
1047# CONFIG_NLS_CODEPAGE_949 is not set
1048# CONFIG_NLS_CODEPAGE_874 is not set
1049# CONFIG_NLS_ISO8859_8 is not set
1050# CONFIG_NLS_CODEPAGE_1250 is not set
1051# CONFIG_NLS_CODEPAGE_1251 is not set
1052# CONFIG_NLS_ASCII is not set
1053# CONFIG_NLS_ISO8859_1 is not set
1054# CONFIG_NLS_ISO8859_2 is not set
1055# CONFIG_NLS_ISO8859_3 is not set
1056# CONFIG_NLS_ISO8859_4 is not set
1057# CONFIG_NLS_ISO8859_5 is not set
1058# CONFIG_NLS_ISO8859_6 is not set
1059# CONFIG_NLS_ISO8859_7 is not set
1060# CONFIG_NLS_ISO8859_9 is not set
1061# CONFIG_NLS_ISO8859_13 is not set
1062# CONFIG_NLS_ISO8859_14 is not set
1063# CONFIG_NLS_ISO8859_15 is not set
1064# CONFIG_NLS_KOI8_R is not set
1065# CONFIG_NLS_KOI8_U is not set
1066# CONFIG_NLS_UTF8 is not set
1067
1068#
1069# Profiling support
1070#
1071CONFIG_PROFILING=y
1072CONFIG_OPROFILE=m
1073
1074#
1075# Kernel hacking
1076#
1077CONFIG_DEBUG_KERNEL=y
1078CONFIG_MAGIC_SYSRQ=y
1079# CONFIG_SCHEDSTATS is not set
1080# CONFIG_DEBUG_SLAB is not set
1081# CONFIG_DEBUG_SPINLOCK is not set
1082# CONFIG_DEBUG_KOBJECT is not set
1083# CONFIG_DEBUG_INFO is not set
1084
1085#
1086# Security options
1087#
1088# CONFIG_KEYS is not set
1089# CONFIG_SECURITY is not set
1090
1091#
1092# Cryptographic options
1093#
1094CONFIG_CRYPTO=y
1095CONFIG_CRYPTO_HMAC=y
1096CONFIG_CRYPTO_NULL=m
1097CONFIG_CRYPTO_MD4=m
1098CONFIG_CRYPTO_MD5=m
1099CONFIG_CRYPTO_SHA1=m
1100CONFIG_CRYPTO_SHA256=m
1101# CONFIG_CRYPTO_SHA512 is not set
1102# CONFIG_CRYPTO_WP512 is not set
1103CONFIG_CRYPTO_DES=m
1104CONFIG_CRYPTO_BLOWFISH=m
1105CONFIG_CRYPTO_TWOFISH=m
1106CONFIG_CRYPTO_SERPENT=m
1107CONFIG_CRYPTO_AES=m
1108CONFIG_CRYPTO_CAST5=m
1109CONFIG_CRYPTO_CAST6=m
1110# CONFIG_CRYPTO_TEA is not set
1111# CONFIG_CRYPTO_ARC4 is not set
1112# CONFIG_CRYPTO_KHAZAD is not set
1113# CONFIG_CRYPTO_ANUBIS is not set
1114CONFIG_CRYPTO_DEFLATE=m
1115# CONFIG_CRYPTO_MICHAEL_MIC is not set
1116CONFIG_CRYPTO_CRC32C=m
1117CONFIG_CRYPTO_TEST=m
1118
1119#
1120# Library routines
1121#
1122CONFIG_CRC_CCITT=m
1123CONFIG_CRC32=y
1124CONFIG_LIBCRC32C=m
1125CONFIG_ZLIB_INFLATE=m
1126CONFIG_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 @@
1#
2# Automatically generated make config: don't edit
3#
4CONFIG_PARISC=y
5CONFIG_MMU=y
6CONFIG_STACK_GROWSUP=y
7CONFIG_RWSEM_GENERIC_SPINLOCK=y
8
9#
10# Code maturity level options
11#
12CONFIG_EXPERIMENTAL=y
13CONFIG_CLEAN_COMPILE=y
14CONFIG_STANDALONE=y
15CONFIG_BROKEN_ON_SMP=y
16
17#
18# General setup
19#
20CONFIG_SWAP=y
21CONFIG_SYSVIPC=y
22# CONFIG_BSD_PROCESS_ACCT is not set
23CONFIG_SYSCTL=y
24CONFIG_LOG_BUF_SHIFT=15
25# CONFIG_HOTPLUG is not set
26CONFIG_IKCONFIG=y
27CONFIG_IKCONFIG_PROC=y
28# CONFIG_EMBEDDED is not set
29CONFIG_KALLSYMS=y
30CONFIG_FUTEX=y
31CONFIG_EPOLL=y
32CONFIG_IOSCHED_NOOP=y
33CONFIG_IOSCHED_AS=y
34CONFIG_IOSCHED_DEADLINE=y
35# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
36
37#
38# Loadable module support
39#
40# CONFIG_MODULES is not set
41
42#
43# Processor type and features
44#
45CONFIG_PA7000=y
46# CONFIG_PA7100LC is not set
47# CONFIG_PA7200 is not set
48# CONFIG_PA8X00 is not set
49CONFIG_PA11=y
50# CONFIG_64BIT is not set
51# CONFIG_SMP is not set
52# CONFIG_PREEMPT is not set
53# CONFIG_HPUX is not set
54
55#
56# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
57#
58CONFIG_GSC=y
59CONFIG_HPPB=y
60CONFIG_IOMMU_CCIO=y
61CONFIG_GSC_LASI=y
62CONFIG_GSC_WAX=y
63CONFIG_EISA=y
64CONFIG_EISA_NAMES=y
65# CONFIG_ISA is not set
66CONFIG_PCI=y
67CONFIG_PCI_LEGACY_PROC=y
68CONFIG_PCI_NAMES=y
69CONFIG_GSC_DINO=y
70CONFIG_PCI_LBA=y
71CONFIG_IOSAPIC=y
72CONFIG_IOMMU_SBA=y
73CONFIG_SUPERIO=y
74CONFIG_CHASSIS_LCD_LED=y
75CONFIG_PDC_CHASSIS=y
76
77#
78# Executable file formats
79#
80CONFIG_BINFMT_ELF=y
81# CONFIG_BINFMT_MISC is not set
82
83#
84# Device Drivers
85#
86
87#
88# Generic Driver Options
89#
90# CONFIG_DEBUG_DRIVER is not set
91
92#
93# Memory Technology Devices (MTD)
94#
95# CONFIG_MTD is not set
96
97#
98# Parallel port support
99#
100CONFIG_PARPORT=y
101CONFIG_PARPORT_PC=y
102CONFIG_PARPORT_PC_CML1=y
103# CONFIG_PARPORT_SERIAL is not set
104# CONFIG_PARPORT_PC_FIFO is not set
105# CONFIG_PARPORT_PC_SUPERIO is not set
106CONFIG_PARPORT_GSC=y
107# CONFIG_PARPORT_OTHER is not set
108# CONFIG_PARPORT_1284 is not set
109
110#
111# Plug and Play support
112#
113
114#
115# Block devices
116#
117# CONFIG_BLK_DEV_FD is not set
118# CONFIG_PARIDE is not set
119# CONFIG_BLK_CPQ_DA is not set
120# CONFIG_BLK_CPQ_CISS_DA is not set
121# CONFIG_BLK_DEV_DAC960 is not set
122# CONFIG_BLK_DEV_UMEM is not set
123CONFIG_BLK_DEV_LOOP=y
124CONFIG_BLK_DEV_CRYPTOLOOP=y
125# CONFIG_BLK_DEV_NBD is not set
126CONFIG_BLK_DEV_RAM=y
127CONFIG_BLK_DEV_RAM_SIZE=4096
128CONFIG_BLK_DEV_INITRD=y
129
130#
131# ATA/ATAPI/MFM/RLL support
132#
133# CONFIG_IDE is not set
134
135#
136# SCSI device support
137#
138CONFIG_SCSI=y
139CONFIG_SCSI_PROC_FS=y
140
141#
142# SCSI support type (disk, tape, CD-ROM)
143#
144CONFIG_BLK_DEV_SD=y
145CONFIG_CHR_DEV_ST=y
146# CONFIG_CHR_DEV_OSST is not set
147CONFIG_BLK_DEV_SR=y
148# CONFIG_BLK_DEV_SR_VENDOR is not set
149CONFIG_CHR_DEV_SG=y
150
151#
152# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
153#
154# CONFIG_SCSI_MULTI_LUN is not set
155# CONFIG_SCSI_REPORT_LUNS is not set
156# CONFIG_SCSI_CONSTANTS is not set
157# CONFIG_SCSI_LOGGING is not set
158
159#
160# SCSI low-level drivers
161#
162# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
163# CONFIG_SCSI_ACARD is not set
164# CONFIG_SCSI_AHA1740 is not set
165# CONFIG_SCSI_AACRAID is not set
166# CONFIG_SCSI_AIC7XXX is not set
167# CONFIG_SCSI_AIC7XXX_OLD is not set
168# CONFIG_SCSI_AIC79XX is not set
169# CONFIG_SCSI_ADVANSYS is not set
170# CONFIG_SCSI_MEGARAID is not set
171# CONFIG_SCSI_SATA is not set
172# CONFIG_SCSI_BUSLOGIC is not set
173# CONFIG_SCSI_CPQFCTS is not set
174# CONFIG_SCSI_DMX3191D is not set
175# CONFIG_SCSI_EATA is not set
176# CONFIG_SCSI_EATA_PIO is not set
177# CONFIG_SCSI_FUTURE_DOMAIN is not set
178# CONFIG_SCSI_GDTH is not set
179# CONFIG_SCSI_IPS is not set
180# CONFIG_SCSI_INIA100 is not set
181# CONFIG_SCSI_PPA is not set
182# CONFIG_SCSI_IMM is not set
183CONFIG_SCSI_LASI700=y
184CONFIG_53C700_MEM_MAPPED=y
185CONFIG_53C700_LE_ON_BE=y
186CONFIG_SCSI_SYM53C8XX_2=y
187CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
188CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
189CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
190# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
191CONFIG_SCSI_ZALON=y
192CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
193CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
194CONFIG_SCSI_NCR53C8XX_SYNC=20
195# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
196# CONFIG_SCSI_QLOGIC_ISP is not set
197# CONFIG_SCSI_QLOGIC_FC is not set
198# CONFIG_SCSI_QLOGIC_1280 is not set
199CONFIG_SCSI_QLA2XXX=y
200# CONFIG_SCSI_QLA21XX is not set
201# CONFIG_SCSI_QLA22XX is not set
202# CONFIG_SCSI_QLA2300 is not set
203# CONFIG_SCSI_QLA2322 is not set
204# CONFIG_SCSI_QLA6312 is not set
205# CONFIG_SCSI_QLA6322 is not set
206# CONFIG_SCSI_SIM710 is not set
207# CONFIG_SCSI_DC395x is not set
208# CONFIG_SCSI_DC390T is not set
209# CONFIG_SCSI_NSP32 is not set
210# CONFIG_SCSI_DEBUG is not set
211
212#
213# Multi-device support (RAID and LVM)
214#
215CONFIG_MD=y
216CONFIG_BLK_DEV_MD=y
217CONFIG_MD_LINEAR=y
218CONFIG_MD_RAID0=y
219CONFIG_MD_RAID1=y
220CONFIG_MD_RAID5=y
221# CONFIG_MD_RAID6 is not set
222# CONFIG_MD_MULTIPATH is not set
223# CONFIG_BLK_DEV_DM is not set
224
225#
226# Fusion MPT device support
227#
228# CONFIG_FUSION is not set
229
230#
231# IEEE 1394 (FireWire) support
232#
233# CONFIG_IEEE1394 is not set
234
235#
236# I2O device support
237#
238# CONFIG_I2O is not set
239
240#
241# Macintosh device drivers
242#
243
244#
245# Networking support
246#
247CONFIG_NET=y
248
249#
250# Networking options
251#
252CONFIG_PACKET=y
253CONFIG_PACKET_MMAP=y
254CONFIG_NETLINK_DEV=y
255CONFIG_UNIX=y
256# CONFIG_NET_KEY is not set
257CONFIG_INET=y
258CONFIG_IP_MULTICAST=y
259# CONFIG_IP_ADVANCED_ROUTER is not set
260CONFIG_IP_PNP=y
261# CONFIG_IP_PNP_DHCP is not set
262CONFIG_IP_PNP_BOOTP=y
263# CONFIG_IP_PNP_RARP is not set
264# CONFIG_NET_IPIP is not set
265# CONFIG_NET_IPGRE is not set
266# CONFIG_IP_MROUTE is not set
267# CONFIG_ARPD is not set
268# CONFIG_INET_ECN is not set
269# CONFIG_SYN_COOKIES is not set
270# CONFIG_INET_AH is not set
271# CONFIG_INET_ESP is not set
272# CONFIG_INET_IPCOMP is not set
273# CONFIG_IPV6 is not set
274# CONFIG_DECNET is not set
275# CONFIG_BRIDGE is not set
276# CONFIG_NETFILTER is not set
277
278#
279# SCTP Configuration (EXPERIMENTAL)
280#
281CONFIG_IPV6_SCTP__=y
282# CONFIG_IP_SCTP is not set
283# CONFIG_ATM is not set
284# CONFIG_VLAN_8021Q is not set
285# CONFIG_LLC2 is not set
286# CONFIG_IPX is not set
287# CONFIG_ATALK is not set
288# CONFIG_X25 is not set
289# CONFIG_LAPB is not set
290# CONFIG_NET_DIVERT is not set
291# CONFIG_ECONET is not set
292# CONFIG_WAN_ROUTER is not set
293# CONFIG_NET_HW_FLOWCONTROL is not set
294
295#
296# QoS and/or fair queueing
297#
298# CONFIG_NET_SCHED is not set
299
300#
301# Network testing
302#
303# CONFIG_NET_PKTGEN is not set
304CONFIG_NETDEVICES=y
305
306#
307# ARCnet devices
308#
309# CONFIG_ARCNET is not set
310# CONFIG_DUMMY is not set
311# CONFIG_BONDING is not set
312# CONFIG_EQUALIZER is not set
313# CONFIG_TUN is not set
314# CONFIG_ETHERTAP is not set
315
316#
317# Ethernet (10 or 100Mbit)
318#
319CONFIG_NET_ETHERNET=y
320# CONFIG_MII is not set
321CONFIG_LASI_82596=y
322# CONFIG_HAPPYMEAL is not set
323# CONFIG_SUNGEM is not set
324# CONFIG_NET_VENDOR_3COM is not set
325# CONFIG_NET_VENDOR_SMC is not set
326
327#
328# Tulip family network device support
329#
330CONFIG_NET_TULIP=y
331# CONFIG_DE2104X is not set
332CONFIG_TULIP=y
333# CONFIG_TULIP_MWI is not set
334# CONFIG_TULIP_MMIO is not set
335# CONFIG_TULIP_NAPI is not set
336# CONFIG_DE4X5 is not set
337# CONFIG_WINBOND_840 is not set
338# CONFIG_DM9102 is not set
339# CONFIG_DEPCA is not set
340# CONFIG_HP100 is not set
341CONFIG_NET_PCI=y
342# CONFIG_PCNET32 is not set
343# CONFIG_AMD8111_ETH is not set
344# CONFIG_ADAPTEC_STARFIRE is not set
345# CONFIG_AC3200 is not set
346# CONFIG_B44 is not set
347# CONFIG_FORCEDETH is not set
348# CONFIG_DGRS is not set
349# CONFIG_EEPRO100 is not set
350# CONFIG_E100 is not set
351# CONFIG_LNE390 is not set
352# CONFIG_FEALNX is not set
353# CONFIG_NATSEMI is not set
354# CONFIG_NE2K_PCI is not set
355# CONFIG_NE3210 is not set
356# CONFIG_ES3210 is not set
357# CONFIG_8139CP is not set
358# CONFIG_8139TOO is not set
359# CONFIG_SIS900 is not set
360# CONFIG_EPIC100 is not set
361# CONFIG_SUNDANCE is not set
362# CONFIG_TLAN is not set
363# CONFIG_VIA_RHINE is not set
364
365#
366# Ethernet (1000 Mbit)
367#
368# CONFIG_ACENIC is not set
369CONFIG_DL2K=y
370# CONFIG_E1000 is not set
371# CONFIG_NS83820 is not set
372# CONFIG_HAMACHI is not set
373# CONFIG_YELLOWFIN is not set
374# CONFIG_R8169 is not set
375# CONFIG_SIS190 is not set
376# CONFIG_SK98LIN is not set
377# CONFIG_TIGON3 is not set
378
379#
380# Ethernet (10000 Mbit)
381#
382# CONFIG_IXGB is not set
383# CONFIG_FDDI is not set
384# CONFIG_HIPPI is not set
385# CONFIG_PLIP is not set
386# CONFIG_PPP is not set
387# CONFIG_SLIP is not set
388
389#
390# Wireless LAN (non-hamradio)
391#
392CONFIG_NET_RADIO=y
393
394#
395# Obsolete Wireless cards support (pre-802.11)
396#
397# CONFIG_STRIP is not set
398
399#
400# Wireless 802.11b ISA/PCI cards support
401#
402CONFIG_AIRO=y
403# CONFIG_HERMES is not set
404# CONFIG_ATMEL is not set
405CONFIG_NET_WIRELESS=y
406
407#
408# Token Ring devices
409#
410# CONFIG_TR is not set
411# CONFIG_NET_FC is not set
412# CONFIG_RCPCI is not set
413# CONFIG_SHAPER is not set
414
415#
416# Wan interfaces
417#
418# CONFIG_WAN is not set
419
420#
421# Amateur Radio support
422#
423# CONFIG_HAMRADIO is not set
424
425#
426# IrDA (infrared) support
427#
428# CONFIG_IRDA is not set
429
430#
431# Bluetooth support
432#
433# CONFIG_BT is not set
434
435#
436# ISDN subsystem
437#
438# CONFIG_ISDN is not set
439
440#
441# Telephony Support
442#
443# CONFIG_PHONE is not set
444
445#
446# Input device support
447#
448CONFIG_INPUT=y
449
450#
451# Userland interfaces
452#
453CONFIG_INPUT_MOUSEDEV=y
454CONFIG_INPUT_MOUSEDEV_PSAUX=y
455CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
456CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
457# CONFIG_INPUT_JOYDEV is not set
458# CONFIG_INPUT_TSDEV is not set
459CONFIG_INPUT_EVDEV=y
460# CONFIG_INPUT_EVBUG is not set
461
462#
463# Input I/O drivers
464#
465# CONFIG_GAMEPORT is not set
466CONFIG_SOUND_GAMEPORT=y
467CONFIG_SERIO=y
468# CONFIG_SERIO_SERPORT is not set
469# CONFIG_SERIO_PARKBD is not set
470CONFIG_SERIO_GSCPS2=y
471CONFIG_HP_SDC=y
472CONFIG_HIL_MLC=y
473# CONFIG_SERIO_PCIPS2 is not set
474
475#
476# Input Device Drivers
477#
478CONFIG_INPUT_KEYBOARD=y
479# CONFIG_KEYBOARD_ATKBD is not set
480# CONFIG_KEYBOARD_SUNKBD is not set
481# CONFIG_KEYBOARD_XTKBD is not set
482# CONFIG_KEYBOARD_NEWTON is not set
483CONFIG_KEYBOARD_HIL=y
484CONFIG_INPUT_MOUSE=y
485# CONFIG_MOUSE_PS2 is not set
486# CONFIG_MOUSE_SERIAL is not set
487# CONFIG_MOUSE_HIL is not set
488CONFIG_INPUT_JOYSTICK=y
489# CONFIG_JOYSTICK_IFORCE is not set
490# CONFIG_JOYSTICK_WARRIOR is not set
491# CONFIG_JOYSTICK_MAGELLAN is not set
492# CONFIG_JOYSTICK_SPACEORB is not set
493# CONFIG_JOYSTICK_SPACEBALL is not set
494# CONFIG_JOYSTICK_STINGER is not set
495# CONFIG_JOYSTICK_TWIDDLER is not set
496# CONFIG_JOYSTICK_DB9 is not set
497# CONFIG_JOYSTICK_GAMECON is not set
498# CONFIG_JOYSTICK_TURBOGRAFX is not set
499# CONFIG_INPUT_JOYDUMP is not set
500CONFIG_INPUT_TOUCHSCREEN=y
501# CONFIG_TOUCHSCREEN_GUNZE is not set
502CONFIG_INPUT_MISC=y
503# CONFIG_INPUT_PCSPKR is not set
504# CONFIG_INPUT_UINPUT is not set
505CONFIG_HP_SDC_RTC=y
506
507#
508# Character devices
509#
510CONFIG_VT=y
511CONFIG_VT_CONSOLE=y
512CONFIG_HW_CONSOLE=y
513# CONFIG_SERIAL_NONSTANDARD is not set
514
515#
516# Serial drivers
517#
518CONFIG_SERIAL_8250=y
519CONFIG_SERIAL_8250_CONSOLE=y
520CONFIG_SERIAL_8250_NR_UARTS=4
521CONFIG_SERIAL_8250_EXTENDED=y
522CONFIG_SERIAL_8250_MANY_PORTS=y
523CONFIG_SERIAL_8250_SHARE_IRQ=y
524# CONFIG_SERIAL_8250_DETECT_IRQ is not set
525# CONFIG_SERIAL_8250_MULTIPORT is not set
526# CONFIG_SERIAL_8250_RSA is not set
527
528#
529# Non-8250 serial port support
530#
531# CONFIG_SERIAL_MUX is not set
532# CONFIG_PDC_CONSOLE is not set
533CONFIG_SERIAL_CORE=y
534CONFIG_SERIAL_CORE_CONSOLE=y
535CONFIG_UNIX98_PTYS=y
536CONFIG_LEGACY_PTYS=y
537CONFIG_LEGACY_PTY_COUNT=256
538CONFIG_PRINTER=y
539# CONFIG_LP_CONSOLE is not set
540# CONFIG_PPDEV is not set
541# CONFIG_TIPAR is not set
542
543#
544# Mice
545#
546# CONFIG_BUSMOUSE is not set
547# CONFIG_QIC02_TAPE is not set
548
549#
550# IPMI
551#
552# CONFIG_IPMI_HANDLER is not set
553
554#
555# Watchdog Cards
556#
557# CONFIG_WATCHDOG is not set
558# CONFIG_NVRAM is not set
559CONFIG_GEN_RTC=y
560# CONFIG_GEN_RTC_X is not set
561# CONFIG_DTLK is not set
562# CONFIG_R3964 is not set
563# CONFIG_APPLICOM is not set
564
565#
566# Ftape, the floppy tape device driver
567#
568# CONFIG_FTAPE is not set
569# CONFIG_AGP is not set
570# CONFIG_DRM is not set
571# CONFIG_RAW_DRIVER is not set
572
573#
574# I2C support
575#
576# CONFIG_I2C is not set
577
578#
579# Misc devices
580#
581
582#
583# Multimedia devices
584#
585# CONFIG_VIDEO_DEV is not set
586
587#
588# Digital Video Broadcasting Devices
589#
590# CONFIG_DVB is not set
591
592#
593# Graphics support
594#
595CONFIG_FB=y
596# CONFIG_FB_PM2 is not set
597# CONFIG_FB_CYBER2000 is not set
598# CONFIG_FB_IMSTT is not set
599CONFIG_FB_STI=y
600# CONFIG_FB_RIVA is not set
601# CONFIG_FB_MATROX is not set
602# CONFIG_FB_RADEON_OLD is not set
603# CONFIG_FB_RADEON is not set
604# CONFIG_FB_ATY128 is not set
605# CONFIG_FB_ATY is not set
606# CONFIG_FB_SIS is not set
607# CONFIG_FB_NEOMAGIC is not set
608# CONFIG_FB_KYRO is not set
609# CONFIG_FB_3DFX is not set
610# CONFIG_FB_VOODOO1 is not set
611# CONFIG_FB_TRIDENT is not set
612# CONFIG_FB_VIRTUAL is not set
613
614#
615# Console display driver support
616#
617# CONFIG_MDA_CONSOLE is not set
618CONFIG_STI_CONSOLE=y
619CONFIG_DUMMY_CONSOLE_COLUMNS=160
620CONFIG_DUMMY_CONSOLE_ROWS=64
621CONFIG_DUMMY_CONSOLE=y
622CONFIG_FRAMEBUFFER_CONSOLE=y
623CONFIG_PCI_CONSOLE=y
624# CONFIG_FONTS is not set
625CONFIG_FONT_8x8=y
626CONFIG_FONT_8x16=y
627
628#
629# Logo configuration
630#
631# CONFIG_LOGO is not set
632
633#
634# Sound
635#
636CONFIG_SOUND=y
637
638#
639# Advanced Linux Sound Architecture
640#
641# CONFIG_SND is not set
642
643#
644# Open Sound System
645#
646# CONFIG_SOUND_PRIME is not set
647# CONFIG_SOUND_HARMONY is not set
648
649#
650# USB support
651#
652CONFIG_USB=y
653CONFIG_USB_DEBUG=y
654
655#
656# Miscellaneous USB options
657#
658# CONFIG_USB_DEVICEFS is not set
659# CONFIG_USB_BANDWIDTH is not set
660# CONFIG_USB_DYNAMIC_MINORS is not set
661
662#
663# USB Host Controller Drivers
664#
665CONFIG_USB_EHCI_HCD=y
666CONFIG_USB_OHCI_HCD=y
667# CONFIG_USB_UHCI_HCD is not set
668
669#
670# USB Device Class drivers
671#
672# CONFIG_USB_AUDIO is not set
673# CONFIG_USB_BLUETOOTH_TTY is not set
674# CONFIG_USB_MIDI is not set
675# CONFIG_USB_ACM is not set
676# CONFIG_USB_PRINTER is not set
677# CONFIG_USB_STORAGE is not set
678
679#
680# USB Human Interface Devices (HID)
681#
682# CONFIG_USB_HID is not set
683
684#
685# USB HID Boot Protocol drivers
686#
687# CONFIG_USB_KBD is not set
688# CONFIG_USB_MOUSE is not set
689# CONFIG_USB_AIPTEK is not set
690# CONFIG_USB_WACOM is not set
691# CONFIG_USB_KBTAB is not set
692# CONFIG_USB_POWERMATE is not set
693# CONFIG_USB_XPAD is not set
694
695#
696# USB Imaging devices
697#
698# CONFIG_USB_MDC800 is not set
699# CONFIG_USB_MICROTEK is not set
700# CONFIG_USB_HPUSBSCSI is not set
701
702#
703# USB Multimedia devices
704#
705# CONFIG_USB_DABUSB is not set
706
707#
708# Video4Linux support is needed for USB Multimedia device support
709#
710
711#
712# USB Network adaptors
713#
714# CONFIG_USB_CATC is not set
715# CONFIG_USB_KAWETH is not set
716# CONFIG_USB_PEGASUS is not set
717# CONFIG_USB_RTL8150 is not set
718# CONFIG_USB_USBNET is not set
719
720#
721# USB port drivers
722#
723# CONFIG_USB_USS720 is not set
724
725#
726# USB Serial Converter support
727#
728# CONFIG_USB_SERIAL is not set
729
730#
731# USB Miscellaneous drivers
732#
733# CONFIG_USB_EMI62 is not set
734# CONFIG_USB_EMI26 is not set
735# CONFIG_USB_TIGL is not set
736# CONFIG_USB_AUERSWALD is not set
737# CONFIG_USB_RIO500 is not set
738# CONFIG_USB_LEGOTOWER is not set
739# CONFIG_USB_LCD is not set
740# CONFIG_USB_LED is not set
741
742#
743# USB Gadget Support
744#
745# CONFIG_USB_GADGET is not set
746
747#
748# File systems
749#
750CONFIG_EXT2_FS=y
751# CONFIG_EXT2_FS_XATTR is not set
752CONFIG_EXT3_FS=y
753# CONFIG_EXT3_FS_XATTR is not set
754CONFIG_JBD=y
755# CONFIG_JBD_DEBUG is not set
756# CONFIG_REISERFS_FS is not set
757# CONFIG_JFS_FS is not set
758# CONFIG_XFS_FS is not set
759# CONFIG_MINIX_FS is not set
760# CONFIG_ROMFS_FS is not set
761# CONFIG_QUOTA is not set
762# CONFIG_AUTOFS_FS is not set
763# CONFIG_AUTOFS4_FS is not set
764
765#
766# CD-ROM/DVD Filesystems
767#
768CONFIG_ISO9660_FS=y
769CONFIG_JOLIET=y
770# CONFIG_ZISOFS is not set
771# CONFIG_UDF_FS is not set
772
773#
774# DOS/FAT/NT Filesystems
775#
776# CONFIG_FAT_FS is not set
777# CONFIG_NTFS_FS is not set
778
779#
780# Pseudo filesystems
781#
782CONFIG_PROC_FS=y
783CONFIG_PROC_KCORE=y
784# CONFIG_DEVFS_FS is not set
785# CONFIG_DEVPTS_FS_XATTR is not set
786CONFIG_TMPFS=y
787# CONFIG_HUGETLB_PAGE is not set
788CONFIG_RAMFS=y
789
790#
791# Miscellaneous filesystems
792#
793# CONFIG_ADFS_FS is not set
794# CONFIG_AFFS_FS is not set
795# CONFIG_HFS_FS is not set
796# CONFIG_HFSPLUS_FS is not set
797# CONFIG_BEFS_FS is not set
798# CONFIG_BFS_FS is not set
799# CONFIG_EFS_FS is not set
800# CONFIG_CRAMFS is not set
801# CONFIG_VXFS_FS is not set
802# CONFIG_HPFS_FS is not set
803# CONFIG_QNX4FS_FS is not set
804# CONFIG_SYSV_FS is not set
805# CONFIG_UFS_FS is not set
806
807#
808# Network File Systems
809#
810CONFIG_NFS_FS=y
811CONFIG_NFS_V3=y
812# CONFIG_NFS_V4 is not set
813# CONFIG_NFS_DIRECTIO is not set
814CONFIG_NFSD=y
815CONFIG_NFSD_V3=y
816# CONFIG_NFSD_V4 is not set
817CONFIG_NFSD_TCP=y
818CONFIG_ROOT_NFS=y
819CONFIG_LOCKD=y
820CONFIG_LOCKD_V4=y
821CONFIG_EXPORTFS=y
822CONFIG_SUNRPC=y
823# CONFIG_SUNRPC_GSS is not set
824# CONFIG_SMB_FS is not set
825# CONFIG_CIFS is not set
826# CONFIG_NCP_FS is not set
827# CONFIG_CODA_FS is not set
828# CONFIG_AFS_FS is not set
829
830#
831# Partition Types
832#
833# CONFIG_PARTITION_ADVANCED is not set
834CONFIG_MSDOS_PARTITION=y
835
836#
837# Native Language Support
838#
839CONFIG_NLS=y
840CONFIG_NLS_DEFAULT="iso8859-1"
841# CONFIG_NLS_CODEPAGE_437 is not set
842# CONFIG_NLS_CODEPAGE_737 is not set
843# CONFIG_NLS_CODEPAGE_775 is not set
844# CONFIG_NLS_CODEPAGE_850 is not set
845# CONFIG_NLS_CODEPAGE_852 is not set
846# CONFIG_NLS_CODEPAGE_855 is not set
847# CONFIG_NLS_CODEPAGE_857 is not set
848# CONFIG_NLS_CODEPAGE_860 is not set
849# CONFIG_NLS_CODEPAGE_861 is not set
850# CONFIG_NLS_CODEPAGE_862 is not set
851# CONFIG_NLS_CODEPAGE_863 is not set
852# CONFIG_NLS_CODEPAGE_864 is not set
853# CONFIG_NLS_CODEPAGE_865 is not set
854# CONFIG_NLS_CODEPAGE_866 is not set
855# CONFIG_NLS_CODEPAGE_869 is not set
856# CONFIG_NLS_CODEPAGE_936 is not set
857# CONFIG_NLS_CODEPAGE_950 is not set
858# CONFIG_NLS_CODEPAGE_932 is not set
859# CONFIG_NLS_CODEPAGE_949 is not set
860# CONFIG_NLS_CODEPAGE_874 is not set
861# CONFIG_NLS_ISO8859_8 is not set
862# CONFIG_NLS_CODEPAGE_1250 is not set
863# CONFIG_NLS_CODEPAGE_1251 is not set
864# CONFIG_NLS_ISO8859_1 is not set
865# CONFIG_NLS_ISO8859_2 is not set
866# CONFIG_NLS_ISO8859_3 is not set
867# CONFIG_NLS_ISO8859_4 is not set
868# CONFIG_NLS_ISO8859_5 is not set
869# CONFIG_NLS_ISO8859_6 is not set
870# CONFIG_NLS_ISO8859_7 is not set
871# CONFIG_NLS_ISO8859_9 is not set
872# CONFIG_NLS_ISO8859_13 is not set
873# CONFIG_NLS_ISO8859_14 is not set
874# CONFIG_NLS_ISO8859_15 is not set
875# CONFIG_NLS_KOI8_R is not set
876# CONFIG_NLS_KOI8_U is not set
877# CONFIG_NLS_UTF8 is not set
878
879#
880# Profiling support
881#
882CONFIG_PROFILING=y
883CONFIG_OPROFILE=y
884
885#
886# Kernel hacking
887#
888CONFIG_DEBUG_KERNEL=y
889# CONFIG_DEBUG_SLAB is not set
890CONFIG_MAGIC_SYSRQ=y
891# CONFIG_DEBUG_SPINLOCK is not set
892# CONFIG_DEBUG_RWLOCK is not set
893CONFIG_FRAME_POINTER=y
894# CONFIG_DEBUG_INFO is not set
895
896#
897# Security options
898#
899# CONFIG_SECURITY is not set
900
901#
902# Cryptographic options
903#
904CONFIG_CRYPTO=y
905# CONFIG_CRYPTO_HMAC is not set
906# CONFIG_CRYPTO_NULL is not set
907# CONFIG_CRYPTO_MD4 is not set
908# CONFIG_CRYPTO_MD5 is not set
909# CONFIG_CRYPTO_SHA1 is not set
910# CONFIG_CRYPTO_SHA256 is not set
911# CONFIG_CRYPTO_SHA512 is not set
912# CONFIG_CRYPTO_DES is not set
913# CONFIG_CRYPTO_BLOWFISH is not set
914# CONFIG_CRYPTO_TWOFISH is not set
915# CONFIG_CRYPTO_SERPENT is not set
916# CONFIG_CRYPTO_AES is not set
917# CONFIG_CRYPTO_CAST5 is not set
918# CONFIG_CRYPTO_CAST6 is not set
919# CONFIG_CRYPTO_ARC4 is not set
920# CONFIG_CRYPTO_DEFLATE is not set
921# CONFIG_CRYPTO_TEST is not set
922
923#
924# Library routines
925#
926CONFIG_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 @@
1# This a generic Palo configuration file. For more information about how
2# it works try 'palo -?'.
3#
4# Most people using 'make palo' want a bootable file, usable for
5# network or tape booting for example.
6--init-tape=lifimage
7--recoverykernel=vmlinux
8
9########## Pick your ROOT here! ##########
10# You need at least one 'root='!
11#
12# If you want a root ramdisk, use the next 2 lines
13# (Edit the ramdisk image name!!!!)
14--ramdisk=ram-disk-image-file
15--commandline=0/vmlinux HOME=/ root=/dev/ram initrd=0/ramdisk
16
17# If you want NFS root, use the following command line (Edit the HOSTNAME!!!)
18#--commandline=0/vmlinux HOME=/ root=/dev/nfs nfsroot=HOSTNAME ip=bootp
19
20# If you have root on a disk partition, use this (Edit the partition name!!!)
21#--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 @@
1#
2# Makefile for HPUX emulation
3#
4
5obj-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 @@
1/* syscall table for HPUX specific syscalls
2 *
3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
4 * Copyright (C) 1999 Matthew Wilcox <willy at debian . org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/sys.h>
22#include <linux/linkage.h>
23#include <asm/unistd.h>
24
25 .text
26
27#define ENTRY_NAME(_name_) .word _name_
28
29 .align 4
30 .export hpux_call_table
31 .import hpux_unimplemented_wrapper
32hpux_call_table:
33 ENTRY_NAME(sys_ni_syscall) /* 0 */
34 ENTRY_NAME(sys_exit)
35 ENTRY_NAME(hpux_fork_wrapper)
36 ENTRY_NAME(sys_read)
37 ENTRY_NAME(sys_write)
38 ENTRY_NAME(sys_open) /* 5 */
39 ENTRY_NAME(sys_close)
40 ENTRY_NAME(hpux_wait)
41 ENTRY_NAME(sys_creat)
42 ENTRY_NAME(sys_link)
43 ENTRY_NAME(sys_unlink) /* 10 */
44 ENTRY_NAME(hpux_execv_wrapper)
45 ENTRY_NAME(sys_chdir)
46 ENTRY_NAME(sys_time)
47 ENTRY_NAME(sys_mknod)
48 ENTRY_NAME(sys_chmod) /* 15 */
49 ENTRY_NAME(sys_chown)
50 ENTRY_NAME(hpux_brk)
51 ENTRY_NAME(hpux_unimplemented_wrapper)
52 ENTRY_NAME(sys_lseek)
53 ENTRY_NAME(sys_getpid) /* 20 */
54 ENTRY_NAME(hpux_mount)
55 ENTRY_NAME(sys_oldumount)
56 ENTRY_NAME(sys_setuid)
57 ENTRY_NAME(sys_getuid)
58 ENTRY_NAME(sys_stime) /* 25 */
59 ENTRY_NAME(hpux_ptrace)
60 ENTRY_NAME(sys_alarm)
61 ENTRY_NAME(hpux_unimplemented_wrapper)
62 ENTRY_NAME(sys_pause)
63 ENTRY_NAME(sys_utime) /* 30 */
64 ENTRY_NAME(hpux_unimplemented_wrapper)
65 ENTRY_NAME(hpux_unimplemented_wrapper)
66 ENTRY_NAME(sys_access)
67 ENTRY_NAME(hpux_nice)
68 ENTRY_NAME(hpux_unimplemented_wrapper) /* 35 */
69 ENTRY_NAME(sys_sync)
70 ENTRY_NAME(hpux_unimplemented_wrapper)
71 ENTRY_NAME(sys_newstat)
72 ENTRY_NAME(hpux_setpgrp3)
73 ENTRY_NAME(sys_newlstat) /* 40 */
74 ENTRY_NAME(sys_dup)
75 ENTRY_NAME(hpux_pipe_wrapper)
76 ENTRY_NAME(sys_times)
77 ENTRY_NAME(hpux_unimplemented_wrapper)
78 ENTRY_NAME(hpux_unimplemented_wrapper) /* 45 */
79 ENTRY_NAME(sys_setgid)
80 ENTRY_NAME(sys_getgid)
81 ENTRY_NAME(hpux_unimplemented_wrapper)
82 ENTRY_NAME(hpux_unimplemented_wrapper)
83 ENTRY_NAME(hpux_unimplemented_wrapper) /* 50 */
84 ENTRY_NAME(hpux_unimplemented_wrapper)
85 ENTRY_NAME(hpux_unimplemented_wrapper)
86 ENTRY_NAME(hpux_unimplemented_wrapper)
87 ENTRY_NAME(hpux_ioctl)
88 ENTRY_NAME(hpux_unimplemented_wrapper) /* 55 */
89 ENTRY_NAME(sys_symlink)
90 ENTRY_NAME(hpux_utssys)
91 ENTRY_NAME(sys_readlink)
92 ENTRY_NAME(hpux_execve_wrapper)
93 ENTRY_NAME(sys_umask) /* 60 */
94 ENTRY_NAME(sys_chroot)
95 ENTRY_NAME(sys_fcntl)
96 ENTRY_NAME(hpux_unimplemented_wrapper)
97 ENTRY_NAME(hpux_unimplemented_wrapper)
98 ENTRY_NAME(hpux_unimplemented_wrapper) /* 65 */
99 ENTRY_NAME(hpux_unimplemented_wrapper)
100 ENTRY_NAME(hpux_unimplemented_wrapper)
101 ENTRY_NAME(hpux_unimplemented_wrapper)
102 ENTRY_NAME(hpux_sbrk)
103 ENTRY_NAME(hpux_unimplemented_wrapper) /* 70 */
104 ENTRY_NAME(sys_mmap)
105 ENTRY_NAME(hpux_unimplemented_wrapper)
106 ENTRY_NAME(hpux_unimplemented_wrapper)
107 ENTRY_NAME(hpux_unimplemented_wrapper)
108 ENTRY_NAME(hpux_unimplemented_wrapper) /* 75 */
109 ENTRY_NAME(hpux_unimplemented_wrapper)
110 ENTRY_NAME(hpux_unimplemented_wrapper)
111 ENTRY_NAME(hpux_unimplemented_wrapper)
112 ENTRY_NAME(hpux_unimplemented_wrapper)
113 ENTRY_NAME(hpux_unimplemented_wrapper) /* 80 */
114 ENTRY_NAME(sys_getpgid)
115 ENTRY_NAME(sys_setpgid)
116 ENTRY_NAME(sys_setitimer)
117 ENTRY_NAME(hpux_unimplemented_wrapper)
118 ENTRY_NAME(hpux_unimplemented_wrapper) /* 85 */
119 ENTRY_NAME(sys_getitimer)
120 ENTRY_NAME(hpux_unimplemented_wrapper)
121 ENTRY_NAME(hpux_unimplemented_wrapper)
122 ENTRY_NAME(hpux_unimplemented_wrapper)
123 ENTRY_NAME(sys_dup2) /* 90 */
124 ENTRY_NAME(hpux_unimplemented_wrapper)
125 ENTRY_NAME(sys_newfstat)
126 ENTRY_NAME(sys_select)
127 ENTRY_NAME(hpux_unimplemented_wrapper)
128 ENTRY_NAME(hpux_unimplemented_wrapper) /* 95 */
129 ENTRY_NAME(hpux_unimplemented_wrapper)
130 ENTRY_NAME(hpux_unimplemented_wrapper)
131 ENTRY_NAME(hpux_unimplemented_wrapper)
132 ENTRY_NAME(hpux_unimplemented_wrapper)
133 ENTRY_NAME(hpux_unimplemented_wrapper) /* 100 */
134 ENTRY_NAME(hpux_unimplemented_wrapper)
135 ENTRY_NAME(hpux_unimplemented_wrapper)
136 ENTRY_NAME(hpux_unimplemented_wrapper)
137 ENTRY_NAME(hpux_unimplemented_wrapper)
138 ENTRY_NAME(hpux_unimplemented_wrapper) /* 105 */
139 ENTRY_NAME(hpux_unimplemented_wrapper)
140 ENTRY_NAME(hpux_unimplemented_wrapper)
141 ENTRY_NAME(hpux_unimplemented_wrapper)
142 ENTRY_NAME(hpux_unimplemented_wrapper)
143 ENTRY_NAME(hpux_unimplemented_wrapper) /* 110 */
144 ENTRY_NAME(hpux_unimplemented_wrapper)
145 ENTRY_NAME(hpux_unimplemented_wrapper)
146 ENTRY_NAME(hpux_unimplemented_wrapper)
147 ENTRY_NAME(hpux_unimplemented_wrapper)
148 ENTRY_NAME(hpux_unimplemented_wrapper) /* 115 */
149 ENTRY_NAME(sys_gettimeofday)
150 ENTRY_NAME(hpux_unimplemented_wrapper)
151 ENTRY_NAME(hpux_unimplemented_wrapper)
152 ENTRY_NAME(hpux_unimplemented_wrapper)
153 ENTRY_NAME(hpux_unimplemented_wrapper) /* 120 */
154 ENTRY_NAME(hpux_unimplemented_wrapper)
155 ENTRY_NAME(hpux_unimplemented_wrapper)
156 ENTRY_NAME(sys_fchown)
157 ENTRY_NAME(sys_fchmod)
158 ENTRY_NAME(hpux_unimplemented_wrapper) /* 125 */
159 ENTRY_NAME(hpux_unimplemented_wrapper)
160 ENTRY_NAME(hpux_unimplemented_wrapper)
161 ENTRY_NAME(sys_rename)
162 ENTRY_NAME(hpux_unimplemented_wrapper)
163 ENTRY_NAME(hpux_unimplemented_wrapper) /* 130 */
164 ENTRY_NAME(hpux_unimplemented_wrapper)
165 ENTRY_NAME(hpux_sysconf)
166 ENTRY_NAME(hpux_unimplemented_wrapper)
167 ENTRY_NAME(hpux_unimplemented_wrapper)
168 ENTRY_NAME(hpux_unimplemented_wrapper) /* 135 */
169 ENTRY_NAME(sys_mkdir)
170 ENTRY_NAME(sys_rmdir)
171 ENTRY_NAME(hpux_unimplemented_wrapper)
172 ENTRY_NAME(hpux_unimplemented_wrapper)
173 ENTRY_NAME(hpux_unimplemented_wrapper) /* 140 */
174 ENTRY_NAME(hpux_unimplemented_wrapper)
175 ENTRY_NAME(hpux_unimplemented_wrapper)
176 ENTRY_NAME(hpux_unimplemented_wrapper)
177 ENTRY_NAME(sys_getrlimit)
178 ENTRY_NAME(sys_setrlimit) /* 145 */
179 ENTRY_NAME(hpux_unimplemented_wrapper)
180 ENTRY_NAME(hpux_unimplemented_wrapper)
181 ENTRY_NAME(hpux_unimplemented_wrapper)
182 ENTRY_NAME(hpux_unimplemented_wrapper)
183 ENTRY_NAME(hpux_unimplemented_wrapper) /* 150 */
184 ENTRY_NAME(hpux_unimplemented_wrapper)
185 ENTRY_NAME(hpux_unimplemented_wrapper)
186 ENTRY_NAME(hpux_unimplemented_wrapper)
187 ENTRY_NAME(hpux_unimplemented_wrapper)
188 ENTRY_NAME(hpux_lockf) /* 155 */
189 ENTRY_NAME(hpux_unimplemented_wrapper)
190 ENTRY_NAME(hpux_unimplemented_wrapper)
191 ENTRY_NAME(hpux_unimplemented_wrapper)
192 ENTRY_NAME(hpux_unimplemented_wrapper)
193 ENTRY_NAME(hpux_unimplemented_wrapper) /* 160 */
194 ENTRY_NAME(hpux_unimplemented_wrapper)
195 ENTRY_NAME(hpux_unimplemented_wrapper)
196 ENTRY_NAME(hpux_unimplemented_wrapper)
197 ENTRY_NAME(hpux_unimplemented_wrapper)
198 ENTRY_NAME(hpux_unimplemented_wrapper) /* 165 */
199 ENTRY_NAME(hpux_unimplemented_wrapper)
200 ENTRY_NAME(hpux_unimplemented_wrapper)
201 ENTRY_NAME(hpux_unimplemented_wrapper)
202 ENTRY_NAME(hpux_unimplemented_wrapper)
203 ENTRY_NAME(hpux_unimplemented_wrapper) /* 170 */
204 ENTRY_NAME(hpux_unimplemented_wrapper)
205 ENTRY_NAME(hpux_unimplemented_wrapper)
206 ENTRY_NAME(hpux_unimplemented_wrapper)
207 ENTRY_NAME(hpux_unimplemented_wrapper)
208 ENTRY_NAME(hpux_unimplemented_wrapper) /* 175 */
209 ENTRY_NAME(hpux_unimplemented_wrapper)
210 ENTRY_NAME(hpux_unimplemented_wrapper)
211 ENTRY_NAME(hpux_unimplemented_wrapper)
212 ENTRY_NAME(hpux_unimplemented_wrapper)
213 ENTRY_NAME(hpux_unimplemented_wrapper) /* 180 */
214 ENTRY_NAME(hpux_unimplemented_wrapper)
215 ENTRY_NAME(hpux_unimplemented_wrapper)
216 ENTRY_NAME(hpux_unimplemented_wrapper)
217 ENTRY_NAME(hpux_unimplemented_wrapper)
218 ENTRY_NAME(sys_sigprocmask) /* 185 */
219 ENTRY_NAME(hpux_unimplemented_wrapper)
220 ENTRY_NAME(hpux_unimplemented_wrapper)
221 ENTRY_NAME(hpux_unimplemented_wrapper)
222 ENTRY_NAME(hpux_unimplemented_wrapper)
223 ENTRY_NAME(hpux_unimplemented_wrapper) /* 190 */
224 ENTRY_NAME(hpux_unimplemented_wrapper)
225 ENTRY_NAME(hpux_getdomainname)
226 ENTRY_NAME(hpux_unimplemented_wrapper)
227 ENTRY_NAME(hpux_unimplemented_wrapper)
228 ENTRY_NAME(hpux_unimplemented_wrapper) /* 195 */
229 ENTRY_NAME(hpux_statfs)
230 ENTRY_NAME(hpux_fstatfs)
231 ENTRY_NAME(hpux_unimplemented_wrapper)
232 ENTRY_NAME(hpux_unimplemented_wrapper)
233 ENTRY_NAME(sys_waitpid) /* 200 */
234 ENTRY_NAME(hpux_unimplemented_wrapper)
235 ENTRY_NAME(hpux_unimplemented_wrapper)
236 ENTRY_NAME(hpux_unimplemented_wrapper)
237 ENTRY_NAME(hpux_unimplemented_wrapper)
238 ENTRY_NAME(hpux_unimplemented_wrapper) /* 205 */
239 ENTRY_NAME(hpux_unimplemented_wrapper)
240 ENTRY_NAME(hpux_unimplemented_wrapper)
241 ENTRY_NAME(hpux_unimplemented_wrapper)
242 ENTRY_NAME(hpux_unimplemented_wrapper)
243 ENTRY_NAME(hpux_unimplemented_wrapper) /* 210 */
244 ENTRY_NAME(hpux_unimplemented_wrapper)
245 ENTRY_NAME(hpux_unimplemented_wrapper)
246 ENTRY_NAME(hpux_unimplemented_wrapper)
247 ENTRY_NAME(hpux_unimplemented_wrapper)
248 ENTRY_NAME(hpux_unimplemented_wrapper) /* 215 */
249 ENTRY_NAME(hpux_unimplemented_wrapper)
250 ENTRY_NAME(hpux_unimplemented_wrapper)
251 ENTRY_NAME(hpux_unimplemented_wrapper)
252 ENTRY_NAME(hpux_unimplemented_wrapper)
253 ENTRY_NAME(hpux_unimplemented_wrapper) /* 220 */
254 ENTRY_NAME(hpux_unimplemented_wrapper)
255 ENTRY_NAME(hpux_unimplemented_wrapper)
256 ENTRY_NAME(hpux_unimplemented_wrapper)
257 ENTRY_NAME(hpux_unimplemented_wrapper)
258 ENTRY_NAME(hpux_unimplemented_wrapper) /* 225 */
259 ENTRY_NAME(hpux_unimplemented_wrapper)
260 ENTRY_NAME(hpux_unimplemented_wrapper)
261 ENTRY_NAME(hpux_unimplemented_wrapper)
262 ENTRY_NAME(hpux_unimplemented_wrapper)
263 ENTRY_NAME(hpux_unimplemented_wrapper) /* 230 */
264 ENTRY_NAME(hpux_unimplemented_wrapper)
265 ENTRY_NAME(hpux_unimplemented_wrapper)
266 ENTRY_NAME(hpux_unimplemented_wrapper)
267 ENTRY_NAME(hpux_unimplemented_wrapper)
268 ENTRY_NAME(hpux_unimplemented_wrapper) /* 235 */
269 ENTRY_NAME(hpux_unimplemented_wrapper)
270 ENTRY_NAME(hpux_unimplemented_wrapper)
271 ENTRY_NAME(hpux_unimplemented_wrapper)
272 ENTRY_NAME(hpux_unimplemented_wrapper)
273 ENTRY_NAME(hpux_unimplemented_wrapper) /* 240 */
274 ENTRY_NAME(hpux_unimplemented_wrapper)
275 ENTRY_NAME(hpux_unimplemented_wrapper)
276 ENTRY_NAME(hpux_unimplemented_wrapper)
277 ENTRY_NAME(hpux_unimplemented_wrapper)
278 ENTRY_NAME(hpux_unimplemented_wrapper) /* 245 */
279 ENTRY_NAME(hpux_unimplemented_wrapper)
280 ENTRY_NAME(hpux_unimplemented_wrapper)
281 ENTRY_NAME(hpux_unimplemented_wrapper)
282 ENTRY_NAME(hpux_unimplemented_wrapper)
283 ENTRY_NAME(hpux_unimplemented_wrapper) /* 250 */
284 ENTRY_NAME(hpux_unimplemented_wrapper)
285 ENTRY_NAME(hpux_unimplemented_wrapper)
286 ENTRY_NAME(hpux_unimplemented_wrapper)
287 ENTRY_NAME(hpux_unimplemented_wrapper)
288 ENTRY_NAME(hpux_unimplemented_wrapper) /* 255 */
289 ENTRY_NAME(hpux_unimplemented_wrapper)
290 ENTRY_NAME(hpux_unimplemented_wrapper)
291 ENTRY_NAME(hpux_unimplemented_wrapper)
292 ENTRY_NAME(hpux_unimplemented_wrapper)
293 ENTRY_NAME(hpux_unimplemented_wrapper) /* 260 */
294 ENTRY_NAME(hpux_unimplemented_wrapper)
295 ENTRY_NAME(hpux_unimplemented_wrapper)
296 ENTRY_NAME(hpux_unimplemented_wrapper)
297 ENTRY_NAME(hpux_unimplemented_wrapper)
298 ENTRY_NAME(hpux_unimplemented_wrapper) /* 265 */
299 ENTRY_NAME(hpux_unimplemented_wrapper)
300 ENTRY_NAME(hpux_unimplemented_wrapper)
301 ENTRY_NAME(hpux_unimplemented_wrapper)
302 ENTRY_NAME(hpux_unimplemented_wrapper)
303 ENTRY_NAME(hpux_unimplemented_wrapper) /* 270 */
304 ENTRY_NAME(hpux_unimplemented_wrapper)
305 ENTRY_NAME(sys_fchdir)
306 ENTRY_NAME(hpux_unimplemented_wrapper)
307 ENTRY_NAME(hpux_unimplemented_wrapper)
308 ENTRY_NAME(sys_accept) /* 275 */
309 ENTRY_NAME(sys_bind)
310 ENTRY_NAME(sys_connect)
311 ENTRY_NAME(sys_getpeername)
312 ENTRY_NAME(sys_getsockname)
313 ENTRY_NAME(sys_getsockopt) /* 280 */
314 ENTRY_NAME(sys_listen)
315 ENTRY_NAME(sys_recv)
316 ENTRY_NAME(sys_recvfrom)
317 ENTRY_NAME(sys_recvmsg)
318 ENTRY_NAME(sys_send) /* 285 */
319 ENTRY_NAME(sys_sendmsg)
320 ENTRY_NAME(sys_sendto)
321 ENTRY_NAME(sys_setsockopt)
322 ENTRY_NAME(sys_shutdown)
323 ENTRY_NAME(sys_socket) /* 290 */
324 ENTRY_NAME(hpux_unimplemented_wrapper)
325 ENTRY_NAME(hpux_unimplemented_wrapper)
326 ENTRY_NAME(hpux_unimplemented_wrapper)
327 ENTRY_NAME(hpux_unimplemented_wrapper)
328 ENTRY_NAME(hpux_unimplemented_wrapper) /* 295 */
329 ENTRY_NAME(hpux_unimplemented_wrapper)
330 ENTRY_NAME(hpux_unimplemented_wrapper)
331 ENTRY_NAME(hpux_unimplemented_wrapper)
332 ENTRY_NAME(hpux_unimplemented_wrapper)
333 ENTRY_NAME(hpux_unimplemented_wrapper) /* 300 */
334 ENTRY_NAME(hpux_unimplemented_wrapper)
335 ENTRY_NAME(hpux_unimplemented_wrapper)
336 ENTRY_NAME(hpux_unimplemented_wrapper)
337 ENTRY_NAME(hpux_unimplemented_wrapper)
338 ENTRY_NAME(hpux_unimplemented_wrapper) /* 305 */
339 ENTRY_NAME(hpux_unimplemented_wrapper)
340 ENTRY_NAME(hpux_unimplemented_wrapper)
341 ENTRY_NAME(hpux_unimplemented_wrapper)
342 ENTRY_NAME(hpux_unimplemented_wrapper)
343 ENTRY_NAME(hpux_unimplemented_wrapper) /* 310 */
344 ENTRY_NAME(hpux_unimplemented_wrapper)
345 ENTRY_NAME(hpux_unimplemented_wrapper)
346 ENTRY_NAME(hpux_unimplemented_wrapper)
347 ENTRY_NAME(hpux_unimplemented_wrapper)
348 ENTRY_NAME(hpux_unimplemented_wrapper) /* 315 */
349 ENTRY_NAME(hpux_unimplemented_wrapper)
350 ENTRY_NAME(hpux_unimplemented_wrapper)
351 ENTRY_NAME(hpux_unimplemented_wrapper)
352 ENTRY_NAME(hpux_unimplemented_wrapper)
353 ENTRY_NAME(hpux_unimplemented_wrapper) /* 320 */
354 ENTRY_NAME(hpux_unimplemented_wrapper)
355 ENTRY_NAME(hpux_unimplemented_wrapper)
356 ENTRY_NAME(hpux_unimplemented_wrapper)
357 ENTRY_NAME(hpux_unimplemented_wrapper)
358 ENTRY_NAME(hpux_unimplemented_wrapper) /* 325 */
359 ENTRY_NAME(hpux_unimplemented_wrapper)
360 ENTRY_NAME(hpux_unimplemented_wrapper)
361 ENTRY_NAME(hpux_unimplemented_wrapper)
362 ENTRY_NAME(hpux_unimplemented_wrapper)
363 ENTRY_NAME(hpux_unimplemented_wrapper) /* 330 */
364 ENTRY_NAME(hpux_unimplemented_wrapper)
365 ENTRY_NAME(sys_lchown)
366 ENTRY_NAME(hpux_unimplemented_wrapper)
367 ENTRY_NAME(hpux_sysfs)
368 ENTRY_NAME(hpux_unimplemented_wrapper) /* 335 */
369 ENTRY_NAME(hpux_unimplemented_wrapper)
370 ENTRY_NAME(hpux_unimplemented_wrapper)
371 ENTRY_NAME(hpux_unimplemented_wrapper)
372 ENTRY_NAME(hpux_unimplemented_wrapper)
373 ENTRY_NAME(hpux_unimplemented_wrapper) /* 340 */
374 ENTRY_NAME(hpux_unimplemented_wrapper)
375 ENTRY_NAME(hpux_unimplemented_wrapper)
376 ENTRY_NAME(hpux_unimplemented_wrapper)
377 ENTRY_NAME(hpux_unimplemented_wrapper)
378 ENTRY_NAME(hpux_unimplemented_wrapper) /* 345 */
379 ENTRY_NAME(hpux_unimplemented_wrapper)
380 ENTRY_NAME(hpux_unimplemented_wrapper)
381 ENTRY_NAME(hpux_unimplemented_wrapper)
382 ENTRY_NAME(hpux_unimplemented_wrapper)
383 ENTRY_NAME(hpux_unimplemented_wrapper) /* 350 */
384 ENTRY_NAME(hpux_unimplemented_wrapper)
385 ENTRY_NAME(hpux_unimplemented_wrapper)
386 ENTRY_NAME(sys_nanosleep)
387 ENTRY_NAME(hpux_unimplemented_wrapper)
388 ENTRY_NAME(hpux_unimplemented_wrapper) /* 355 */
389 ENTRY_NAME(hpux_getdents)
390 ENTRY_NAME(hpux_unimplemented_wrapper)
391 ENTRY_NAME(hpux_unimplemented_wrapper)
392 ENTRY_NAME(hpux_unimplemented_wrapper)
393 ENTRY_NAME(hpux_unimplemented_wrapper) /* 360 */
394 ENTRY_NAME(hpux_fstat64)
395 ENTRY_NAME(hpux_unimplemented_wrapper)
396 ENTRY_NAME(hpux_unimplemented_wrapper)
397 ENTRY_NAME(hpux_unimplemented_wrapper)
398 ENTRY_NAME(hpux_unimplemented_wrapper) /* 365 */
399 ENTRY_NAME(hpux_lstat64)
400 ENTRY_NAME(hpux_unimplemented_wrapper)
401 ENTRY_NAME(hpux_unimplemented_wrapper)
402 ENTRY_NAME(hpux_stat64)
403 ENTRY_NAME(hpux_unimplemented_wrapper) /* 370 */
404 ENTRY_NAME(hpux_unimplemented_wrapper)
405 ENTRY_NAME(hpux_unimplemented_wrapper)
406 ENTRY_NAME(hpux_unimplemented_wrapper)
407 ENTRY_NAME(hpux_unimplemented_wrapper)
408 ENTRY_NAME(hpux_unimplemented_wrapper) /* 375 */
409 ENTRY_NAME(hpux_unimplemented_wrapper)
410 ENTRY_NAME(hpux_unimplemented_wrapper)
411 ENTRY_NAME(hpux_unimplemented_wrapper)
412 ENTRY_NAME(hpux_unimplemented_wrapper)
413 ENTRY_NAME(hpux_unimplemented_wrapper) /* 380 */
414 ENTRY_NAME(hpux_unimplemented_wrapper)
415 ENTRY_NAME(hpux_unimplemented_wrapper)
416 ENTRY_NAME(hpux_setpgrp)
417 ENTRY_NAME(hpux_unimplemented_wrapper)
418 ENTRY_NAME(hpux_unimplemented_wrapper) /* 385 */
419 ENTRY_NAME(hpux_unimplemented_wrapper)
420 ENTRY_NAME(hpux_unimplemented_wrapper)
421 ENTRY_NAME(hpux_unimplemented_wrapper)
422 ENTRY_NAME(hpux_unimplemented_wrapper)
423 ENTRY_NAME(hpux_unimplemented_wrapper) /* 390 */
424 ENTRY_NAME(hpux_unimplemented_wrapper)
425 ENTRY_NAME(hpux_unimplemented_wrapper)
426 ENTRY_NAME(hpux_unimplemented_wrapper)
427 ENTRY_NAME(hpux_unimplemented_wrapper)
428 ENTRY_NAME(hpux_unimplemented_wrapper) /* 395 */
429 ENTRY_NAME(hpux_unimplemented_wrapper)
430 ENTRY_NAME(hpux_unimplemented_wrapper)
431 ENTRY_NAME(hpux_unimplemented_wrapper)
432 ENTRY_NAME(hpux_unimplemented_wrapper)
433 ENTRY_NAME(hpux_unimplemented_wrapper) /* 400 */
434 ENTRY_NAME(hpux_unimplemented_wrapper)
435 ENTRY_NAME(hpux_unimplemented_wrapper)
436 ENTRY_NAME(hpux_unimplemented_wrapper)
437 ENTRY_NAME(hpux_unimplemented_wrapper)
438 ENTRY_NAME(hpux_unimplemented_wrapper) /* 405 */
439 ENTRY_NAME(hpux_unimplemented_wrapper)
440 ENTRY_NAME(hpux_unimplemented_wrapper)
441 ENTRY_NAME(hpux_unimplemented_wrapper)
442 ENTRY_NAME(hpux_unimplemented_wrapper)
443 ENTRY_NAME(hpux_unimplemented_wrapper) /* 410 */
444 ENTRY_NAME(hpux_unimplemented_wrapper)
445 ENTRY_NAME(hpux_unimplemented_wrapper)
446 ENTRY_NAME(hpux_unimplemented_wrapper)
447 ENTRY_NAME(hpux_unimplemented_wrapper)
448 ENTRY_NAME(hpux_unimplemented_wrapper) /* 415 */
449 ENTRY_NAME(hpux_unimplemented_wrapper)
450 ENTRY_NAME(hpux_unimplemented_wrapper)
451 ENTRY_NAME(hpux_unimplemented_wrapper)
452 ENTRY_NAME(hpux_unimplemented_wrapper)
453 ENTRY_NAME(hpux_unimplemented_wrapper) /* 420 */
454 ENTRY_NAME(hpux_unimplemented_wrapper)
455 ENTRY_NAME(hpux_unimplemented_wrapper)
456 ENTRY_NAME(hpux_unimplemented_wrapper)
457 ENTRY_NAME(hpux_unimplemented_wrapper)
458 ENTRY_NAME(hpux_unimplemented_wrapper) /* 425 */
459 ENTRY_NAME(hpux_unimplemented_wrapper)
460 ENTRY_NAME(hpux_unimplemented_wrapper)
461 ENTRY_NAME(hpux_unimplemented_wrapper)
462 ENTRY_NAME(hpux_unimplemented_wrapper)
463 ENTRY_NAME(hpux_unimplemented_wrapper) /* 430 */
464 ENTRY_NAME(hpux_unimplemented_wrapper)
465 ENTRY_NAME(hpux_unimplemented_wrapper)
466 ENTRY_NAME(hpux_unimplemented_wrapper)
467 ENTRY_NAME(hpux_unimplemented_wrapper)
468 ENTRY_NAME(hpux_unimplemented_wrapper) /* 435 */
469 ENTRY_NAME(hpux_unimplemented_wrapper)
470 ENTRY_NAME(hpux_unimplemented_wrapper)
471 ENTRY_NAME(hpux_unimplemented_wrapper)
472 ENTRY_NAME(hpux_unimplemented_wrapper)
473 ENTRY_NAME(hpux_unimplemented_wrapper) /* 440 */
474 ENTRY_NAME(hpux_unimplemented_wrapper)
475 ENTRY_NAME(hpux_unimplemented_wrapper)
476 ENTRY_NAME(hpux_unimplemented_wrapper)
477 ENTRY_NAME(hpux_unimplemented_wrapper)
478 ENTRY_NAME(hpux_unimplemented_wrapper) /* 445 */
479 ENTRY_NAME(hpux_unimplemented_wrapper)
480 ENTRY_NAME(hpux_unimplemented_wrapper)
481 ENTRY_NAME(hpux_unimplemented_wrapper)
482 ENTRY_NAME(hpux_unimplemented_wrapper)
483 ENTRY_NAME(hpux_unimplemented_wrapper) /* 450 */
484 ENTRY_NAME(hpux_unimplemented_wrapper)
485 ENTRY_NAME(hpux_unimplemented_wrapper)
486 ENTRY_NAME(hpux_unimplemented_wrapper)
487 ENTRY_NAME(hpux_unimplemented_wrapper)
488 ENTRY_NAME(hpux_unimplemented_wrapper) /* 455 */
489 ENTRY_NAME(hpux_unimplemented_wrapper)
490 ENTRY_NAME(hpux_unimplemented_wrapper)
491 ENTRY_NAME(hpux_unimplemented_wrapper)
492 ENTRY_NAME(hpux_unimplemented_wrapper)
493 ENTRY_NAME(hpux_unimplemented_wrapper) /* 460 */
494 ENTRY_NAME(hpux_unimplemented_wrapper)
495 ENTRY_NAME(hpux_unimplemented_wrapper)
496 ENTRY_NAME(hpux_unimplemented_wrapper)
497 ENTRY_NAME(hpux_unimplemented_wrapper)
498 ENTRY_NAME(hpux_unimplemented_wrapper) /* 465 */
499 ENTRY_NAME(hpux_unimplemented_wrapper)
500 ENTRY_NAME(hpux_unimplemented_wrapper)
501 ENTRY_NAME(hpux_unimplemented_wrapper)
502 ENTRY_NAME(hpux_unimplemented_wrapper)
503 ENTRY_NAME(hpux_unimplemented_wrapper) /* 470 */
504 ENTRY_NAME(hpux_unimplemented_wrapper)
505 ENTRY_NAME(hpux_unimplemented_wrapper)
506 ENTRY_NAME(hpux_unimplemented_wrapper)
507 ENTRY_NAME(hpux_unimplemented_wrapper)
508 ENTRY_NAME(hpux_unimplemented_wrapper) /* 475 */
509 ENTRY_NAME(hpux_unimplemented_wrapper)
510 ENTRY_NAME(hpux_unimplemented_wrapper)
511 ENTRY_NAME(hpux_unimplemented_wrapper)
512 ENTRY_NAME(hpux_unimplemented_wrapper)
513 ENTRY_NAME(hpux_unimplemented_wrapper) /* 480 */
514 ENTRY_NAME(hpux_unimplemented_wrapper)
515 ENTRY_NAME(hpux_unimplemented_wrapper)
516 ENTRY_NAME(hpux_unimplemented_wrapper)
517 ENTRY_NAME(hpux_unimplemented_wrapper)
518 ENTRY_NAME(hpux_unimplemented_wrapper) /* 485 */
519 ENTRY_NAME(hpux_unimplemented_wrapper)
520 ENTRY_NAME(hpux_unimplemented_wrapper)
521 ENTRY_NAME(hpux_unimplemented_wrapper)
522 ENTRY_NAME(hpux_unimplemented_wrapper)
523 ENTRY_NAME(hpux_unimplemented_wrapper) /* 490 */
524 ENTRY_NAME(hpux_unimplemented_wrapper)
525 ENTRY_NAME(hpux_unimplemented_wrapper)
526 ENTRY_NAME(hpux_unimplemented_wrapper)
527 ENTRY_NAME(hpux_unimplemented_wrapper)
528 ENTRY_NAME(hpux_unimplemented_wrapper) /* 495 */
529 ENTRY_NAME(hpux_unimplemented_wrapper)
530 ENTRY_NAME(hpux_unimplemented_wrapper)
531 ENTRY_NAME(hpux_unimplemented_wrapper)
532 ENTRY_NAME(hpux_unimplemented_wrapper)
533 ENTRY_NAME(hpux_unimplemented_wrapper) /* 500 */
534 ENTRY_NAME(hpux_unimplemented_wrapper)
535 ENTRY_NAME(hpux_unimplemented_wrapper)
536 ENTRY_NAME(hpux_unimplemented_wrapper)
537 ENTRY_NAME(hpux_unimplemented_wrapper)
538 ENTRY_NAME(hpux_unimplemented_wrapper) /* 505 */
539 ENTRY_NAME(hpux_unimplemented_wrapper)
540 ENTRY_NAME(hpux_unimplemented_wrapper)
541 ENTRY_NAME(hpux_unimplemented_wrapper)
542 ENTRY_NAME(hpux_unimplemented_wrapper)
543 ENTRY_NAME(hpux_unimplemented_wrapper) /* 510 */
544 ENTRY_NAME(hpux_unimplemented_wrapper)
545 ENTRY_NAME(hpux_unimplemented_wrapper)
546.end
547
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 @@
1/*
2 * Implements HPUX syscalls.
3 *
4 * Copyright (C) 1999 Matthew Wilcox <willy with parisc-linux.org>
5 * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
6 * Copyright (C) 2000 John Marvin <jsm with parisc-linux.org>
7 * Copyright (C) 2000 Philipp Rumpf
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <linux/mm.h>
25#include <linux/sched.h>
26#include <linux/file.h>
27#include <linux/smp_lock.h>
28#include <linux/slab.h>
29#include <linux/ptrace.h>
30#include <asm/errno.h>
31#include <asm/uaccess.h>
32
33int hpux_execve(struct pt_regs *regs)
34{
35 int error;
36 char *filename;
37
38 filename = getname((char *) regs->gr[26]);
39 error = PTR_ERR(filename);
40 if (IS_ERR(filename))
41 goto out;
42
43 error = do_execve(filename, (char **) regs->gr[25],
44 (char **)regs->gr[24], regs);
45
46 if (error == 0) {
47 task_lock(current);
48 current->ptrace &= ~PT_DTRACE;
49 task_unlock(current);
50 }
51 putname(filename);
52
53out:
54 return error;
55}
56
57struct hpux_dirent {
58 loff_t d_off;
59 ino_t d_ino;
60 short d_reclen;
61 short d_namlen;
62 char d_name[1];
63};
64
65struct getdents_callback {
66 struct hpux_dirent *current_dir;
67 struct hpux_dirent *previous;
68 int count;
69 int error;
70};
71
72#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
73#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
74
75static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
76 ino_t ino, unsigned d_type)
77{
78 struct hpux_dirent * dirent;
79 struct getdents_callback * buf = (struct getdents_callback *) __buf;
80 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
81
82 buf->error = -EINVAL; /* only used if we fail.. */
83 if (reclen > buf->count)
84 return -EINVAL;
85 dirent = buf->previous;
86 if (dirent)
87 put_user(offset, &dirent->d_off);
88 dirent = buf->current_dir;
89 buf->previous = dirent;
90 put_user(ino, &dirent->d_ino);
91 put_user(reclen, &dirent->d_reclen);
92 put_user(namlen, &dirent->d_namlen);
93 copy_to_user(dirent->d_name, name, namlen);
94 put_user(0, dirent->d_name + namlen);
95 ((char *) dirent) += reclen;
96 buf->current_dir = dirent;
97 buf->count -= reclen;
98 return 0;
99}
100
101#undef NAME_OFFSET
102#undef ROUND_UP
103
104int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count)
105{
106 struct file * file;
107 struct hpux_dirent * lastdirent;
108 struct getdents_callback buf;
109 int error = -EBADF;
110
111 file = fget(fd);
112 if (!file)
113 goto out;
114
115 buf.current_dir = dirent;
116 buf.previous = NULL;
117 buf.count = count;
118 buf.error = 0;
119
120 error = vfs_readdir(file, filldir, &buf);
121 if (error < 0)
122 goto out_putf;
123 error = buf.error;
124 lastdirent = buf.previous;
125 if (lastdirent) {
126 put_user(file->f_pos, &lastdirent->d_off);
127 error = count - buf.count;
128 }
129
130out_putf:
131 fput(file);
132out:
133 return error;
134}
135
136int hpux_mount(const char *fs, const char *path, int mflag,
137 const char *fstype, const char *dataptr, int datalen)
138{
139 return -ENOSYS;
140}
141
142static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf)
143{
144 struct hpux_stat64 tmp;
145
146 /* we probably want a different split here - is hpux 12:20? */
147
148 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
149 return -EOVERFLOW;
150
151 memset(&tmp, 0, sizeof(tmp));
152 tmp.st_dev = new_encode_dev(stat->dev);
153 tmp.st_ino = stat->ino;
154 tmp.st_mode = stat->mode;
155 tmp.st_nlink = stat->nlink;
156 tmp.st_uid = stat->uid;
157 tmp.st_gid = stat->gid;
158 tmp.st_rdev = new_encode_dev(stat->rdev);
159 tmp.st_size = stat->size;
160 tmp.st_atime = stat->atime.tv_sec;
161 tmp.st_mtime = stat->mtime.tv_sec;
162 tmp.st_ctime = stat->ctime.tv_sec;
163 tmp.st_blocks = stat->blocks;
164 tmp.st_blksize = stat->blksize;
165 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
166}
167
168long hpux_stat64(char *filename, struct hpux_stat64 *statbuf)
169{
170 struct kstat stat;
171 int error = vfs_stat(filename, &stat);
172
173 if (!error)
174 error = cp_hpux_stat(&stat, statbuf);
175
176 return error;
177}
178
179long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
180{
181 struct kstat stat;
182 int error = vfs_fstat(fd, &stat);
183
184 if (!error)
185 error = cp_hpux_stat(&stat, statbuf);
186
187 return error;
188}
189
190long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf)
191{
192 struct kstat stat;
193 int error = vfs_lstat(filename, &stat);
194
195 if (!error)
196 error = cp_hpux_stat(&stat, statbuf);
197
198 return error;
199}
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 @@
1/*
2 *
3 * Linux/PARISC Project (http://www.parisc-linux.org/)
4 *
5 * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
6 * Licensed under the GNU GPL.
7 * thanks to Philipp Rumpf, Mike Shaver and various others
8 * sorry about the wall, puffin..
9 */
10
11#include <asm/assembly.h>
12#include <asm/offsets.h>
13#include <asm/unistd.h>
14#include <asm/errno.h>
15
16#ifdef __LP64__
17 .level 2.0w
18#else
19 .level 1.1
20#endif
21 .text
22
23#ifdef __LP64__
24#define FRAME_SIZE 128
25#else
26#define FRAME_SIZE 64
27#endif
28 .import hpux_call_table
29 .import hpux_syscall_exit,code
30 .export hpux_gateway_page
31
32 .align 4096
33hpux_gateway_page:
34 nop
35#ifdef __LP64__
36#warning NEEDS WORK for 64-bit
37#endif
38 ldw -64(%r30), %r29 ;! 8th argument
39 ldw -60(%r30), %r19 ;! 7th argument
40 ldw -56(%r30), %r20 ;! 6th argument
41 ldw -52(%r30), %r21 ;! 5th argument
42 gate .+8, %r0 /* become privileged */
43 mtsp %r0,%sr4 /* get kernel space into sr4 */
44 mtsp %r0,%sr5 /* get kernel space into sr5 */
45 mtsp %r0,%sr6 /* get kernel space into sr6 */
46 mfsp %sr7,%r1 /* save user sr7 */
47 mtsp %r1,%sr3 /* and store it in sr3 */
48
49 mtctl %r30,%cr28
50 mfctl %cr30,%r1
51 xor %r1,%r30,%r30 /* ye olde xor trick */
52 xor %r1,%r30,%r1
53 xor %r1,%r30,%r30
54 ldo TASK_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */
55
56 /* N.B.: It is critical that we don't set sr7 to 0 until r30
57 * contains a valid kernel stack pointer. It is also
58 * critical that we don't start using the kernel stack
59 * until after sr7 has been set to 0.
60 */
61
62 mtsp %r0,%sr7 /* get kernel space into sr7 */
63 STREG %r1,TASK_PT_GR30-TASK_SZ_ALGN-FRAME_SIZE(%r30) /* save usp */
64 ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr in %r1 */
65
66 /* Save some registers for sigcontext and potential task
67 switch (see entry.S for the details of which ones are
68 saved/restored). TASK_PT_PSW is zeroed so we can see whether
69 a process is on a syscall or not. For an interrupt the real
70 PSW value is stored. This is needed for gdb and sys_ptrace. */
71 STREG %r0, TASK_PT_PSW(%r1)
72 STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
73 STREG %r19, TASK_PT_GR19(%r1) /* 7th argument */
74 STREG %r20, TASK_PT_GR20(%r1) /* 6th argument */
75 STREG %r21, TASK_PT_GR21(%r1) /* 5th argument */
76 STREG %r22, TASK_PT_GR22(%r1) /* syscall # */
77 STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */
78 STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */
79 STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */
80 STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
81 STREG %r27, TASK_PT_GR27(%r1) /* user dp */
82 STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
83 STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */
84 STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */
85 STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
86
87 ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */
88 save_fp %r27 /* or potential task switch */
89
90 mfctl %cr11, %r27 /* i.e. SAR */
91 STREG %r27, TASK_PT_SAR(%r1)
92
93 loadgp
94
95 stw %r21, -52(%r30) ;! 5th argument
96 stw %r20, -56(%r30) ;! 6th argument
97 stw %r19, -60(%r30) ;! 7th argument
98 stw %r29, -64(%r30) ;! 8th argument
99
100 ldil L%hpux_call_table, %r21
101 ldo R%hpux_call_table(%r21), %r21
102 comiclr,>>= __NR_HPUX_syscalls, %r22, %r0
103 b,n syscall_nosys
104 ldwx,s %r22(%r21), %r21
105 ldil L%hpux_syscall_exit,%r2
106 be 0(%sr7,%r21)
107 ldo R%hpux_syscall_exit(%r2),%r2
108
109syscall_nosys:
110 ldil L%hpux_syscall_exit,%r1
111 be R%hpux_syscall_exit(%sr7,%r1)
112 ldo -ENOSYS(%r0),%r28
113
114 .align 4096
115 .export end_hpux_gateway_page
116end_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 @@
1/*
2 * Implements some necessary HPUX ioctls.
3 *
4 * Copyright (C) 1999-2002 Matthew Wilcox <willy with parisc-linux.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * Supported ioctls:
23 * TCGETA
24 * TCSETA
25 * TCSETAW
26 * TCSETAF
27 * TCSBRK
28 * TCXONC
29 * TCFLSH
30 * TIOCGWINSZ
31 * TIOCSWINSZ
32 * TIOCGPGRP
33 * TIOCSPGRP
34 */
35
36#include <linux/sched.h>
37#include <linux/smp_lock.h>
38#include <linux/syscalls.h>
39#include <asm/errno.h>
40#include <asm/ioctl.h>
41#include <asm/termios.h>
42#include <asm/uaccess.h>
43
44static int hpux_ioctl_t(int fd, unsigned long cmd, unsigned long arg)
45{
46 int result = -EOPNOTSUPP;
47 int nr = _IOC_NR(cmd);
48 switch (nr) {
49 case 106:
50 result = sys_ioctl(fd, TIOCSWINSZ, arg);
51 break;
52 case 107:
53 result = sys_ioctl(fd, TIOCGWINSZ, arg);
54 break;
55 }
56 return result;
57}
58
59int hpux_ioctl(int fd, unsigned long cmd, unsigned long arg)
60{
61 int result = -EOPNOTSUPP;
62 int type = _IOC_TYPE(cmd);
63 switch (type) {
64 case 'T':
65 /* Our structures are now compatible with HPUX's */
66 result = sys_ioctl(fd, cmd, arg);
67 break;
68 case 't':
69 result = hpux_ioctl_t(fd, cmd, arg);
70 break;
71 }
72 return result;
73}
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 @@
1/*
2 * Implements HPUX syscalls.
3 *
4 * Copyright (C) 1999 Matthew Wilcox <willy with parisc-linux.org>
5 * Copyright (C) 2000 Philipp Rumpf
6 * Copyright (C) 2000 John Marvin <jsm with parisc-linux.org>
7 * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
8 * Copyright (C) 2001 Nathan Neulinger <nneul at umr.edu>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <linux/file.h>
26#include <linux/fs.h>
27#include <linux/namei.h>
28#include <linux/sched.h>
29#include <linux/slab.h>
30#include <linux/smp_lock.h>
31#include <linux/syscalls.h>
32#include <linux/utsname.h>
33#include <linux/vfs.h>
34#include <linux/vmalloc.h>
35
36#include <asm/errno.h>
37#include <asm/pgalloc.h>
38#include <asm/uaccess.h>
39
40unsigned long hpux_brk(unsigned long addr)
41{
42 /* Sigh. Looks like HP/UX libc relies on kernel bugs. */
43 return sys_brk(addr + PAGE_SIZE);
44}
45
46int hpux_sbrk(void)
47{
48 return -ENOSYS;
49}
50
51/* Random other syscalls */
52
53int hpux_nice(int priority_change)
54{
55 return -ENOSYS;
56}
57
58int hpux_ptrace(void)
59{
60 return -ENOSYS;
61}
62
63int hpux_wait(int *stat_loc)
64{
65 return sys_waitpid(-1, stat_loc, 0);
66}
67
68int hpux_setpgrp(void)
69{
70 return sys_setpgid(0,0);
71}
72
73int hpux_setpgrp3(void)
74{
75 return hpux_setpgrp();
76}
77
78#define _SC_CPU_VERSION 10001
79#define _SC_OPEN_MAX 4
80#define CPU_PA_RISC1_1 0x210
81
82int hpux_sysconf(int which)
83{
84 switch (which) {
85 case _SC_CPU_VERSION:
86 return CPU_PA_RISC1_1;
87 case _SC_OPEN_MAX:
88 return INT_MAX;
89 default:
90 return -EINVAL;
91 }
92}
93
94/*****************************************************************************/
95
96#define HPUX_UTSLEN 9
97#define HPUX_SNLEN 15
98
99struct hpux_utsname {
100 char sysname[HPUX_UTSLEN];
101 char nodename[HPUX_UTSLEN];
102 char release[HPUX_UTSLEN];
103 char version[HPUX_UTSLEN];
104 char machine[HPUX_UTSLEN];
105 char idnumber[HPUX_SNLEN];
106} ;
107
108struct hpux_ustat {
109 int32_t f_tfree; /* total free (daddr_t) */
110 u_int32_t f_tinode; /* total inodes free (ino_t) */
111 char f_fname[6]; /* filsys name */
112 char f_fpack[6]; /* filsys pack name */
113 u_int32_t f_blksize; /* filsys block size (int) */
114};
115
116/*
117 * HPUX's utssys() call. It's a collection of miscellaneous functions,
118 * alas, so there's no nice way of splitting them up.
119 */
120
121/* This function is called from hpux_utssys(); HP-UX implements
122 * ustat() as an option to utssys().
123 *
124 * Now, struct ustat on HP-UX is exactly the same as on Linux, except
125 * that it contains one addition field on the end, int32_t f_blksize.
126 * So, we could have written this function to just call the Linux
127 * sys_ustat(), (defined in linux/fs/super.c), and then just
128 * added this additional field to the user's structure. But I figure
129 * if we're gonna be digging through filesystem structures to get
130 * this, we might as well just do the whole enchilada all in one go.
131 *
132 * So, most of this function is almost identical to sys_ustat().
133 * I have placed comments at the few lines changed or added, to
134 * aid in porting forward if and when sys_ustat() is changed from
135 * its form in kernel 2.2.5.
136 */
137static int hpux_ustat(dev_t dev, struct hpux_ustat __user *ubuf)
138{
139 struct super_block *s;
140 struct hpux_ustat tmp; /* Changed to hpux_ustat */
141 struct kstatfs sbuf;
142 int err = -EINVAL;
143
144 s = user_get_super(dev);
145 if (s == NULL)
146 goto out;
147 err = vfs_statfs(s, &sbuf);
148 drop_super(s);
149 if (err)
150 goto out;
151
152 memset(&tmp,0,sizeof(tmp));
153
154 tmp.f_tfree = (int32_t)sbuf.f_bfree;
155 tmp.f_tinode = (u_int32_t)sbuf.f_ffree;
156 tmp.f_blksize = (u_int32_t)sbuf.f_bsize; /* Added this line */
157
158 err = copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
159out:
160 return err;
161}
162
163/*
164 * Wrapper for hpux statfs call. At the moment, just calls the linux native one
165 * and ignores the extra fields at the end of the hpux statfs struct.
166 *
167 */
168
169typedef int32_t hpux_fsid_t[2]; /* file system ID type */
170typedef uint16_t hpux_site_t;
171
172struct hpux_statfs {
173 int32_t f_type; /* type of info, zero for now */
174 int32_t f_bsize; /* fundamental file system block size */
175 int32_t f_blocks; /* total blocks in file system */
176 int32_t f_bfree; /* free block in fs */
177 int32_t f_bavail; /* free blocks avail to non-superuser */
178 int32_t f_files; /* total file nodes in file system */
179 int32_t f_ffree; /* free file nodes in fs */
180 hpux_fsid_t f_fsid; /* file system ID */
181 int32_t f_magic; /* file system magic number */
182 int32_t f_featurebits; /* file system features */
183 int32_t f_spare[4]; /* spare for later */
184 hpux_site_t f_cnode; /* cluster node where mounted */
185 int16_t f_pad;
186};
187
188static int vfs_statfs_hpux(struct super_block *sb, struct hpux_statfs *buf)
189{
190 struct kstatfs st;
191 int retval;
192
193 retval = vfs_statfs(sb, &st);
194 if (retval)
195 return retval;
196
197 memset(buf, 0, sizeof(*buf));
198 buf->f_type = st.f_type;
199 buf->f_bsize = st.f_bsize;
200 buf->f_blocks = st.f_blocks;
201 buf->f_bfree = st.f_bfree;
202 buf->f_bavail = st.f_bavail;
203 buf->f_files = st.f_files;
204 buf->f_ffree = st.f_ffree;
205 buf->f_fsid[0] = st.f_fsid.val[0];
206 buf->f_fsid[1] = st.f_fsid.val[1];
207
208 return 0;
209}
210
211/* hpux statfs */
212asmlinkage long hpux_statfs(const char __user *path,
213 struct hpux_statfs __user *buf)
214{
215 struct nameidata nd;
216 int error;
217
218 error = user_path_walk(path, &nd);
219 if (!error) {
220 struct hpux_statfs tmp;
221 error = vfs_statfs_hpux(nd.dentry->d_inode->i_sb, &tmp);
222 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
223 error = -EFAULT;
224 path_release(&nd);
225 }
226 return error;
227}
228
229asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
230{
231 struct file *file;
232 struct hpux_statfs tmp;
233 int error;
234
235 error = -EBADF;
236 file = fget(fd);
237 if (!file)
238 goto out;
239 error = vfs_statfs_hpux(file->f_dentry->d_inode->i_sb, &tmp);
240 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
241 error = -EFAULT;
242 fput(file);
243 out:
244 return error;
245}
246
247
248/* This function is called from hpux_utssys(); HP-UX implements
249 * uname() as an option to utssys().
250 *
251 * The form of this function is pretty much copied from sys_olduname(),
252 * defined in linux/arch/i386/kernel/sys_i386.c.
253 */
254/* TODO: Are these put_user calls OK? Should they pass an int?
255 * (I copied it from sys_i386.c like this.)
256 */
257static int hpux_uname(struct hpux_utsname *name)
258{
259 int error;
260
261 if (!name)
262 return -EFAULT;
263 if (!access_ok(VERIFY_WRITE,name,sizeof(struct hpux_utsname)))
264 return -EFAULT;
265
266 down_read(&uts_sem);
267
268 error = __copy_to_user(&name->sysname,&system_utsname.sysname,HPUX_UTSLEN-1);
269 error |= __put_user(0,name->sysname+HPUX_UTSLEN-1);
270 error |= __copy_to_user(&name->nodename,&system_utsname.nodename,HPUX_UTSLEN-1);
271 error |= __put_user(0,name->nodename+HPUX_UTSLEN-1);
272 error |= __copy_to_user(&name->release,&system_utsname.release,HPUX_UTSLEN-1);
273 error |= __put_user(0,name->release+HPUX_UTSLEN-1);
274 error |= __copy_to_user(&name->version,&system_utsname.version,HPUX_UTSLEN-1);
275 error |= __put_user(0,name->version+HPUX_UTSLEN-1);
276 error |= __copy_to_user(&name->machine,&system_utsname.machine,HPUX_UTSLEN-1);
277 error |= __put_user(0,name->machine+HPUX_UTSLEN-1);
278
279 up_read(&uts_sem);
280
281 /* HP-UX utsname has no domainname field. */
282
283 /* TODO: Implement idnumber!!! */
284#if 0
285 error |= __put_user(0,name->idnumber);
286 error |= __put_user(0,name->idnumber+HPUX_SNLEN-1);
287#endif
288
289 error = error ? -EFAULT : 0;
290
291 return error;
292}
293
294/* Note: HP-UX just uses the old suser() function to check perms
295 * in this system call. We'll use capable(CAP_SYS_ADMIN).
296 */
297int hpux_utssys(char *ubuf, int n, int type)
298{
299 int len;
300 int error;
301 switch( type ) {
302 case 0:
303 /* uname(): */
304 return( hpux_uname( (struct hpux_utsname *)ubuf ) );
305 break ;
306 case 1:
307 /* Obsolete (used to be umask().) */
308 return -EFAULT ;
309 break ;
310 case 2:
311 /* ustat(): */
312 return( hpux_ustat(new_decode_dev(n), (struct hpux_ustat *)ubuf) );
313 break ;
314 case 3:
315 /* setuname():
316 *
317 * On linux (unlike HP-UX), utsname.nodename
318 * is the same as the hostname.
319 *
320 * sys_sethostname() is defined in linux/kernel/sys.c.
321 */
322 if (!capable(CAP_SYS_ADMIN))
323 return -EPERM;
324 /* Unlike Linux, HP-UX returns an error if n==0: */
325 if ( n <= 0 )
326 return -EINVAL ;
327 /* Unlike Linux, HP-UX truncates it if n is too big: */
328 len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
329 return( sys_sethostname(ubuf, len) );
330 break ;
331 case 4:
332 /* sethostname():
333 *
334 * sys_sethostname() is defined in linux/kernel/sys.c.
335 */
336 if (!capable(CAP_SYS_ADMIN))
337 return -EPERM;
338 /* Unlike Linux, HP-UX returns an error if n==0: */
339 if ( n <= 0 )
340 return -EINVAL ;
341 /* Unlike Linux, HP-UX truncates it if n is too big: */
342 len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
343 return( sys_sethostname(ubuf, len) );
344 break ;
345 case 5:
346 /* gethostname():
347 *
348 * sys_gethostname() is defined in linux/kernel/sys.c.
349 */
350 /* Unlike Linux, HP-UX returns an error if n==0: */
351 if ( n <= 0 )
352 return -EINVAL ;
353 return( sys_gethostname(ubuf, n) );
354 break ;
355 case 6:
356 /* Supposedly called from setuname() in libc.
357 * TODO: When and why is this called?
358 * Is it ever even called?
359 *
360 * This code should look a lot like sys_sethostname(),
361 * defined in linux/kernel/sys.c. If that gets updated,
362 * update this code similarly.
363 */
364 if (!capable(CAP_SYS_ADMIN))
365 return -EPERM;
366 /* Unlike Linux, HP-UX returns an error if n==0: */
367 if ( n <= 0 )
368 return -EINVAL ;
369 /* Unlike Linux, HP-UX truncates it if n is too big: */
370 len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
371 /**/
372 /* TODO: print a warning about using this? */
373 down_write(&uts_sem);
374 error = -EFAULT;
375 if (!copy_from_user(system_utsname.sysname, ubuf, len)) {
376 system_utsname.sysname[len] = 0;
377 error = 0;
378 }
379 up_write(&uts_sem);
380 return error;
381 break ;
382 case 7:
383 /* Sets utsname.release, if you're allowed.
384 * Undocumented. Used by swinstall to change the
385 * OS version, during OS updates. Yuck!!!
386 *
387 * This code should look a lot like sys_sethostname()
388 * in linux/kernel/sys.c. If that gets updated, update
389 * this code similarly.
390 */
391 if (!capable(CAP_SYS_ADMIN))
392 return -EPERM;
393 /* Unlike Linux, HP-UX returns an error if n==0: */
394 if ( n <= 0 )
395 return -EINVAL ;
396 /* Unlike Linux, HP-UX truncates it if n is too big: */
397 len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
398 /**/
399 /* TODO: print a warning about this? */
400 down_write(&uts_sem);
401 error = -EFAULT;
402 if (!copy_from_user(system_utsname.release, ubuf, len)) {
403 system_utsname.release[len] = 0;
404 error = 0;
405 }
406 up_write(&uts_sem);
407 return error;
408 break ;
409 default:
410 /* This system call returns -EFAULT if given an unknown type.
411 * Why not -EINVAL? I don't know, it's just not what they did.
412 */
413 return -EFAULT ;
414 }
415}
416
417int hpux_getdomainname(char *name, int len)
418{
419 int nlen;
420 int err = -EFAULT;
421
422 down_read(&uts_sem);
423
424 nlen = strlen(system_utsname.domainname) + 1;
425
426 if (nlen < len)
427 len = nlen;
428 if(len > __NEW_UTS_LEN)
429 goto done;
430 if(copy_to_user(name, system_utsname.domainname, len))
431 goto done;
432 err = 0;
433done:
434 up_read(&uts_sem);
435 return err;
436
437}
438
439int hpux_pipe(int *kstack_fildes)
440{
441 int error;
442
443 lock_kernel();
444 error = do_pipe(kstack_fildes);
445 unlock_kernel();
446 return error;
447}
448
449/* lies - says it works, but it really didn't lock anything */
450int hpux_lockf(int fildes, int function, off_t size)
451{
452 return 0;
453}
454
455int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2)
456{
457 char *fsname = NULL;
458 int len = 0;
459 int fstype;
460
461/*Unimplemented HP-UX syscall emulation. Syscall #334 (sysfs)
462 Args: 1 80057bf4 0 400179f0 0 0 0 */
463 printk(KERN_DEBUG "in hpux_sysfs\n");
464 printk(KERN_DEBUG "hpux_sysfs called with opcode = %d\n", opcode);
465 printk(KERN_DEBUG "hpux_sysfs called with arg1='%lx'\n", arg1);
466
467 if ( opcode == 1 ) { /* GETFSIND */
468 len = strlen_user((char *)arg1);
469 printk(KERN_DEBUG "len of arg1 = %d\n", len);
470
471 fsname = (char *) kmalloc(len+1, GFP_KERNEL);
472 if ( !fsname ) {
473 printk(KERN_DEBUG "failed to kmalloc fsname\n");
474 return 0;
475 }
476
477 if ( copy_from_user(fsname, (char *)arg1, len+1) ) {
478 printk(KERN_DEBUG "failed to copy_from_user fsname\n");
479 kfree(fsname);
480 return 0;
481 }
482
483 printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname);
484 if ( !strcmp(fsname, "hfs") ) {
485 fstype = 0;
486 } else {
487 fstype = 0;
488 };
489
490 kfree(fsname);
491
492 printk(KERN_DEBUG "returning fstype=%d\n", fstype);
493 return fstype; /* something other than default */
494 }
495
496
497 return 0;
498}
499
500
501/* Table of syscall names and handle for unimplemented routines */
502static const char *syscall_names[] = {
503 "nosys", /* 0 */
504 "exit",
505 "fork",
506 "read",
507 "write",
508 "open", /* 5 */
509 "close",
510 "wait",
511 "creat",
512 "link",
513 "unlink", /* 10 */
514 "execv",
515 "chdir",
516 "time",
517 "mknod",
518 "chmod", /* 15 */
519 "chown",
520 "brk",
521 "lchmod",
522 "lseek",
523 "getpid", /* 20 */
524 "mount",
525 "umount",
526 "setuid",
527 "getuid",
528 "stime", /* 25 */
529 "ptrace",
530 "alarm",
531 NULL,
532 "pause",
533 "utime", /* 30 */
534 "stty",
535 "gtty",
536 "access",
537 "nice",
538 "ftime", /* 35 */
539 "sync",
540 "kill",
541 "stat",
542 "setpgrp3",
543 "lstat", /* 40 */
544 "dup",
545 "pipe",
546 "times",
547 "profil",
548 "ki_call", /* 45 */
549 "setgid",
550 "getgid",
551 NULL,
552 NULL,
553 NULL, /* 50 */
554 "acct",
555 "set_userthreadid",
556 NULL,
557 "ioctl",
558 "reboot", /* 55 */
559 "symlink",
560 "utssys",
561 "readlink",
562 "execve",
563 "umask", /* 60 */
564 "chroot",
565 "fcntl",
566 "ulimit",
567 NULL,
568 NULL, /* 65 */
569 "vfork",
570 NULL,
571 NULL,
572 NULL,
573 NULL, /* 70 */
574 "mmap",
575 NULL,
576 "munmap",
577 "mprotect",
578 "madvise", /* 75 */
579 "vhangup",
580 "swapoff",
581 NULL,
582 "getgroups",
583 "setgroups", /* 80 */
584 "getpgrp2",
585 "setpgid/setpgrp2",
586 "setitimer",
587 "wait3",
588 "swapon", /* 85 */
589 "getitimer",
590 NULL,
591 NULL,
592 NULL,
593 "dup2", /* 90 */
594 NULL,
595 "fstat",
596 "select",
597 NULL,
598 "fsync", /* 95 */
599 "setpriority",
600 NULL,
601 NULL,
602 NULL,
603 "getpriority", /* 100 */
604 NULL,
605 NULL,
606 NULL,
607 NULL,
608 NULL, /* 105 */
609 NULL,
610 NULL,
611 "sigvector",
612 "sigblock",
613 "sigsetmask", /* 110 */
614 "sigpause",
615 "sigstack",
616 NULL,
617 NULL,
618 NULL, /* 115 */
619 "gettimeofday",
620 "getrusage",
621 NULL,
622 NULL,
623 "readv", /* 120 */
624 "writev",
625 "settimeofday",
626 "fchown",
627 "fchmod",
628 NULL, /* 125 */
629 "setresuid",
630 "setresgid",
631 "rename",
632 "truncate",
633 "ftruncate", /* 130 */
634 NULL,
635 "sysconf",
636 NULL,
637 NULL,
638 NULL, /* 135 */
639 "mkdir",
640 "rmdir",
641 NULL,
642 "sigcleanup",
643 "setcore", /* 140 */
644 NULL,
645 "gethostid",
646 "sethostid",
647 "getrlimit",
648 "setrlimit", /* 145 */
649 NULL,
650 NULL,
651 "quotactl",
652 "get_sysinfo",
653 NULL, /* 150 */
654 "privgrp",
655 "rtprio",
656 "plock",
657 NULL,
658 "lockf", /* 155 */
659 "semget",
660 NULL,
661 "semop",
662 "msgget",
663 NULL, /* 160 */
664 "msgsnd",
665 "msgrcv",
666 "shmget",
667 NULL,
668 "shmat", /* 165 */
669 "shmdt",
670 NULL,
671 "csp/nsp_init",
672 "cluster",
673 "mkrnod", /* 170 */
674 "test",
675 "unsp_open",
676 NULL,
677 "getcontext",
678 "osetcontext", /* 175 */
679 "bigio",
680 "pipenode",
681 "lsync",
682 "getmachineid",
683 "cnodeid/mysite", /* 180 */
684 "cnodes/sitels",
685 "swapclients",
686 "rmtprocess",
687 "dskless_stats",
688 "sigprocmask", /* 185 */
689 "sigpending",
690 "sigsuspend",
691 "sigaction",
692 NULL,
693 "nfssvc", /* 190 */
694 "getfh",
695 "getdomainname",
696 "setdomainname",
697 "async_daemon",
698 "getdirentries", /* 195 */
699 NULL,
700 NULL,
701 "vfsmount",
702 NULL,
703 "waitpid", /* 200 */
704 NULL,
705 NULL,
706 NULL,
707 NULL,
708 NULL, /* 205 */
709 NULL,
710 NULL,
711 NULL,
712 NULL,
713 NULL, /* 210 */
714 NULL,
715 NULL,
716 NULL,
717 NULL,
718 NULL, /* 215 */
719 NULL,
720 NULL,
721 NULL,
722 NULL,
723 NULL, /* 220 */
724 NULL,
725 NULL,
726 NULL,
727 "sigsetreturn",
728 "sigsetstatemask", /* 225 */
729 "bfactl",
730 "cs",
731 "cds",
732 NULL,
733 "pathconf", /* 230 */
734 "fpathconf",
735 NULL,
736 NULL,
737 "nfs_fcntl",
738 "ogetacl", /* 235 */
739 "ofgetacl",
740 "osetacl",
741 "ofsetacl",
742 "pstat",
743 "getaudid", /* 240 */
744 "setaudid",
745 "getaudproc",
746 "setaudproc",
747 "getevent",
748 "setevent", /* 245 */
749 "audwrite",
750 "audswitch",
751 "audctl",
752 "ogetaccess",
753 "fsctl", /* 250 */
754 "ulconnect",
755 "ulcontrol",
756 "ulcreate",
757 "uldest",
758 "ulrecv", /* 255 */
759 "ulrecvcn",
760 "ulsend",
761 "ulshutdown",
762 "swapfs",
763 "fss", /* 260 */
764 NULL,
765 NULL,
766 NULL,
767 NULL,
768 NULL, /* 265 */
769 NULL,
770 "tsync",
771 "getnumfds",
772 "poll",
773 "getmsg", /* 270 */
774 "putmsg",
775 "fchdir",
776 "getmount_cnt",
777 "getmount_entry",
778 "accept", /* 275 */
779 "bind",
780 "connect",
781 "getpeername",
782 "getsockname",
783 "getsockopt", /* 280 */
784 "listen",
785 "recv",
786 "recvfrom",
787 "recvmsg",
788 "send", /* 285 */
789 "sendmsg",
790 "sendto",
791 "setsockopt",
792 "shutdown",
793 "socket", /* 290 */
794 "socketpair",
795 "proc_open",
796 "proc_close",
797 "proc_send",
798 "proc_recv", /* 295 */
799 "proc_sendrecv",
800 "proc_syscall",
801 "ipccreate",
802 "ipcname",
803 "ipcnamerase", /* 300 */
804 "ipclookup",
805 "ipcselect",
806 "ipcconnect",
807 "ipcrecvcn",
808 "ipcsend", /* 305 */
809 "ipcrecv",
810 "ipcgetnodename",
811 "ipcsetnodename",
812 "ipccontrol",
813 "ipcshutdown", /* 310 */
814 "ipcdest",
815 "semctl",
816 "msgctl",
817 "shmctl",
818 "mpctl", /* 315 */
819 "exportfs",
820 "getpmsg",
821 "putpmsg",
822 "strioctl",
823 "msync", /* 320 */
824 "msleep",
825 "mwakeup",
826 "msem_init",
827 "msem_remove",
828 "adjtime", /* 325 */
829 "kload",
830 "fattach",
831 "fdetach",
832 "serialize",
833 "statvfs", /* 330 */
834 "fstatvfs",
835 "lchown",
836 "getsid",
837 "sysfs",
838 NULL, /* 335 */
839 NULL,
840 "sched_setparam",
841 "sched_getparam",
842 "sched_setscheduler",
843 "sched_getscheduler", /* 340 */
844 "sched_yield",
845 "sched_get_priority_max",
846 "sched_get_priority_min",
847 "sched_rr_get_interval",
848 "clock_settime", /* 345 */
849 "clock_gettime",
850 "clock_getres",
851 "timer_create",
852 "timer_delete",
853 "timer_settime", /* 350 */
854 "timer_gettime",
855 "timer_getoverrun",
856 "nanosleep",
857 "toolbox",
858 NULL, /* 355 */
859 "getdents",
860 "getcontext",
861 "sysinfo",
862 "fcntl64",
863 "ftruncate64", /* 360 */
864 "fstat64",
865 "getdirentries64",
866 "getrlimit64",
867 "lockf64",
868 "lseek64", /* 365 */
869 "lstat64",
870 "mmap64",
871 "setrlimit64",
872 "stat64",
873 "truncate64", /* 370 */
874 "ulimit64",
875 NULL,
876 NULL,
877 NULL,
878 NULL, /* 375 */
879 NULL,
880 NULL,
881 NULL,
882 NULL,
883 "setcontext", /* 380 */
884 "sigaltstack",
885 "waitid",
886 "setpgrp",
887 "recvmsg2",
888 "sendmsg2", /* 385 */
889 "socket2",
890 "socketpair2",
891 "setregid",
892 "lwp_create",
893 "lwp_terminate", /* 390 */
894 "lwp_wait",
895 "lwp_suspend",
896 "lwp_resume",
897 "lwp_self",
898 "lwp_abort_syscall", /* 395 */
899 "lwp_info",
900 "lwp_kill",
901 "ksleep",
902 "kwakeup",
903 "ksleep_abort", /* 400 */
904 "lwp_proc_info",
905 "lwp_exit",
906 "lwp_continue",
907 "getacl",
908 "fgetacl", /* 405 */
909 "setacl",
910 "fsetacl",
911 "getaccess",
912 "lwp_mutex_init",
913 "lwp_mutex_lock_sys", /* 410 */
914 "lwp_mutex_unlock",
915 "lwp_cond_init",
916 "lwp_cond_signal",
917 "lwp_cond_broadcast",
918 "lwp_cond_wait_sys", /* 415 */
919 "lwp_getscheduler",
920 "lwp_setscheduler",
921 "lwp_getprivate",
922 "lwp_setprivate",
923 "lwp_detach", /* 420 */
924 "mlock",
925 "munlock",
926 "mlockall",
927 "munlockall",
928 "shm_open", /* 425 */
929 "shm_unlink",
930 "sigqueue",
931 "sigwaitinfo",
932 "sigtimedwait",
933 "sigwait", /* 430 */
934 "aio_read",
935 "aio_write",
936 "lio_listio",
937 "aio_error",
938 "aio_return", /* 435 */
939 "aio_cancel",
940 "aio_suspend",
941 "aio_fsync",
942 "mq_open",
943 "mq_unlink", /* 440 */
944 "mq_send",
945 "mq_receive",
946 "mq_notify",
947 "mq_setattr",
948 "mq_getattr", /* 445 */
949 "ksem_open",
950 "ksem_unlink",
951 "ksem_close",
952 "ksem_destroy",
953 "lw_sem_incr", /* 450 */
954 "lw_sem_decr",
955 "lw_sem_read",
956 "mq_close",
957};
958static const int syscall_names_max = 453;
959
960int
961hpux_unimplemented(unsigned long arg1,unsigned long arg2,unsigned long arg3,
962 unsigned long arg4,unsigned long arg5,unsigned long arg6,
963 unsigned long arg7,unsigned long sc_num)
964{
965 /* NOTE: sc_num trashes arg8 for the few syscalls that actually
966 * have a valid 8th argument.
967 */
968 const char *name = NULL;
969 if ( sc_num <= syscall_names_max && sc_num >= 0 ) {
970 name = syscall_names[sc_num];
971 }
972
973 if ( name ) {
974 printk(KERN_DEBUG "Unimplemented HP-UX syscall emulation. Syscall #%lu (%s)\n",
975 sc_num, name);
976 } else {
977 printk(KERN_DEBUG "Unimplemented unknown HP-UX syscall emulation. Syscall #%lu\n",
978 sc_num);
979 }
980
981 printk(KERN_DEBUG " Args: %lx %lx %lx %lx %lx %lx %lx\n",
982 arg1, arg2, arg3, arg4, arg5, arg6, arg7);
983
984 return -ENOSYS;
985}
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 @@
1/*
2 * Linux/PARISC Project (http://www.parisc-linux.org/)
3 *
4 * HP-UX System Call Wrapper routines and System Call Return Path
5 *
6 * Copyright (C) 2000 Hewlett-Packard (John Marvin)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#ifdef __LP64__
24#warning PA64 support needs more work...did first cut
25#endif
26
27#include <asm/offsets.h>
28#include <asm/assembly.h>
29#include <asm/signal.h>
30
31#ifdef __LP64__
32 .level 2.0w
33#else
34 .level 1.1
35#endif
36 .text
37
38 /* These should probably go in a header file somewhere.
39 * They are duplicated in kernel/wrappers.S
40 * Possibly we should consider consolidating these
41 * register save/restore macros.
42 */
43 .macro reg_save regs
44#ifdef __LP64__
45#warning NEEDS WORK for 64-bit
46#endif
47 STREG %r3, PT_GR3(\regs)
48 STREG %r4, PT_GR4(\regs)
49 STREG %r5, PT_GR5(\regs)
50 STREG %r6, PT_GR6(\regs)
51 STREG %r7, PT_GR7(\regs)
52 STREG %r8, PT_GR8(\regs)
53 STREG %r9, PT_GR9(\regs)
54 STREG %r10,PT_GR10(\regs)
55 STREG %r11,PT_GR11(\regs)
56 STREG %r12,PT_GR12(\regs)
57 STREG %r13,PT_GR13(\regs)
58 STREG %r14,PT_GR14(\regs)
59 STREG %r15,PT_GR15(\regs)
60 STREG %r16,PT_GR16(\regs)
61 STREG %r17,PT_GR17(\regs)
62 STREG %r18,PT_GR18(\regs)
63 .endm
64
65 .macro reg_restore regs
66 LDREG PT_GR3(\regs), %r3
67 LDREG PT_GR4(\regs), %r4
68 LDREG PT_GR5(\regs), %r5
69 LDREG PT_GR6(\regs), %r6
70 LDREG PT_GR7(\regs), %r7
71 LDREG PT_GR8(\regs), %r8
72 LDREG PT_GR9(\regs), %r9
73 LDREG PT_GR10(\regs),%r10
74 LDREG PT_GR11(\regs),%r11
75 LDREG PT_GR12(\regs),%r12
76 LDREG PT_GR13(\regs),%r13
77 LDREG PT_GR14(\regs),%r14
78 LDREG PT_GR15(\regs),%r15
79 LDREG PT_GR16(\regs),%r16
80 LDREG PT_GR17(\regs),%r17
81 LDREG PT_GR18(\regs),%r18
82 .endm
83
84
85 .export hpux_fork_wrapper
86 .export hpux_child_return
87 .import sys_fork
88
89hpux_fork_wrapper:
90 ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
91 ;! pointer in task
92 reg_save %r1
93
94 STREG %r2,-20(%r30)
95 ldo 64(%r30),%r30
96 STREG %r2,PT_GR19(%r1) ;! save for child
97 STREG %r30,PT_GR21(%r1) ;! save for child
98
99 LDREG PT_GR30(%r1),%r25
100 mtctl %r25,%cr29
101 copy %r1,%r24
102 bl sys_clone,%r2
103 ldi SIGCHLD,%r26
104
105 LDREG -84(%r30),%r2
106fork_return:
107 ldo -64(%r30),%r30
108 ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
109
110 reg_restore %r1
111
112 /*
113 * HP-UX wants pid (child gets parent pid, parent gets child pid)
114 * in r28 and a flag in r29 (r29 == 1 for child, 0 for parent).
115 * Linux fork returns 0 for child, pid for parent. Since HP-UX
116 * libc stub throws away parent pid and returns 0 for child,
117 * we'll just return 0 for parent pid now. Only applications
118 * that jump directly to the gateway page (not supported) will
119 * know the difference. We can fix this later if necessary.
120 */
121
122 ldo -1024(%r0),%r1
123 comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */
124 or,= %r28,%r0,%r0
125 or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */
126 ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */
127
128fork_exit:
129 bv %r0(%r2)
130 nop
131
132 /* Set the return value for the child */
133
134hpux_child_return:
135#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
136 bl schedule_tail, %r2
137 nop
138#endif
139
140 LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
141 b fork_return
142 copy %r0,%r28
143
144 .export hpux_execve_wrapper
145 .export hpux_execv_wrapper
146 .import hpux_execve
147
148hpux_execv_wrapper:
149 copy %r0,%r24 /* NULL environment */
150
151hpux_execve_wrapper:
152
153 ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
154
155 /*
156 * Do we need to save/restore r3-r18 here?
157 * I don't think so. why would new thread need old
158 * threads registers?
159 */
160
161 /* Store arg0, arg1 and arg2 so that hpux_execve will find them */
162
163 STREG %r26,PT_GR26(%r1)
164 STREG %r25,PT_GR25(%r1)
165 STREG %r24,PT_GR24(%r1)
166
167 STREG %r2,-20(%r30)
168 ldo 64(%r30),%r30
169 bl hpux_execve,%r2
170 copy %r1,%arg0
171
172 ldo -64(%r30),%r30
173 LDREG -20(%r30),%r2
174
175 /* If exec succeeded we need to load the args */
176
177 ldo -1024(%r0),%r1
178 comb,>>= %r28,%r1,exec_error
179 copy %r2,%r19
180 ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr
181 LDREG TASK_PT_GR26(%r1),%r26
182 LDREG TASK_PT_GR25(%r1),%r25
183 LDREG TASK_PT_GR24(%r1),%r24
184 LDREG TASK_PT_GR23(%r1),%r23
185 copy %r0,%r2 /* Flag to syscall_exit not to clear args */
186
187exec_error:
188 bv %r0(%r19)
189 nop
190
191 .export hpux_pipe_wrapper
192 .import hpux_pipe
193
194 /* HP-UX expects pipefd's returned in r28 & r29 */
195
196hpux_pipe_wrapper:
197 STREG %r2,-20(%r30)
198 ldo 64(%r30),%r30
199 bl hpux_pipe,%r2
200 ldo -56(%r30),%r26 /* pass local array to hpux_pipe */
201
202
203 ldo -1024(%r0),%r1
204 comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */
205 LDREG -84(%r30),%r2
206
207 /* if success, load fd's from stack array */
208
209 LDREG -56(%r30),%r28
210 LDREG -52(%r30),%r29
211
212pipe_exit:
213 bv %r0(%r2)
214 ldo -64(%r30),%r30
215
216 .export hpux_syscall_exit
217 .import syscall_exit
218
219hpux_syscall_exit:
220
221 /*
222 *
223 * HP-UX call return conventions:
224 *
225 * if error:
226 * r22 = 1
227 * r28 = errno value
228 * r29 = secondary return value
229 * else
230 * r22 = 0
231 * r28 = return value
232 * r29 = secondary return value
233 *
234 * For now, we'll just check to see if r28 is < (unsigned long)-1024
235 * (to handle addresses > 2 Gb) and if so set r22 to zero. If not,
236 * we'll complement r28 and set r22 to 1. Wrappers will be
237 * needed for syscalls that care about the secondary return value.
238 * The wrapper may also need a way of avoiding the following code,
239 * but we'll deal with that when it becomes necessary.
240 */
241
242 ldo -1024(%r0),%r1
243 comb,<< %r28,%r1,no_error
244 copy %r0,%r22
245 subi 0,%r28,%r28
246 ldo 1(%r0),%r22
247
248no_error:
249 b syscall_exit
250 nop
251
252 .export hpux_unimplemented_wrapper
253 .import hpux_unimplemented
254
255hpux_unimplemented_wrapper:
256 b hpux_unimplemented
257 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 @@
1#!/bin/sh
2#
3# arch/parisc/install.sh, derived from arch/i386/boot/install.sh
4#
5# This file is subject to the terms and conditions of the GNU General Public
6# License. See the file "COPYING" in the main directory of this archive
7# for more details.
8#
9# Copyright (C) 1995 by Linus Torvalds
10#
11# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
12#
13# "make install" script for i386 architecture
14#
15# Arguments:
16# $1 - kernel version
17# $2 - kernel image file
18# $3 - kernel map file
19# $4 - default install path (blank if root directory)
20#
21
22# User may have a custom install script
23
24if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
25if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
26
27# Default install
28
29if [ -f $4/vmlinux ]; then
30 mv $4/vmlinux $4/vmlinux.old
31fi
32
33if [ -f $4/System.map ]; then
34 mv $4/System.map $4/System.old
35fi
36
37cat $2 > $4/vmlinux
38cp $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 @@
1#
2# Makefile for arch/parisc/kernel
3#
4
5extra-y := init_task.o head.o vmlinux.lds
6
7AFLAGS_entry.o := -traditional
8AFLAGS_pacache.o := -traditional
9CFLAGS_ioctl32.o := -Ifs/
10
11obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
12 pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
13 ptrace.o hardware.o inventory.o drivers.o semaphore.o \
14 signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
15 process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
16 topology.o
17
18obj-$(CONFIG_SMP) += smp.o
19obj-$(CONFIG_PA11) += pci-dma.o
20obj-$(CONFIG_PCI) += pci.o
21obj-$(CONFIG_MODULES) += module.o
22obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o
23# only supported for PCX-W/U in 64-bit mode at the moment
24obj-$(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 @@
1/*
2 * Generate definitions needed by assembly language modules.
3 * This code generates raw asm output which is post-processed to extract
4 * and format the required data.
5 *
6 * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org>
7 * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org>
8 * Copyright (C) 2000 Sam Creasey <sammy@sammy.net>
9 * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
10 * Copyright (C) 2001 Paul Bame <bame at parisc-linux.org>
11 * Copyright (C) 2001 Richard Hirst <rhirst at parisc-linux.org>
12 * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
13 * Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#include <linux/types.h>
31#include <linux/sched.h>
32#include <linux/thread_info.h>
33#include <linux/version.h>
34#include <linux/ptrace.h>
35#include <linux/hardirq.h>
36
37#include <asm/pgtable.h>
38#include <asm/ptrace.h>
39#include <asm/processor.h>
40#include <asm/pdc.h>
41#include <asm/uaccess.h>
42
43#define DEFINE(sym, val) \
44 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
45
46#define BLANK() asm volatile("\n->" : : )
47
48#ifdef __LP64__
49#define FRAME_SIZE 128
50#else
51#define FRAME_SIZE 64
52#endif
53
54#define align(x,y) (((x)+FRAME_SIZE+(y)-1) - (((x)+(y)-1)%(y)))
55
56int main(void)
57{
58 DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
59 DEFINE(TASK_STATE, offsetof(struct task_struct, state));
60 DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
61 DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending));
62 DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
63 DEFINE(TASK_MM, offsetof(struct task_struct, mm));
64 DEFINE(TASK_PERSONALITY, offsetof(struct task_struct, personality));
65 DEFINE(TASK_PID, offsetof(struct task_struct, pid));
66 BLANK();
67 DEFINE(TASK_REGS, offsetof(struct task_struct, thread.regs));
68 DEFINE(TASK_PT_PSW, offsetof(struct task_struct, thread.regs.gr[ 0]));
69 DEFINE(TASK_PT_GR1, offsetof(struct task_struct, thread.regs.gr[ 1]));
70 DEFINE(TASK_PT_GR2, offsetof(struct task_struct, thread.regs.gr[ 2]));
71 DEFINE(TASK_PT_GR3, offsetof(struct task_struct, thread.regs.gr[ 3]));
72 DEFINE(TASK_PT_GR4, offsetof(struct task_struct, thread.regs.gr[ 4]));
73 DEFINE(TASK_PT_GR5, offsetof(struct task_struct, thread.regs.gr[ 5]));
74 DEFINE(TASK_PT_GR6, offsetof(struct task_struct, thread.regs.gr[ 6]));
75 DEFINE(TASK_PT_GR7, offsetof(struct task_struct, thread.regs.gr[ 7]));
76 DEFINE(TASK_PT_GR8, offsetof(struct task_struct, thread.regs.gr[ 8]));
77 DEFINE(TASK_PT_GR9, offsetof(struct task_struct, thread.regs.gr[ 9]));
78 DEFINE(TASK_PT_GR10, offsetof(struct task_struct, thread.regs.gr[10]));
79 DEFINE(TASK_PT_GR11, offsetof(struct task_struct, thread.regs.gr[11]));
80 DEFINE(TASK_PT_GR12, offsetof(struct task_struct, thread.regs.gr[12]));
81 DEFINE(TASK_PT_GR13, offsetof(struct task_struct, thread.regs.gr[13]));
82 DEFINE(TASK_PT_GR14, offsetof(struct task_struct, thread.regs.gr[14]));
83 DEFINE(TASK_PT_GR15, offsetof(struct task_struct, thread.regs.gr[15]));
84 DEFINE(TASK_PT_GR16, offsetof(struct task_struct, thread.regs.gr[16]));
85 DEFINE(TASK_PT_GR17, offsetof(struct task_struct, thread.regs.gr[17]));
86 DEFINE(TASK_PT_GR18, offsetof(struct task_struct, thread.regs.gr[18]));
87 DEFINE(TASK_PT_GR19, offsetof(struct task_struct, thread.regs.gr[19]));
88 DEFINE(TASK_PT_GR20, offsetof(struct task_struct, thread.regs.gr[20]));
89 DEFINE(TASK_PT_GR21, offsetof(struct task_struct, thread.regs.gr[21]));
90 DEFINE(TASK_PT_GR22, offsetof(struct task_struct, thread.regs.gr[22]));
91 DEFINE(TASK_PT_GR23, offsetof(struct task_struct, thread.regs.gr[23]));
92 DEFINE(TASK_PT_GR24, offsetof(struct task_struct, thread.regs.gr[24]));
93 DEFINE(TASK_PT_GR25, offsetof(struct task_struct, thread.regs.gr[25]));
94 DEFINE(TASK_PT_GR26, offsetof(struct task_struct, thread.regs.gr[26]));
95 DEFINE(TASK_PT_GR27, offsetof(struct task_struct, thread.regs.gr[27]));
96 DEFINE(TASK_PT_GR28, offsetof(struct task_struct, thread.regs.gr[28]));
97 DEFINE(TASK_PT_GR29, offsetof(struct task_struct, thread.regs.gr[29]));
98 DEFINE(TASK_PT_GR30, offsetof(struct task_struct, thread.regs.gr[30]));
99 DEFINE(TASK_PT_GR31, offsetof(struct task_struct, thread.regs.gr[31]));
100 DEFINE(TASK_PT_FR0, offsetof(struct task_struct, thread.regs.fr[ 0]));
101 DEFINE(TASK_PT_FR1, offsetof(struct task_struct, thread.regs.fr[ 1]));
102 DEFINE(TASK_PT_FR2, offsetof(struct task_struct, thread.regs.fr[ 2]));
103 DEFINE(TASK_PT_FR3, offsetof(struct task_struct, thread.regs.fr[ 3]));
104 DEFINE(TASK_PT_FR4, offsetof(struct task_struct, thread.regs.fr[ 4]));
105 DEFINE(TASK_PT_FR5, offsetof(struct task_struct, thread.regs.fr[ 5]));
106 DEFINE(TASK_PT_FR6, offsetof(struct task_struct, thread.regs.fr[ 6]));
107 DEFINE(TASK_PT_FR7, offsetof(struct task_struct, thread.regs.fr[ 7]));
108 DEFINE(TASK_PT_FR8, offsetof(struct task_struct, thread.regs.fr[ 8]));
109 DEFINE(TASK_PT_FR9, offsetof(struct task_struct, thread.regs.fr[ 9]));
110 DEFINE(TASK_PT_FR10, offsetof(struct task_struct, thread.regs.fr[10]));
111 DEFINE(TASK_PT_FR11, offsetof(struct task_struct, thread.regs.fr[11]));
112 DEFINE(TASK_PT_FR12, offsetof(struct task_struct, thread.regs.fr[12]));
113 DEFINE(TASK_PT_FR13, offsetof(struct task_struct, thread.regs.fr[13]));
114 DEFINE(TASK_PT_FR14, offsetof(struct task_struct, thread.regs.fr[14]));
115 DEFINE(TASK_PT_FR15, offsetof(struct task_struct, thread.regs.fr[15]));
116 DEFINE(TASK_PT_FR16, offsetof(struct task_struct, thread.regs.fr[16]));
117 DEFINE(TASK_PT_FR17, offsetof(struct task_struct, thread.regs.fr[17]));
118 DEFINE(TASK_PT_FR18, offsetof(struct task_struct, thread.regs.fr[18]));
119 DEFINE(TASK_PT_FR19, offsetof(struct task_struct, thread.regs.fr[19]));
120 DEFINE(TASK_PT_FR20, offsetof(struct task_struct, thread.regs.fr[20]));
121 DEFINE(TASK_PT_FR21, offsetof(struct task_struct, thread.regs.fr[21]));
122 DEFINE(TASK_PT_FR22, offsetof(struct task_struct, thread.regs.fr[22]));
123 DEFINE(TASK_PT_FR23, offsetof(struct task_struct, thread.regs.fr[23]));
124 DEFINE(TASK_PT_FR24, offsetof(struct task_struct, thread.regs.fr[24]));
125 DEFINE(TASK_PT_FR25, offsetof(struct task_struct, thread.regs.fr[25]));
126 DEFINE(TASK_PT_FR26, offsetof(struct task_struct, thread.regs.fr[26]));
127 DEFINE(TASK_PT_FR27, offsetof(struct task_struct, thread.regs.fr[27]));
128 DEFINE(TASK_PT_FR28, offsetof(struct task_struct, thread.regs.fr[28]));
129 DEFINE(TASK_PT_FR29, offsetof(struct task_struct, thread.regs.fr[29]));
130 DEFINE(TASK_PT_FR30, offsetof(struct task_struct, thread.regs.fr[30]));
131 DEFINE(TASK_PT_FR31, offsetof(struct task_struct, thread.regs.fr[31]));
132 DEFINE(TASK_PT_SR0, offsetof(struct task_struct, thread.regs.sr[ 0]));
133 DEFINE(TASK_PT_SR1, offsetof(struct task_struct, thread.regs.sr[ 1]));
134 DEFINE(TASK_PT_SR2, offsetof(struct task_struct, thread.regs.sr[ 2]));
135 DEFINE(TASK_PT_SR3, offsetof(struct task_struct, thread.regs.sr[ 3]));
136 DEFINE(TASK_PT_SR4, offsetof(struct task_struct, thread.regs.sr[ 4]));
137 DEFINE(TASK_PT_SR5, offsetof(struct task_struct, thread.regs.sr[ 5]));
138 DEFINE(TASK_PT_SR6, offsetof(struct task_struct, thread.regs.sr[ 6]));
139 DEFINE(TASK_PT_SR7, offsetof(struct task_struct, thread.regs.sr[ 7]));
140 DEFINE(TASK_PT_IASQ0, offsetof(struct task_struct, thread.regs.iasq[0]));
141 DEFINE(TASK_PT_IASQ1, offsetof(struct task_struct, thread.regs.iasq[1]));
142 DEFINE(TASK_PT_IAOQ0, offsetof(struct task_struct, thread.regs.iaoq[0]));
143 DEFINE(TASK_PT_IAOQ1, offsetof(struct task_struct, thread.regs.iaoq[1]));
144 DEFINE(TASK_PT_CR27, offsetof(struct task_struct, thread.regs.cr27));
145 DEFINE(TASK_PT_ORIG_R28, offsetof(struct task_struct, thread.regs.orig_r28));
146 DEFINE(TASK_PT_KSP, offsetof(struct task_struct, thread.regs.ksp));
147 DEFINE(TASK_PT_KPC, offsetof(struct task_struct, thread.regs.kpc));
148 DEFINE(TASK_PT_SAR, offsetof(struct task_struct, thread.regs.sar));
149 DEFINE(TASK_PT_IIR, offsetof(struct task_struct, thread.regs.iir));
150 DEFINE(TASK_PT_ISR, offsetof(struct task_struct, thread.regs.isr));
151 DEFINE(TASK_PT_IOR, offsetof(struct task_struct, thread.regs.ior));
152 BLANK();
153 DEFINE(TASK_SZ, sizeof(struct task_struct));
154 DEFINE(TASK_SZ_ALGN, align(sizeof(struct task_struct), 64));
155 BLANK();
156 DEFINE(PT_PSW, offsetof(struct pt_regs, gr[ 0]));
157 DEFINE(PT_GR1, offsetof(struct pt_regs, gr[ 1]));
158 DEFINE(PT_GR2, offsetof(struct pt_regs, gr[ 2]));
159 DEFINE(PT_GR3, offsetof(struct pt_regs, gr[ 3]));
160 DEFINE(PT_GR4, offsetof(struct pt_regs, gr[ 4]));
161 DEFINE(PT_GR5, offsetof(struct pt_regs, gr[ 5]));
162 DEFINE(PT_GR6, offsetof(struct pt_regs, gr[ 6]));
163 DEFINE(PT_GR7, offsetof(struct pt_regs, gr[ 7]));
164 DEFINE(PT_GR8, offsetof(struct pt_regs, gr[ 8]));
165 DEFINE(PT_GR9, offsetof(struct pt_regs, gr[ 9]));
166 DEFINE(PT_GR10, offsetof(struct pt_regs, gr[10]));
167 DEFINE(PT_GR11, offsetof(struct pt_regs, gr[11]));
168 DEFINE(PT_GR12, offsetof(struct pt_regs, gr[12]));
169 DEFINE(PT_GR13, offsetof(struct pt_regs, gr[13]));
170 DEFINE(PT_GR14, offsetof(struct pt_regs, gr[14]));
171 DEFINE(PT_GR15, offsetof(struct pt_regs, gr[15]));
172 DEFINE(PT_GR16, offsetof(struct pt_regs, gr[16]));
173 DEFINE(PT_GR17, offsetof(struct pt_regs, gr[17]));
174 DEFINE(PT_GR18, offsetof(struct pt_regs, gr[18]));
175 DEFINE(PT_GR19, offsetof(struct pt_regs, gr[19]));
176 DEFINE(PT_GR20, offsetof(struct pt_regs, gr[20]));
177 DEFINE(PT_GR21, offsetof(struct pt_regs, gr[21]));
178 DEFINE(PT_GR22, offsetof(struct pt_regs, gr[22]));
179 DEFINE(PT_GR23, offsetof(struct pt_regs, gr[23]));
180 DEFINE(PT_GR24, offsetof(struct pt_regs, gr[24]));
181 DEFINE(PT_GR25, offsetof(struct pt_regs, gr[25]));
182 DEFINE(PT_GR26, offsetof(struct pt_regs, gr[26]));
183 DEFINE(PT_GR27, offsetof(struct pt_regs, gr[27]));
184 DEFINE(PT_GR28, offsetof(struct pt_regs, gr[28]));
185 DEFINE(PT_GR29, offsetof(struct pt_regs, gr[29]));
186 DEFINE(PT_GR30, offsetof(struct pt_regs, gr[30]));
187 DEFINE(PT_GR31, offsetof(struct pt_regs, gr[31]));
188 DEFINE(PT_FR0, offsetof(struct pt_regs, fr[ 0]));
189 DEFINE(PT_FR1, offsetof(struct pt_regs, fr[ 1]));
190 DEFINE(PT_FR2, offsetof(struct pt_regs, fr[ 2]));
191 DEFINE(PT_FR3, offsetof(struct pt_regs, fr[ 3]));
192 DEFINE(PT_FR4, offsetof(struct pt_regs, fr[ 4]));
193 DEFINE(PT_FR5, offsetof(struct pt_regs, fr[ 5]));
194 DEFINE(PT_FR6, offsetof(struct pt_regs, fr[ 6]));
195 DEFINE(PT_FR7, offsetof(struct pt_regs, fr[ 7]));
196 DEFINE(PT_FR8, offsetof(struct pt_regs, fr[ 8]));
197 DEFINE(PT_FR9, offsetof(struct pt_regs, fr[ 9]));
198 DEFINE(PT_FR10, offsetof(struct pt_regs, fr[10]));
199 DEFINE(PT_FR11, offsetof(struct pt_regs, fr[11]));
200 DEFINE(PT_FR12, offsetof(struct pt_regs, fr[12]));
201 DEFINE(PT_FR13, offsetof(struct pt_regs, fr[13]));
202 DEFINE(PT_FR14, offsetof(struct pt_regs, fr[14]));
203 DEFINE(PT_FR15, offsetof(struct pt_regs, fr[15]));
204 DEFINE(PT_FR16, offsetof(struct pt_regs, fr[16]));
205 DEFINE(PT_FR17, offsetof(struct pt_regs, fr[17]));
206 DEFINE(PT_FR18, offsetof(struct pt_regs, fr[18]));
207 DEFINE(PT_FR19, offsetof(struct pt_regs, fr[19]));
208 DEFINE(PT_FR20, offsetof(struct pt_regs, fr[20]));
209 DEFINE(PT_FR21, offsetof(struct pt_regs, fr[21]));
210 DEFINE(PT_FR22, offsetof(struct pt_regs, fr[22]));
211 DEFINE(PT_FR23, offsetof(struct pt_regs, fr[23]));
212 DEFINE(PT_FR24, offsetof(struct pt_regs, fr[24]));
213 DEFINE(PT_FR25, offsetof(struct pt_regs, fr[25]));
214 DEFINE(PT_FR26, offsetof(struct pt_regs, fr[26]));
215 DEFINE(PT_FR27, offsetof(struct pt_regs, fr[27]));
216 DEFINE(PT_FR28, offsetof(struct pt_regs, fr[28]));
217 DEFINE(PT_FR29, offsetof(struct pt_regs, fr[29]));
218 DEFINE(PT_FR30, offsetof(struct pt_regs, fr[30]));
219 DEFINE(PT_FR31, offsetof(struct pt_regs, fr[31]));
220 DEFINE(PT_SR0, offsetof(struct pt_regs, sr[ 0]));
221 DEFINE(PT_SR1, offsetof(struct pt_regs, sr[ 1]));
222 DEFINE(PT_SR2, offsetof(struct pt_regs, sr[ 2]));
223 DEFINE(PT_SR3, offsetof(struct pt_regs, sr[ 3]));
224 DEFINE(PT_SR4, offsetof(struct pt_regs, sr[ 4]));
225 DEFINE(PT_SR5, offsetof(struct pt_regs, sr[ 5]));
226 DEFINE(PT_SR6, offsetof(struct pt_regs, sr[ 6]));
227 DEFINE(PT_SR7, offsetof(struct pt_regs, sr[ 7]));
228 DEFINE(PT_IASQ0, offsetof(struct pt_regs, iasq[0]));
229 DEFINE(PT_IASQ1, offsetof(struct pt_regs, iasq[1]));
230 DEFINE(PT_IAOQ0, offsetof(struct pt_regs, iaoq[0]));
231 DEFINE(PT_IAOQ1, offsetof(struct pt_regs, iaoq[1]));
232 DEFINE(PT_CR27, offsetof(struct pt_regs, cr27));
233 DEFINE(PT_ORIG_R28, offsetof(struct pt_regs, orig_r28));
234 DEFINE(PT_KSP, offsetof(struct pt_regs, ksp));
235 DEFINE(PT_KPC, offsetof(struct pt_regs, kpc));
236 DEFINE(PT_SAR, offsetof(struct pt_regs, sar));
237 DEFINE(PT_IIR, offsetof(struct pt_regs, iir));
238 DEFINE(PT_ISR, offsetof(struct pt_regs, isr));
239 DEFINE(PT_IOR, offsetof(struct pt_regs, ior));
240 DEFINE(PT_SIZE, sizeof(struct pt_regs));
241 DEFINE(PT_SZ_ALGN, align(sizeof(struct pt_regs), 64));
242 BLANK();
243 DEFINE(TI_TASK, offsetof(struct thread_info, task));
244 DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
245 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
246 DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
247 DEFINE(TI_SEGMENT, offsetof(struct thread_info, addr_limit));
248 DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
249 DEFINE(THREAD_SZ, sizeof(struct thread_info));
250 DEFINE(THREAD_SZ_ALGN, align(sizeof(struct thread_info), 64));
251 BLANK();
252 DEFINE(IRQSTAT_SIRQ_PEND, offsetof(irq_cpustat_t, __softirq_pending));
253 DEFINE(IRQSTAT_SZ, sizeof(irq_cpustat_t));
254 BLANK();
255 DEFINE(ICACHE_BASE, offsetof(struct pdc_cache_info, ic_base));
256 DEFINE(ICACHE_STRIDE, offsetof(struct pdc_cache_info, ic_stride));
257 DEFINE(ICACHE_COUNT, offsetof(struct pdc_cache_info, ic_count));
258 DEFINE(ICACHE_LOOP, offsetof(struct pdc_cache_info, ic_loop));
259 DEFINE(DCACHE_BASE, offsetof(struct pdc_cache_info, dc_base));
260 DEFINE(DCACHE_STRIDE, offsetof(struct pdc_cache_info, dc_stride));
261 DEFINE(DCACHE_COUNT, offsetof(struct pdc_cache_info, dc_count));
262 DEFINE(DCACHE_LOOP, offsetof(struct pdc_cache_info, dc_loop));
263 DEFINE(ITLB_SID_BASE, offsetof(struct pdc_cache_info, it_sp_base));
264 DEFINE(ITLB_SID_STRIDE, offsetof(struct pdc_cache_info, it_sp_stride));
265 DEFINE(ITLB_SID_COUNT, offsetof(struct pdc_cache_info, it_sp_count));
266 DEFINE(ITLB_OFF_BASE, offsetof(struct pdc_cache_info, it_off_base));
267 DEFINE(ITLB_OFF_STRIDE, offsetof(struct pdc_cache_info, it_off_stride));
268 DEFINE(ITLB_OFF_COUNT, offsetof(struct pdc_cache_info, it_off_count));
269 DEFINE(ITLB_LOOP, offsetof(struct pdc_cache_info, it_loop));
270 DEFINE(DTLB_SID_BASE, offsetof(struct pdc_cache_info, dt_sp_base));
271 DEFINE(DTLB_SID_STRIDE, offsetof(struct pdc_cache_info, dt_sp_stride));
272 DEFINE(DTLB_SID_COUNT, offsetof(struct pdc_cache_info, dt_sp_count));
273 DEFINE(DTLB_OFF_BASE, offsetof(struct pdc_cache_info, dt_off_base));
274 DEFINE(DTLB_OFF_STRIDE, offsetof(struct pdc_cache_info, dt_off_stride));
275 DEFINE(DTLB_OFF_COUNT, offsetof(struct pdc_cache_info, dt_off_count));
276 DEFINE(DTLB_LOOP, offsetof(struct pdc_cache_info, dt_loop));
277 BLANK();
278 DEFINE(PA_BLOCKSTEP_BIT, 31-PT_BLOCKSTEP_BIT);
279 DEFINE(PA_SINGLESTEP_BIT, 31-PT_SINGLESTEP_BIT);
280 BLANK();
281 DEFINE(ASM_PMD_SHIFT, PMD_SHIFT);
282 DEFINE(ASM_PGDIR_SHIFT, PGDIR_SHIFT);
283 DEFINE(ASM_BITS_PER_PGD, BITS_PER_PGD);
284 DEFINE(ASM_BITS_PER_PMD, BITS_PER_PMD);
285 DEFINE(ASM_BITS_PER_PTE, BITS_PER_PTE);
286 DEFINE(ASM_PGD_PMD_OFFSET, -(PAGE_SIZE << PGD_ORDER));
287 DEFINE(ASM_PMD_ENTRY, ((PAGE_OFFSET & PMD_MASK) >> PMD_SHIFT));
288 DEFINE(ASM_PGD_ENTRY, PAGE_OFFSET >> PGDIR_SHIFT);
289 DEFINE(ASM_PGD_ENTRY_SIZE, PGD_ENTRY_SIZE);
290 DEFINE(ASM_PMD_ENTRY_SIZE, PMD_ENTRY_SIZE);
291 DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE);
292 DEFINE(ASM_PT_INITIAL, PT_INITIAL);
293 DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
294 BLANK();
295 DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
296 DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
297 DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
298 return 0;
299}
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 @@
1/*
2 * Support for 32-bit Linux/Parisc ELF binaries on 64 bit kernels
3 *
4 * Copyright (C) 2000 John Marvin
5 * Copyright (C) 2000 Hewlett Packard Co.
6 *
7 * Heavily inspired from various other efforts to do the same thing
8 * (ia64,sparc64/mips64)
9 */
10
11/* Make sure include/asm-parisc/elf.h does the right thing */
12
13#define ELF_CLASS ELFCLASS32
14
15#define ELF_CORE_COPY_REGS(dst, pt) \
16 memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \
17 { int i; \
18 for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \
19 for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \
20 } \
21 dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \
22 dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \
23 dst[44] = (elf_greg_t) pt->sar; dst[45] = (elf_greg_t) pt->iir; \
24 dst[46] = (elf_greg_t) pt->isr; dst[47] = (elf_greg_t) pt->ior; \
25 dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \
26 dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \
27 dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \
28 dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \
29 dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \
30 dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \
31 dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \
32 dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15);
33
34
35typedef unsigned int elf_greg_t;
36
37#include <linux/spinlock.h>
38#include <asm/processor.h>
39#include <linux/module.h>
40#include <linux/elfcore.h>
41#include <linux/compat.h> /* struct compat_timeval */
42
43#define elf_prstatus elf_prstatus32
44struct elf_prstatus32
45{
46 struct elf_siginfo pr_info; /* Info associated with signal */
47 short pr_cursig; /* Current signal */
48 unsigned int pr_sigpend; /* Set of pending signals */
49 unsigned int pr_sighold; /* Set of held signals */
50 pid_t pr_pid;
51 pid_t pr_ppid;
52 pid_t pr_pgrp;
53 pid_t pr_sid;
54 struct compat_timeval pr_utime; /* User time */
55 struct compat_timeval pr_stime; /* System time */
56 struct compat_timeval pr_cutime; /* Cumulative user time */
57 struct compat_timeval pr_cstime; /* Cumulative system time */
58 elf_gregset_t pr_reg; /* GP registers */
59 int pr_fpvalid; /* True if math co-processor being used. */
60};
61
62#define elf_prpsinfo elf_prpsinfo32
63struct elf_prpsinfo32
64{
65 char pr_state; /* numeric process state */
66 char pr_sname; /* char for pr_state */
67 char pr_zomb; /* zombie */
68 char pr_nice; /* nice val */
69 unsigned int pr_flag; /* flags */
70 u16 pr_uid;
71 u16 pr_gid;
72 pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
73 /* Lots missing */
74 char pr_fname[16]; /* filename of executable */
75 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
76};
77
78#define elf_addr_t unsigned int
79#define init_elf_binfmt init_elf32_binfmt
80
81#define ELF_PLATFORM ("PARISC32\0")
82
83/*
84 * We should probably use this macro to set a flag somewhere to indicate
85 * this is a 32 on 64 process. We could use PER_LINUX_32BIT, or we
86 * could set a processor dependent flag in the thread_struct.
87 */
88
89#define SET_PERSONALITY(ex, ibcs2) \
90 current->personality = PER_LINUX32; \
91 current->thread.map_base = DEFAULT_MAP_BASE32; \
92 current->thread.task_size = DEFAULT_TASK_SIZE32 \
93
94#undef cputime_to_timeval
95#define cputime_to_timeval cputime_to_compat_timeval
96static __inline__ void
97cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
98{
99 unsigned long jiffies = cputime_to_jiffies(cputime);
100 value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
101 value->tv_sec = jiffies / HZ;
102}
103
104#include "../../../fs/binfmt_elf.c"
105
106/* Set up a separate execution domain for ELF32 binaries running
107 * on an ELF64 kernel */
108
109static struct exec_domain parisc32_exec_domain = {
110 .name = "Linux/ELF32",
111 .pers_low = PER_LINUX32,
112 .pers_high = PER_LINUX32,
113};
114
115static int __init parisc32_exec_init(void)
116{
117 /* steal the identity signal mappings from the default domain */
118 parisc32_exec_domain.signal_map = default_exec_domain.signal_map;
119 parisc32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
120
121 register_exec_domain(&parisc32_exec_domain);
122
123 return 0;
124}
125
126__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 @@
1/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
2 *
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 1999 Helge Deller (07-13-1999)
8 * Copyright (C) 1999 SuSE GmbH Nuernberg
9 * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
10 *
11 * Cache and TLB management
12 *
13 */
14
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/mm.h>
18#include <linux/module.h>
19#include <linux/seq_file.h>
20#include <linux/pagemap.h>
21
22#include <asm/pdc.h>
23#include <asm/cache.h>
24#include <asm/cacheflush.h>
25#include <asm/tlbflush.h>
26#include <asm/system.h>
27#include <asm/page.h>
28#include <asm/pgalloc.h>
29#include <asm/processor.h>
30
31int split_tlb;
32int dcache_stride;
33int icache_stride;
34EXPORT_SYMBOL(dcache_stride);
35
36
37#if defined(CONFIG_SMP)
38/* On some machines (e.g. ones with the Merced bus), there can be
39 * only a single PxTLB broadcast at a time; this must be guaranteed
40 * by software. We put a spinlock around all TLB flushes to
41 * ensure this.
42 */
43DEFINE_SPINLOCK(pa_tlb_lock);
44EXPORT_SYMBOL(pa_tlb_lock);
45#endif
46
47struct pdc_cache_info cache_info;
48#ifndef CONFIG_PA20
49static struct pdc_btlb_info btlb_info;
50#endif
51
52#ifdef CONFIG_SMP
53void
54flush_data_cache(void)
55{
56 on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
57}
58void
59flush_instruction_cache(void)
60{
61 on_each_cpu((void (*)(void *))flush_instruction_cache_local, NULL, 1, 1);
62}
63#endif
64
65void
66flush_cache_all_local(void)
67{
68 flush_instruction_cache_local();
69 flush_data_cache_local();
70}
71EXPORT_SYMBOL(flush_cache_all_local);
72
73/* flushes EVERYTHING (tlb & cache) */
74
75void
76flush_all_caches(void)
77{
78 flush_cache_all();
79 flush_tlb_all();
80}
81EXPORT_SYMBOL(flush_all_caches);
82
83void
84update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
85{
86 struct page *page = pte_page(pte);
87
88 if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&
89 test_bit(PG_dcache_dirty, &page->flags)) {
90
91 flush_kernel_dcache_page(page_address(page));
92 clear_bit(PG_dcache_dirty, &page->flags);
93 }
94}
95
96void
97show_cache_info(struct seq_file *m)
98{
99 seq_printf(m, "I-cache\t\t: %ld KB\n",
100 cache_info.ic_size/1024 );
101 seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %d-way associative)\n",
102 cache_info.dc_size/1024,
103 (cache_info.dc_conf.cc_wt ? "WT":"WB"),
104 (cache_info.dc_conf.cc_sh ? ", shared I/D":""),
105 (cache_info.dc_conf.cc_assoc)
106 );
107
108 seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
109 cache_info.it_size,
110 cache_info.dt_size,
111 cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
112 );
113
114#ifndef CONFIG_PA20
115 /* BTLB - Block TLB */
116 if (btlb_info.max_size==0) {
117 seq_printf(m, "BTLB\t\t: not supported\n" );
118 } else {
119 seq_printf(m,
120 "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
121 "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
122 "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
123 btlb_info.max_size, (int)4096,
124 btlb_info.max_size>>8,
125 btlb_info.fixed_range_info.num_i,
126 btlb_info.fixed_range_info.num_d,
127 btlb_info.fixed_range_info.num_comb,
128 btlb_info.variable_range_info.num_i,
129 btlb_info.variable_range_info.num_d,
130 btlb_info.variable_range_info.num_comb
131 );
132 }
133#endif
134}
135
136void __init
137parisc_cache_init(void)
138{
139 if (pdc_cache_info(&cache_info) < 0)
140 panic("parisc_cache_init: pdc_cache_info failed");
141
142#if 0
143 printk("ic_size %lx dc_size %lx it_size %lx\n",
144 cache_info.ic_size,
145 cache_info.dc_size,
146 cache_info.it_size);
147
148 printk("DC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
149 cache_info.dc_base,
150 cache_info.dc_stride,
151 cache_info.dc_count,
152 cache_info.dc_loop);
153
154 printk("dc_conf = 0x%lx alias %d blk %d line %d shift %d\n",
155 *(unsigned long *) (&cache_info.dc_conf),
156 cache_info.dc_conf.cc_alias,
157 cache_info.dc_conf.cc_block,
158 cache_info.dc_conf.cc_line,
159 cache_info.dc_conf.cc_shift);
160 printk(" wt %d sh %d cst %d assoc %d\n",
161 cache_info.dc_conf.cc_wt,
162 cache_info.dc_conf.cc_sh,
163 cache_info.dc_conf.cc_cst,
164 cache_info.dc_conf.cc_assoc);
165
166 printk("IC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
167 cache_info.ic_base,
168 cache_info.ic_stride,
169 cache_info.ic_count,
170 cache_info.ic_loop);
171
172 printk("ic_conf = 0x%lx alias %d blk %d line %d shift %d\n",
173 *(unsigned long *) (&cache_info.ic_conf),
174 cache_info.ic_conf.cc_alias,
175 cache_info.ic_conf.cc_block,
176 cache_info.ic_conf.cc_line,
177 cache_info.ic_conf.cc_shift);
178 printk(" wt %d sh %d cst %d assoc %d\n",
179 cache_info.ic_conf.cc_wt,
180 cache_info.ic_conf.cc_sh,
181 cache_info.ic_conf.cc_cst,
182 cache_info.ic_conf.cc_assoc);
183
184 printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
185 cache_info.dt_conf.tc_sh,
186 cache_info.dt_conf.tc_page,
187 cache_info.dt_conf.tc_cst,
188 cache_info.dt_conf.tc_aid,
189 cache_info.dt_conf.tc_pad1);
190
191 printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
192 cache_info.it_conf.tc_sh,
193 cache_info.it_conf.tc_page,
194 cache_info.it_conf.tc_cst,
195 cache_info.it_conf.tc_aid,
196 cache_info.it_conf.tc_pad1);
197#endif
198
199 split_tlb = 0;
200 if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) {
201 if (cache_info.dt_conf.tc_sh == 2)
202 printk(KERN_WARNING "Unexpected TLB configuration. "
203 "Will flush I/D separately (could be optimized).\n");
204
205 split_tlb = 1;
206 }
207
208 /* "New and Improved" version from Jim Hull
209 * (1 << (cc_block-1)) * (cc_line << (4 + cnf.cc_shift))
210 */
211#define CAFL_STRIDE(cnf) (cnf.cc_line << (3 + cnf.cc_block + cnf.cc_shift))
212 dcache_stride = CAFL_STRIDE(cache_info.dc_conf);
213 icache_stride = CAFL_STRIDE(cache_info.ic_conf);
214#undef CAFL_STRIDE
215
216#ifndef CONFIG_PA20
217 if (pdc_btlb_info(&btlb_info) < 0) {
218 memset(&btlb_info, 0, sizeof btlb_info);
219 }
220#endif
221
222 if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) ==
223 PDC_MODEL_NVA_UNSUPPORTED) {
224 printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n");
225#if 0
226 panic("SMP kernel required to avoid non-equivalent aliasing");
227#endif
228 }
229}
230
231void disable_sr_hashing(void)
232{
233 int srhash_type;
234
235 switch (boot_cpu_data.cpu_type) {
236 case pcx: /* We shouldn't get this far. setup.c should prevent it. */
237 BUG();
238 return;
239
240 case pcxs:
241 case pcxt:
242 case pcxt_:
243 srhash_type = SRHASH_PCXST;
244 break;
245
246 case pcxl:
247 srhash_type = SRHASH_PCXL;
248 break;
249
250 case pcxl2: /* pcxl2 doesn't support space register hashing */
251 return;
252
253 default: /* Currently all PA2.0 machines use the same ins. sequence */
254 srhash_type = SRHASH_PA20;
255 break;
256 }
257
258 disable_sr_hashing_asm(srhash_type);
259}
260
261void flush_dcache_page(struct page *page)
262{
263 struct address_space *mapping = page_mapping(page);
264 struct vm_area_struct *mpnt;
265 struct prio_tree_iter iter;
266 unsigned long offset;
267 unsigned long addr;
268 pgoff_t pgoff;
269 pte_t *pte;
270 unsigned long pfn = page_to_pfn(page);
271
272
273 if (mapping && !mapping_mapped(mapping)) {
274 set_bit(PG_dcache_dirty, &page->flags);
275 return;
276 }
277
278 flush_kernel_dcache_page(page_address(page));
279
280 if (!mapping)
281 return;
282
283 pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
284
285 /* We have carefully arranged in arch_get_unmapped_area() that
286 * *any* mappings of a file are always congruently mapped (whether
287 * declared as MAP_PRIVATE or MAP_SHARED), so we only need
288 * to flush one address here for them all to become coherent */
289
290 flush_dcache_mmap_lock(mapping);
291 vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
292 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
293 addr = mpnt->vm_start + offset;
294
295 /* Flush instructions produce non access tlb misses.
296 * On PA, we nullify these instructions rather than
297 * taking a page fault if the pte doesn't exist.
298 * This is just for speed. If the page translation
299 * isn't there, there's no point exciting the
300 * nadtlb handler into a nullification frenzy */
301
302
303 if(!(pte = translation_exists(mpnt, addr)))
304 continue;
305
306 /* make sure we really have this page: the private
307 * mappings may cover this area but have COW'd this
308 * particular page */
309 if(pte_pfn(*pte) != pfn)
310 continue;
311
312 __flush_cache_page(mpnt, addr);
313
314 break;
315 }
316 flush_dcache_mmap_unlock(mapping);
317}
318EXPORT_SYMBOL(flush_dcache_page);
319
320/* Defined in arch/parisc/kernel/pacache.S */
321EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
322EXPORT_SYMBOL(flush_kernel_dcache_page);
323EXPORT_SYMBOL(flush_data_cache_local);
324EXPORT_SYMBOL(flush_kernel_icache_range_asm);
325
326void clear_user_page_asm(void *page, unsigned long vaddr)
327{
328 /* This function is implemented in assembly in pacache.S */
329 extern void __clear_user_page_asm(void *page, unsigned long vaddr);
330
331 purge_tlb_start();
332 __clear_user_page_asm(page, vaddr);
333 purge_tlb_end();
334}
335
336#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
337int parisc_cache_flush_threshold = FLUSH_THRESHOLD;
338
339void parisc_setup_cache_timing(void)
340{
341 unsigned long rangetime, alltime;
342 extern char _text; /* start of kernel code, defined by linker */
343 extern char _end; /* end of BSS, defined by linker */
344 unsigned long size;
345
346 alltime = mfctl(16);
347 flush_data_cache();
348 alltime = mfctl(16) - alltime;
349
350 size = (unsigned long)(&_end - _text);
351 rangetime = mfctl(16);
352 flush_kernel_dcache_range((unsigned long)&_text, size);
353 rangetime = mfctl(16) - rangetime;
354
355 printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
356 alltime, size, rangetime);
357
358 /* Racy, but if we see an intermediate value, it's ok too... */
359 parisc_cache_flush_threshold = size * alltime / rangetime;
360
361 parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1);
362 if (!parisc_cache_flush_threshold)
363 parisc_cache_flush_threshold = FLUSH_THRESHOLD;
364
365 printk("Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
366}
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 @@
1/*
2 * drivers.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Copyright (c) 1999 The Puffin Group
10 * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard
11 * Copyright (c) 2001 Helge Deller <deller@gmx.de>
12 * Copyright (c) 2001,2002 Ryan Bradetich
13 * Copyright (c) 2004-2005 Thibaut VARENE <varenet@parisc-linux.org>
14 *
15 * The file handles registering devices and drivers, then matching them.
16 * It's the closest we get to a dating agency.
17 *
18 * If you're thinking about modifying this file, here are some gotchas to
19 * bear in mind:
20 * - 715/Mirage device paths have a dummy device between Lasi and its children
21 * - The EISA adapter may show up as a sibling or child of Wax
22 * - Dino has an optionally functional serial port. If firmware enables it,
23 * it shows up as a child of Dino. If firmware disables it, the buswalk
24 * finds it and it shows up as a child of Cujo
25 * - Dino has both parisc and pci devices as children
26 * - parisc devices are discovered in a random order, including children
27 * before parents in some cases.
28 */
29
30#include <linux/slab.h>
31#include <linux/types.h>
32#include <linux/kernel.h>
33#include <linux/pci.h>
34#include <linux/spinlock.h>
35#include <linux/string.h>
36#include <asm/hardware.h>
37#include <asm/io.h>
38#include <asm/pdc.h>
39#include <asm/parisc-device.h>
40
41/* See comments in include/asm-parisc/pci.h */
42struct hppa_dma_ops *hppa_dma_ops;
43EXPORT_SYMBOL(hppa_dma_ops);
44
45static struct device root = {
46 .bus_id = "parisc",
47};
48
49#define for_each_padev(padev) \
50 for (padev = next_dev(&root); padev != NULL; \
51 padev = next_dev(&padev->dev))
52
53#define check_dev(padev) \
54 (padev->id.hw_type != HPHW_FAULTY) ? padev : next_dev(&padev->dev)
55
56/**
57 * next_dev - enumerates registered devices
58 * @dev: the previous device returned from next_dev
59 *
60 * next_dev does a depth-first search of the tree, returning parents
61 * before children. Returns NULL when there are no more devices.
62 */
63static struct parisc_device *next_dev(struct device *dev)
64{
65 if (!list_empty(&dev->children)) {
66 dev = list_to_dev(dev->children.next);
67 return check_dev(to_parisc_device(dev));
68 }
69
70 while (dev != &root) {
71 if (dev->node.next != &dev->parent->children) {
72 dev = list_to_dev(dev->node.next);
73 return to_parisc_device(dev);
74 }
75 dev = dev->parent;
76 }
77
78 return NULL;
79}
80
81/**
82 * match_device - Report whether this driver can handle this device
83 * @driver: the PA-RISC driver to try
84 * @dev: the PA-RISC device to try
85 */
86static int match_device(struct parisc_driver *driver, struct parisc_device *dev)
87{
88 const struct parisc_device_id *ids;
89
90 for (ids = driver->id_table; ids->sversion; ids++) {
91 if ((ids->sversion != SVERSION_ANY_ID) &&
92 (ids->sversion != dev->id.sversion))
93 continue;
94
95 if ((ids->hw_type != HWTYPE_ANY_ID) &&
96 (ids->hw_type != dev->id.hw_type))
97 continue;
98
99 if ((ids->hversion != HVERSION_ANY_ID) &&
100 (ids->hversion != dev->id.hversion))
101 continue;
102
103 return 1;
104 }
105 return 0;
106}
107
108static void claim_device(struct parisc_driver *driver, struct parisc_device *dev)
109{
110 dev->driver = driver;
111 request_mem_region(dev->hpa, 0x1000, driver->name);
112}
113
114static int parisc_driver_probe(struct device *dev)
115{
116 int rc;
117 struct parisc_device *pa_dev = to_parisc_device(dev);
118 struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
119
120 rc = pa_drv->probe(pa_dev);
121
122 if(!rc)
123 claim_device(pa_drv, pa_dev);
124
125 return rc;
126}
127
128static int parisc_driver_remove(struct device *dev)
129{
130 struct parisc_device *pa_dev = to_parisc_device(dev);
131 struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
132 if (pa_drv->remove)
133 pa_drv->remove(pa_dev);
134 release_mem_region(pa_dev->hpa, 0x1000);
135
136 return 0;
137}
138
139
140/**
141 * register_parisc_driver - Register this driver if it can handle a device
142 * @driver: the PA-RISC driver to try
143 */
144int register_parisc_driver(struct parisc_driver *driver)
145{
146 /* FIXME: we need this because apparently the sti
147 * driver can be registered twice */
148 if(driver->drv.name) {
149 printk(KERN_WARNING
150 "BUG: skipping previously registered driver %s\n",
151 driver->name);
152 return 1;
153 }
154
155 if (!driver->probe) {
156 printk(KERN_WARNING
157 "BUG: driver %s has no probe routine\n",
158 driver->name);
159 return 1;
160 }
161
162 driver->drv.bus = &parisc_bus_type;
163
164 /* We install our own probe and remove routines */
165 WARN_ON(driver->drv.probe != NULL);
166 WARN_ON(driver->drv.remove != NULL);
167
168 driver->drv.probe = parisc_driver_probe;
169 driver->drv.remove = parisc_driver_remove;
170 driver->drv.name = driver->name;
171
172 return driver_register(&driver->drv);
173}
174EXPORT_SYMBOL(register_parisc_driver);
175
176/**
177 * count_parisc_driver - count # of devices this driver would match
178 * @driver: the PA-RISC driver to try
179 *
180 * Use by IOMMU support to "guess" the right size IOPdir.
181 * Formula is something like memsize/(num_iommu * entry_size).
182 */
183int count_parisc_driver(struct parisc_driver *driver)
184{
185 struct parisc_device *device;
186 int cnt = 0;
187
188 for_each_padev(device) {
189 if (match_device(driver, device))
190 cnt++;
191 }
192
193 return cnt;
194}
195
196
197
198/**
199 * unregister_parisc_driver - Unregister this driver from the list of drivers
200 * @driver: the PA-RISC driver to unregister
201 */
202int unregister_parisc_driver(struct parisc_driver *driver)
203{
204 driver_unregister(&driver->drv);
205 return 0;
206}
207EXPORT_SYMBOL(unregister_parisc_driver);
208
209static struct parisc_device *find_device_by_addr(unsigned long hpa)
210{
211 struct parisc_device *dev;
212 for_each_padev(dev) {
213 if (dev->hpa == hpa)
214 return dev;
215 }
216 return NULL;
217}
218
219/**
220 * find_pa_parent_type - Find a parent of a specific type
221 * @dev: The device to start searching from
222 * @type: The device type to search for.
223 *
224 * Walks up the device tree looking for a device of the specified type.
225 * If it finds it, it returns it. If not, it returns NULL.
226 */
227const struct parisc_device *
228find_pa_parent_type(const struct parisc_device *padev, int type)
229{
230 const struct device *dev = &padev->dev;
231 while (dev != &root) {
232 struct parisc_device *candidate = to_parisc_device(dev);
233 if (candidate->id.hw_type == type)
234 return candidate;
235 dev = dev->parent;
236 }
237
238 return NULL;
239}
240
241#ifdef CONFIG_PCI
242static inline int is_pci_dev(struct device *dev)
243{
244 return dev->bus == &pci_bus_type;
245}
246#else
247static inline int is_pci_dev(struct device *dev)
248{
249 return 0;
250}
251#endif
252
253/*
254 * get_node_path fills in @path with the firmware path to the device.
255 * Note that if @node is a parisc device, we don't fill in the 'mod' field.
256 * This is because both callers pass the parent and fill in the mod
257 * themselves. If @node is a PCI device, we do fill it in, even though this
258 * is inconsistent.
259 */
260static void get_node_path(struct device *dev, struct hardware_path *path)
261{
262 int i = 5;
263 memset(&path->bc, -1, 6);
264
265 if (is_pci_dev(dev)) {
266 unsigned int devfn = to_pci_dev(dev)->devfn;
267 path->mod = PCI_FUNC(devfn);
268 path->bc[i--] = PCI_SLOT(devfn);
269 dev = dev->parent;
270 }
271
272 while (dev != &root) {
273 if (is_pci_dev(dev)) {
274 unsigned int devfn = to_pci_dev(dev)->devfn;
275 path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn)<< 5);
276 } else if (dev->bus == &parisc_bus_type) {
277 path->bc[i--] = to_parisc_device(dev)->hw_path;
278 }
279 dev = dev->parent;
280 }
281}
282
283static char *print_hwpath(struct hardware_path *path, char *output)
284{
285 int i;
286 for (i = 0; i < 6; i++) {
287 if (path->bc[i] == -1)
288 continue;
289 output += sprintf(output, "%u/", (unsigned char) path->bc[i]);
290 }
291 output += sprintf(output, "%u", (unsigned char) path->mod);
292 return output;
293}
294
295/**
296 * print_pa_hwpath - Returns hardware path for PA devices
297 * dev: The device to return the path for
298 * output: Pointer to a previously-allocated array to place the path in.
299 *
300 * This function fills in the output array with a human-readable path
301 * to a PA device. This string is compatible with that used by PDC, and
302 * may be printed on the outside of the box.
303 */
304char *print_pa_hwpath(struct parisc_device *dev, char *output)
305{
306 struct hardware_path path;
307
308 get_node_path(dev->dev.parent, &path);
309 path.mod = dev->hw_path;
310 return print_hwpath(&path, output);
311}
312EXPORT_SYMBOL(print_pa_hwpath);
313
314#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
315/**
316 * get_pci_node_path - Determines the hardware path for a PCI device
317 * @pdev: The device to return the path for
318 * @path: Pointer to a previously-allocated array to place the path in.
319 *
320 * This function fills in the hardware_path structure with the route to
321 * the specified PCI device. This structure is suitable for passing to
322 * PDC calls.
323 */
324void get_pci_node_path(struct pci_dev *pdev, struct hardware_path *path)
325{
326 get_node_path(&pdev->dev, path);
327}
328EXPORT_SYMBOL(get_pci_node_path);
329
330/**
331 * print_pci_hwpath - Returns hardware path for PCI devices
332 * dev: The device to return the path for
333 * output: Pointer to a previously-allocated array to place the path in.
334 *
335 * This function fills in the output array with a human-readable path
336 * to a PCI device. This string is compatible with that used by PDC, and
337 * may be printed on the outside of the box.
338 */
339char *print_pci_hwpath(struct pci_dev *dev, char *output)
340{
341 struct hardware_path path;
342
343 get_pci_node_path(dev, &path);
344 return print_hwpath(&path, output);
345}
346EXPORT_SYMBOL(print_pci_hwpath);
347
348#endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */
349
350static void setup_bus_id(struct parisc_device *padev)
351{
352 struct hardware_path path;
353 char *output = padev->dev.bus_id;
354 int i;
355
356 get_node_path(padev->dev.parent, &path);
357
358 for (i = 0; i < 6; i++) {
359 if (path.bc[i] == -1)
360 continue;
361 output += sprintf(output, "%u:", (unsigned char) path.bc[i]);
362 }
363 sprintf(output, "%u", (unsigned char) padev->hw_path);
364}
365
366struct parisc_device * create_tree_node(char id, struct device *parent)
367{
368 struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
369 if (!dev)
370 return NULL;
371
372 memset(dev, 0, sizeof(*dev));
373 dev->hw_path = id;
374 dev->id.hw_type = HPHW_FAULTY;
375
376 dev->dev.parent = parent;
377 setup_bus_id(dev);
378
379 dev->dev.bus = &parisc_bus_type;
380 dev->dma_mask = 0xffffffffUL; /* PARISC devices are 32-bit */
381
382 /* make the generic dma mask a pointer to the parisc one */
383 dev->dev.dma_mask = &dev->dma_mask;
384 dev->dev.coherent_dma_mask = dev->dma_mask;
385 device_register(&dev->dev);
386
387 return dev;
388}
389
390/**
391 * alloc_tree_node - returns a device entry in the iotree
392 * @parent: the parent node in the tree
393 * @id: the element of the module path for this entry
394 *
395 * Checks all the children of @parent for a matching @id. If none
396 * found, it allocates a new device and returns it.
397 */
398static struct parisc_device * alloc_tree_node(struct device *parent, char id)
399{
400 struct device *dev;
401
402 list_for_each_entry(dev, &parent->children, node) {
403 struct parisc_device *padev = to_parisc_device(dev);
404 if (padev->hw_path == id)
405 return padev;
406 }
407
408 return create_tree_node(id, parent);
409}
410
411static struct parisc_device *create_parisc_device(struct hardware_path *modpath)
412{
413 int i;
414 struct device *parent = &root;
415 for (i = 0; i < 6; i++) {
416 if (modpath->bc[i] == -1)
417 continue;
418 parent = &alloc_tree_node(parent, modpath->bc[i])->dev;
419 }
420 return alloc_tree_node(parent, modpath->mod);
421}
422
423struct parisc_device *
424alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path)
425{
426 int status;
427 unsigned long bytecnt;
428 u8 iodc_data[32];
429 struct parisc_device *dev;
430 const char *name;
431
432 /* Check to make sure this device has not already been added - Ryan */
433 if (find_device_by_addr(hpa) != NULL)
434 return NULL;
435
436 status = pdc_iodc_read(&bytecnt, hpa, 0, &iodc_data, 32);
437 if (status != PDC_OK)
438 return NULL;
439
440 dev = create_parisc_device(mod_path);
441 if (dev->id.hw_type != HPHW_FAULTY) {
442 char p[64];
443 print_pa_hwpath(dev, p);
444 printk("Two devices have hardware path %s. Please file a bug with HP.\n"
445 "In the meantime, you could try rearranging your cards.\n", p);
446 return NULL;
447 }
448
449 dev->id.hw_type = iodc_data[3] & 0x1f;
450 dev->id.hversion = (iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4);
451 dev->id.hversion_rev = iodc_data[1] & 0x0f;
452 dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) |
453 (iodc_data[5] << 8) | iodc_data[6];
454 dev->hpa = hpa;
455 name = parisc_hardware_description(&dev->id);
456 if (name) {
457 strlcpy(dev->name, name, sizeof(dev->name));
458 }
459
460 return dev;
461}
462
463static int parisc_generic_match(struct device *dev, struct device_driver *drv)
464{
465 return match_device(to_parisc_driver(drv), to_parisc_device(dev));
466}
467
468#define pa_dev_attr(name, field, format_string) \
469static ssize_t name##_show(struct device *dev, char *buf) \
470{ \
471 struct parisc_device *padev = to_parisc_device(dev); \
472 return sprintf(buf, format_string, padev->field); \
473}
474
475#define pa_dev_attr_id(field, format) pa_dev_attr(field, id.field, format)
476
477pa_dev_attr(irq, irq, "%u\n");
478pa_dev_attr_id(hw_type, "0x%02x\n");
479pa_dev_attr(rev, id.hversion_rev, "0x%x\n");
480pa_dev_attr_id(hversion, "0x%03x\n");
481pa_dev_attr_id(sversion, "0x%05x\n");
482
483static struct device_attribute parisc_device_attrs[] = {
484 __ATTR_RO(irq),
485 __ATTR_RO(hw_type),
486 __ATTR_RO(rev),
487 __ATTR_RO(hversion),
488 __ATTR_RO(sversion),
489 __ATTR_NULL,
490};
491
492struct bus_type parisc_bus_type = {
493 .name = "parisc",
494 .match = parisc_generic_match,
495 .dev_attrs = parisc_device_attrs,
496};
497
498/**
499 * register_parisc_device - Locate a driver to manage this device.
500 * @dev: The parisc device.
501 *
502 * Search the driver list for a driver that is willing to manage
503 * this device.
504 */
505int register_parisc_device(struct parisc_device *dev)
506{
507 if (!dev)
508 return 0;
509
510 if (dev->driver)
511 return 1;
512
513 return 0;
514}
515
516/**
517 * match_pci_device - Matches a pci device against a given hardware path
518 * entry.
519 * @dev: the generic device (known to be contained by a pci_dev).
520 * @index: the current BC index
521 * @modpath: the hardware path.
522 * @return: true if the device matches the hardware path.
523 */
524static int match_pci_device(struct device *dev, int index,
525 struct hardware_path *modpath)
526{
527 struct pci_dev *pdev = to_pci_dev(dev);
528 int id;
529
530 if (index == 5) {
531 /* we are at the end of the path, and on the actual device */
532 unsigned int devfn = pdev->devfn;
533 return ((modpath->bc[5] == PCI_SLOT(devfn)) &&
534 (modpath->mod == PCI_FUNC(devfn)));
535 }
536
537 id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5);
538 return (modpath->bc[index] == id);
539}
540
541/**
542 * match_parisc_device - Matches a parisc device against a given hardware
543 * path entry.
544 * @dev: the generic device (known to be contained by a parisc_device).
545 * @index: the current BC index
546 * @modpath: the hardware path.
547 * @return: true if the device matches the hardware path.
548 */
549static int match_parisc_device(struct device *dev, int index,
550 struct hardware_path *modpath)
551{
552 struct parisc_device *curr = to_parisc_device(dev);
553 char id = (index == 6) ? modpath->mod : modpath->bc[index];
554
555 return (curr->hw_path == id);
556}
557
558/**
559 * parse_tree_node - returns a device entry in the iotree
560 * @parent: the parent node in the tree
561 * @index: the current BC index
562 * @modpath: the hardware_path struct to match a device against
563 * @return: The corresponding device if found, NULL otherwise.
564 *
565 * Checks all the children of @parent for a matching @id. If none
566 * found, it returns NULL.
567 */
568static struct device *
569parse_tree_node(struct device *parent, int index, struct hardware_path *modpath)
570{
571 struct device *device;
572
573 list_for_each_entry(device, &parent->children, node) {
574 if (device->bus == &parisc_bus_type) {
575 if (match_parisc_device(device, index, modpath))
576 return device;
577 } else if (is_pci_dev(device)) {
578 if (match_pci_device(device, index, modpath))
579 return device;
580 } else if (device->bus == NULL) {
581 /* we are on a bus bridge */
582 struct device *new = parse_tree_node(device, index, modpath);
583 if (new)
584 return new;
585 }
586 }
587
588 return NULL;
589}
590
591/**
592 * hwpath_to_device - Finds the generic device corresponding to a given hardware path.
593 * @modpath: the hardware path.
594 * @return: The target device, NULL if not found.
595 */
596struct device *hwpath_to_device(struct hardware_path *modpath)
597{
598 int i;
599 struct device *parent = &root;
600 for (i = 0; i < 6; i++) {
601 if (modpath->bc[i] == -1)
602 continue;
603 parent = parse_tree_node(parent, i, modpath);
604 if (!parent)
605 return NULL;
606 }
607 if (is_pci_dev(parent)) /* pci devices already parse MOD */
608 return parent;
609 else
610 return parse_tree_node(parent, 6, modpath);
611}
612EXPORT_SYMBOL(hwpath_to_device);
613
614/**
615 * device_to_hwpath - Populates the hwpath corresponding to the given device.
616 * @param dev the target device
617 * @param path pointer to a previously allocated hwpath struct to be filled in
618 */
619void device_to_hwpath(struct device *dev, struct hardware_path *path)
620{
621 struct parisc_device *padev;
622 if (dev->bus == &parisc_bus_type) {
623 padev = to_parisc_device(dev);
624 get_node_path(dev->parent, path);
625 path->mod = padev->hw_path;
626 } else if (is_pci_dev(dev)) {
627 get_node_path(dev, path);
628 }
629}
630EXPORT_SYMBOL(device_to_hwpath);
631
632#define BC_PORT_MASK 0x8
633#define BC_LOWER_PORT 0x8
634
635#define BUS_CONVERTER(dev) \
636 ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT))
637
638#define IS_LOWER_PORT(dev) \
639 ((gsc_readl(dev->hpa + offsetof(struct bc_module, io_status)) \
640 & BC_PORT_MASK) == BC_LOWER_PORT)
641
642#define MAX_NATIVE_DEVICES 64
643#define NATIVE_DEVICE_OFFSET 0x1000
644
645#define FLEX_MASK F_EXTEND(0xfffc0000)
646#define IO_IO_LOW offsetof(struct bc_module, io_io_low)
647#define IO_IO_HIGH offsetof(struct bc_module, io_io_high)
648#define READ_IO_IO_LOW(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_LOW)
649#define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_HIGH)
650
651static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
652 struct device *parent);
653
654void walk_lower_bus(struct parisc_device *dev)
655{
656 unsigned long io_io_low, io_io_high;
657
658 if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev))
659 return;
660
661 if(dev->id.hw_type == HPHW_IOA) {
662 io_io_low = (unsigned long)(signed int)(READ_IO_IO_LOW(dev) << 16);
663 io_io_high = io_io_low + MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET;
664 } else {
665 io_io_low = (READ_IO_IO_LOW(dev) + ~FLEX_MASK) & FLEX_MASK;
666 io_io_high = (READ_IO_IO_HIGH(dev)+ ~FLEX_MASK) & FLEX_MASK;
667 }
668
669 walk_native_bus(io_io_low, io_io_high, &dev->dev);
670}
671
672/**
673 * walk_native_bus -- Probe a bus for devices
674 * @io_io_low: Base address of this bus.
675 * @io_io_high: Last address of this bus.
676 * @parent: The parent bus device.
677 *
678 * A native bus (eg Runway or GSC) may have up to 64 devices on it,
679 * spaced at intervals of 0x1000 bytes. PDC may not inform us of these
680 * devices, so we have to probe for them. Unfortunately, we may find
681 * devices which are not physically connected (such as extra serial &
682 * keyboard ports). This problem is not yet solved.
683 */
684static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
685 struct device *parent)
686{
687 int i, devices_found = 0;
688 unsigned long hpa = io_io_low;
689 struct hardware_path path;
690
691 get_node_path(parent, &path);
692 do {
693 for(i = 0; i < MAX_NATIVE_DEVICES; i++, hpa += NATIVE_DEVICE_OFFSET) {
694 struct parisc_device *dev;
695
696 /* Was the device already added by Firmware? */
697 dev = find_device_by_addr(hpa);
698 if (!dev) {
699 path.mod = i;
700 dev = alloc_pa_dev(hpa, &path);
701 if (!dev)
702 continue;
703
704 register_parisc_device(dev);
705 devices_found++;
706 }
707 walk_lower_bus(dev);
708 }
709 } while(!devices_found && hpa < io_io_high);
710}
711
712#define CENTRAL_BUS_ADDR F_EXTEND(0xfff80000)
713
714/**
715 * walk_central_bus - Find devices attached to the central bus
716 *
717 * PDC doesn't tell us about all devices in the system. This routine
718 * finds devices connected to the central bus.
719 */
720void walk_central_bus(void)
721{
722 walk_native_bus(CENTRAL_BUS_ADDR,
723 CENTRAL_BUS_ADDR + (MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET),
724 &root);
725}
726
727static void print_parisc_device(struct parisc_device *dev)
728{
729 char hw_path[64];
730 static int count;
731
732 print_pa_hwpath(dev, hw_path);
733 printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
734 ++count, dev->name, dev->hpa, hw_path, dev->id.hw_type,
735 dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
736
737 if (dev->num_addrs) {
738 int k;
739 printk(", additional addresses: ");
740 for (k = 0; k < dev->num_addrs; k++)
741 printk("0x%lx ", dev->addr[k]);
742 }
743 printk("\n");
744}
745
746/**
747 * init_parisc_bus - Some preparation to be done before inventory
748 */
749void init_parisc_bus(void)
750{
751 bus_register(&parisc_bus_type);
752 device_register(&root);
753 get_device(&root);
754}
755
756/**
757 * print_parisc_devices - Print out a list of devices found in this system
758 */
759void print_parisc_devices(void)
760{
761 struct parisc_device *dev;
762 for_each_padev(dev) {
763 print_parisc_device(dev);
764 }
765}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * kernel entry points (interruptions, system call wrappers)
5 * Copyright (C) 1999,2000 Philipp Rumpf
6 * Copyright (C) 1999 SuSE GmbH Nuernberg
7 * Copyright (C) 2000 Hewlett-Packard (John Marvin)
8 * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/config.h>
26#include <asm/offsets.h>
27
28/* we have the following possibilities to act on an interruption:
29 * - handle in assembly and use shadowed registers only
30 * - save registers to kernel stack and handle in assembly or C */
31
32
33#include <asm/assembly.h> /* for LDREG/STREG defines */
34#include <asm/pgtable.h>
35#include <asm/psw.h>
36#include <asm/signal.h>
37#include <asm/unistd.h>
38#include <asm/thread_info.h>
39
40#ifdef __LP64__
41#define CMPIB cmpib,*
42#define CMPB cmpb,*
43#define COND(x) *x
44
45 .level 2.0w
46#else
47#define CMPIB cmpib,
48#define CMPB cmpb,
49#define COND(x) x
50
51 .level 2.0
52#endif
53
54 .import pa_dbit_lock,data
55
56 /* space_to_prot macro creates a prot id from a space id */
57
58#if (SPACEID_SHIFT) == 0
59 .macro space_to_prot spc prot
60 depd,z \spc,62,31,\prot
61 .endm
62#else
63 .macro space_to_prot spc prot
64 extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot
65 .endm
66#endif
67
68 /* Switch to virtual mapping, trashing only %r1 */
69 .macro virt_map
70 rsm PSW_SM_Q,%r0
71 tovirt_r1 %r29
72 mfsp %sr7, %r1
73 or,= %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */
74 mtsp %r1, %sr3
75 mtsp %r0, %sr4
76 mtsp %r0, %sr5
77 mtsp %r0, %sr6
78 mtsp %r0, %sr7
79 load32 KERNEL_PSW, %r1
80 mtctl %r1, %cr22
81 mtctl %r0, %cr17 /* Clear IIASQ tail */
82 mtctl %r0, %cr17 /* Clear IIASQ head */
83 load32 4f, %r1
84 mtctl %r1, %cr18 /* Set IIAOQ tail */
85 ldo 4(%r1), %r1
86 mtctl %r1, %cr18 /* Set IIAOQ head */
87 rfir
88 nop
894:
90 .endm
91
92 /*
93 * The "get_stack" macros are responsible for determining the
94 * kernel stack value.
95 *
96 * For Faults:
97 * If sr7 == 0
98 * Already using a kernel stack, so call the
99 * get_stack_use_r30 macro to push a pt_regs structure
100 * on the stack, and store registers there.
101 * else
102 * Need to set up a kernel stack, so call the
103 * get_stack_use_cr30 macro to set up a pointer
104 * to the pt_regs structure contained within the
105 * task pointer pointed to by cr30. Set the stack
106 * pointer to point to the end of the task structure.
107 *
108 * For Interrupts:
109 * If sr7 == 0
110 * Already using a kernel stack, check to see if r30
111 * is already pointing to the per processor interrupt
112 * stack. If it is, call the get_stack_use_r30 macro
113 * to push a pt_regs structure on the stack, and store
114 * registers there. Otherwise, call get_stack_use_cr31
115 * to get a pointer to the base of the interrupt stack
116 * and push a pt_regs structure on that stack.
117 * else
118 * Need to set up a kernel stack, so call the
119 * get_stack_use_cr30 macro to set up a pointer
120 * to the pt_regs structure contained within the
121 * task pointer pointed to by cr30. Set the stack
122 * pointer to point to the end of the task structure.
123 * N.B: We don't use the interrupt stack for the
124 * first interrupt from userland, because signals/
125 * resched's are processed when returning to userland,
126 * and we can sleep in those cases.
127 *
128 * Note that we use shadowed registers for temps until
129 * we can save %r26 and %r29. %r26 is used to preserve
130 * %r8 (a shadowed register) which temporarily contained
131 * either the fault type ("code") or the eirr. We need
132 * to use a non-shadowed register to carry the value over
133 * the rfir in virt_map. We use %r26 since this value winds
134 * up being passed as the argument to either do_cpu_irq_mask
135 * or handle_interruption. %r29 is used to hold a pointer
136 * the register save area, and once again, it needs to
137 * be a non-shadowed register so that it survives the rfir.
138 *
139 * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame.
140 */
141
142 .macro get_stack_use_cr30
143
144 /* we save the registers in the task struct */
145
146 mfctl %cr30, %r1
147 tophys %r1,%r9
148 LDREG TI_TASK(%r9), %r1 /* thread_info -> task_struct */
149 tophys %r1,%r9
150 ldo TASK_REGS(%r9),%r9
151 STREG %r30, PT_GR30(%r9)
152 STREG %r29,PT_GR29(%r9)
153 STREG %r26,PT_GR26(%r9)
154 copy %r9,%r29
155 mfctl %cr30, %r1
156 ldo THREAD_SZ_ALGN(%r1), %r30
157 .endm
158
159 .macro get_stack_use_r30
160
161 /* we put a struct pt_regs on the stack and save the registers there */
162
163 tophys %r30,%r9
164 STREG %r30,PT_GR30(%r9)
165 ldo PT_SZ_ALGN(%r30),%r30
166 STREG %r29,PT_GR29(%r9)
167 STREG %r26,PT_GR26(%r9)
168 copy %r9,%r29
169 .endm
170
171 .macro rest_stack
172 LDREG PT_GR1(%r29), %r1
173 LDREG PT_GR30(%r29),%r30
174 LDREG PT_GR29(%r29),%r29
175 .endm
176
177 /* default interruption handler
178 * (calls traps.c:handle_interruption) */
179 .macro def code
180 b intr_save
181 ldi \code, %r8
182 .align 32
183 .endm
184
185 /* Interrupt interruption handler
186 * (calls irq.c:do_cpu_irq_mask) */
187 .macro extint code
188 b intr_extint
189 mfsp %sr7,%r16
190 .align 32
191 .endm
192
193 .import os_hpmc, code
194
195 /* HPMC handler */
196 .macro hpmc code
197 nop /* must be a NOP, will be patched later */
198 load32 PA(os_hpmc), %r3
199 bv,n 0(%r3)
200 nop
201 .word 0 /* checksum (will be patched) */
202 .word PA(os_hpmc) /* address of handler */
203 .word 0 /* length of handler */
204 .endm
205
206 /*
207 * Performance Note: Instructions will be moved up into
208 * this part of the code later on, once we are sure
209 * that the tlb miss handlers are close to final form.
210 */
211
212 /* Register definitions for tlb miss handler macros */
213
214 va = r8 /* virtual address for which the trap occured */
215 spc = r24 /* space for which the trap occured */
216
217#ifndef __LP64__
218
219 /*
220 * itlb miss interruption handler (parisc 1.1 - 32 bit)
221 */
222
223 .macro itlb_11 code
224
225 mfctl %pcsq, spc
226 b itlb_miss_11
227 mfctl %pcoq, va
228
229 .align 32
230 .endm
231#endif
232
233 /*
234 * itlb miss interruption handler (parisc 2.0)
235 */
236
237 .macro itlb_20 code
238 mfctl %pcsq, spc
239#ifdef __LP64__
240 b itlb_miss_20w
241#else
242 b itlb_miss_20
243#endif
244 mfctl %pcoq, va
245
246 .align 32
247 .endm
248
249#ifndef __LP64__
250 /*
251 * naitlb miss interruption handler (parisc 1.1 - 32 bit)
252 *
253 * Note: naitlb misses will be treated
254 * as an ordinary itlb miss for now.
255 * However, note that naitlb misses
256 * have the faulting address in the
257 * IOR/ISR.
258 */
259
260 .macro naitlb_11 code
261
262 mfctl %isr,spc
263 b itlb_miss_11
264 mfctl %ior,va
265 /* FIXME: If user causes a naitlb miss, the priv level may not be in
266 * lower bits of va, where the itlb miss handler is expecting them
267 */
268
269 .align 32
270 .endm
271#endif
272
273 /*
274 * naitlb miss interruption handler (parisc 2.0)
275 *
276 * Note: naitlb misses will be treated
277 * as an ordinary itlb miss for now.
278 * However, note that naitlb misses
279 * have the faulting address in the
280 * IOR/ISR.
281 */
282
283 .macro naitlb_20 code
284
285 mfctl %isr,spc
286#ifdef __LP64__
287 b itlb_miss_20w
288#else
289 b itlb_miss_20
290#endif
291 mfctl %ior,va
292 /* FIXME: If user causes a naitlb miss, the priv level may not be in
293 * lower bits of va, where the itlb miss handler is expecting them
294 */
295
296 .align 32
297 .endm
298
299#ifndef __LP64__
300 /*
301 * dtlb miss interruption handler (parisc 1.1 - 32 bit)
302 */
303
304 .macro dtlb_11 code
305
306 mfctl %isr, spc
307 b dtlb_miss_11
308 mfctl %ior, va
309
310 .align 32
311 .endm
312#endif
313
314 /*
315 * dtlb miss interruption handler (parisc 2.0)
316 */
317
318 .macro dtlb_20 code
319
320 mfctl %isr, spc
321#ifdef __LP64__
322 b dtlb_miss_20w
323#else
324 b dtlb_miss_20
325#endif
326 mfctl %ior, va
327
328 .align 32
329 .endm
330
331#ifndef __LP64__
332 /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */
333
334 .macro nadtlb_11 code
335
336 mfctl %isr,spc
337 b nadtlb_miss_11
338 mfctl %ior,va
339
340 .align 32
341 .endm
342#endif
343
344 /* nadtlb miss interruption handler (parisc 2.0) */
345
346 .macro nadtlb_20 code
347
348 mfctl %isr,spc
349#ifdef __LP64__
350 b nadtlb_miss_20w
351#else
352 b nadtlb_miss_20
353#endif
354 mfctl %ior,va
355
356 .align 32
357 .endm
358
359#ifndef __LP64__
360 /*
361 * dirty bit trap interruption handler (parisc 1.1 - 32 bit)
362 */
363
364 .macro dbit_11 code
365
366 mfctl %isr,spc
367 b dbit_trap_11
368 mfctl %ior,va
369
370 .align 32
371 .endm
372#endif
373
374 /*
375 * dirty bit trap interruption handler (parisc 2.0)
376 */
377
378 .macro dbit_20 code
379
380 mfctl %isr,spc
381#ifdef __LP64__
382 b dbit_trap_20w
383#else
384 b dbit_trap_20
385#endif
386 mfctl %ior,va
387
388 .align 32
389 .endm
390
391 /* The following are simple 32 vs 64 bit instruction
392 * abstractions for the macros */
393 .macro EXTR reg1,start,length,reg2
394#ifdef __LP64__
395 extrd,u \reg1,32+\start,\length,\reg2
396#else
397 extrw,u \reg1,\start,\length,\reg2
398#endif
399 .endm
400
401 .macro DEP reg1,start,length,reg2
402#ifdef __LP64__
403 depd \reg1,32+\start,\length,\reg2
404#else
405 depw \reg1,\start,\length,\reg2
406#endif
407 .endm
408
409 .macro DEPI val,start,length,reg
410#ifdef __LP64__
411 depdi \val,32+\start,\length,\reg
412#else
413 depwi \val,\start,\length,\reg
414#endif
415 .endm
416
417 /* In LP64, the space contains part of the upper 32 bits of the
418 * fault. We have to extract this and place it in the va,
419 * zeroing the corresponding bits in the space register */
420 .macro space_adjust spc,va,tmp
421#ifdef __LP64__
422 extrd,u \spc,63,SPACEID_SHIFT,\tmp
423 depd %r0,63,SPACEID_SHIFT,\spc
424 depd \tmp,31,SPACEID_SHIFT,\va
425#endif
426 .endm
427
428 .import swapper_pg_dir,code
429
430 /* Get the pgd. For faults on space zero (kernel space), this
431 * is simply swapper_pg_dir. For user space faults, the
432 * pgd is stored in %cr25 */
433 .macro get_pgd spc,reg
434 ldil L%PA(swapper_pg_dir),\reg
435 ldo R%PA(swapper_pg_dir)(\reg),\reg
436 or,COND(=) %r0,\spc,%r0
437 mfctl %cr25,\reg
438 .endm
439
440 /*
441 space_check(spc,tmp,fault)
442
443 spc - The space we saw the fault with.
444 tmp - The place to store the current space.
445 fault - Function to call on failure.
446
447 Only allow faults on different spaces from the
448 currently active one if we're the kernel
449
450 */
451 .macro space_check spc,tmp,fault
452 mfsp %sr7,\tmp
453 or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page
454 * as kernel, so defeat the space
455 * check if it is */
456 copy \spc,\tmp
457 or,COND(=) %r0,\tmp,%r0 /* nullify if executing as kernel */
458 cmpb,COND(<>),n \tmp,\spc,\fault
459 .endm
460
461 /* Look up a PTE in a 2-Level scheme (faulting at each
462 * level if the entry isn't present
463 *
464 * NOTE: we use ldw even for LP64, since the short pointers
465 * can address up to 1TB
466 */
467 .macro L2_ptep pmd,pte,index,va,fault
468#if PT_NLEVELS == 3
469 EXTR \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
470#else
471 EXTR \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
472#endif
473 DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */
474 copy %r0,\pte
475 ldw,s \index(\pmd),\pmd
476 bb,>=,n \pmd,_PxD_PRESENT_BIT,\fault
477 DEP %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
478 copy \pmd,%r9
479#ifdef __LP64__
480 shld %r9,PxD_VALUE_SHIFT,\pmd
481#else
482 shlw %r9,PxD_VALUE_SHIFT,\pmd
483#endif
484 EXTR \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
485 DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */
486 shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd
487 LDREG %r0(\pmd),\pte /* pmd is now pte */
488 bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault
489 .endm
490
491 /* Look up PTE in a 3-Level scheme.
492 *
493 * Here we implement a Hybrid L2/L3 scheme: we allocate the
494 * first pmd adjacent to the pgd. This means that we can
495 * subtract a constant offset to get to it. The pmd and pgd
496 * sizes are arranged so that a single pmd covers 4GB (giving
497 * a full LP64 process access to 8TB) so our lookups are
498 * effectively L2 for the first 4GB of the kernel (i.e. for
499 * all ILP32 processes and all the kernel for machines with
500 * under 4GB of memory) */
501 .macro L3_ptep pgd,pte,index,va,fault
502 extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
503 copy %r0,\pte
504 extrd,u,*= \va,31,32,%r0
505 ldw,s \index(\pgd),\pgd
506 extrd,u,*= \va,31,32,%r0
507 bb,>=,n \pgd,_PxD_PRESENT_BIT,\fault
508 extrd,u,*= \va,31,32,%r0
509 shld \pgd,PxD_VALUE_SHIFT,\index
510 extrd,u,*= \va,31,32,%r0
511 copy \index,\pgd
512 extrd,u,*<> \va,31,32,%r0
513 ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd
514 L2_ptep \pgd,\pte,\index,\va,\fault
515 .endm
516
517 /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and
518 * don't needlessly dirty the cache line if it was already set */
519 .macro update_ptep ptep,pte,tmp,tmp1
520 ldi _PAGE_ACCESSED,\tmp1
521 or \tmp1,\pte,\tmp
522 and,COND(<>) \tmp1,\pte,%r0
523 STREG \tmp,0(\ptep)
524 .endm
525
526 /* Set the dirty bit (and accessed bit). No need to be
527 * clever, this is only used from the dirty fault */
528 .macro update_dirty ptep,pte,tmp
529 ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp
530 or \tmp,\pte,\pte
531 STREG \pte,0(\ptep)
532 .endm
533
534 /* Convert the pte and prot to tlb insertion values. How
535 * this happens is quite subtle, read below */
536 .macro make_insert_tlb spc,pte,prot
537 space_to_prot \spc \prot /* create prot id from space */
538 /* The following is the real subtlety. This is depositing
539 * T <-> _PAGE_REFTRAP
540 * D <-> _PAGE_DIRTY
541 * B <-> _PAGE_DMB (memory break)
542 *
543 * Then incredible subtlety: The access rights are
544 * _PAGE_GATEWAY _PAGE_EXEC _PAGE_READ
545 * See 3-14 of the parisc 2.0 manual
546 *
547 * Finally, _PAGE_READ goes in the top bit of PL1 (so we
548 * trigger an access rights trap in user space if the user
549 * tries to read an unreadable page */
550 depd \pte,8,7,\prot
551
552 /* PAGE_USER indicates the page can be read with user privileges,
553 * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1
554 * contains _PAGE_READ */
555 extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0
556 depdi 7,11,3,\prot
557 /* If we're a gateway page, drop PL2 back to zero for promotion
558 * to kernel privilege (so we can execute the page as kernel).
559 * Any privilege promotion page always denys read and write */
560 extrd,u,*= \pte,_PAGE_GATEWAY_BIT+32,1,%r0
561 depd %r0,11,2,\prot /* If Gateway, Set PL2 to 0 */
562
563 /* Get rid of prot bits and convert to page addr for iitlbt */
564
565 depd %r0,63,PAGE_SHIFT,\pte
566 extrd,u \pte,56,32,\pte
567 .endm
568
569 /* Identical macro to make_insert_tlb above, except it
570 * makes the tlb entry for the differently formatted pa11
571 * insertion instructions */
572 .macro make_insert_tlb_11 spc,pte,prot
573 zdep \spc,30,15,\prot
574 dep \pte,8,7,\prot
575 extru,= \pte,_PAGE_NO_CACHE_BIT,1,%r0
576 depi 1,12,1,\prot
577 extru,= \pte,_PAGE_USER_BIT,1,%r0
578 depi 7,11,3,\prot /* Set for user space (1 rsvd for read) */
579 extru,= \pte,_PAGE_GATEWAY_BIT,1,%r0
580 depi 0,11,2,\prot /* If Gateway, Set PL2 to 0 */
581
582 /* Get rid of prot bits and convert to page addr for iitlba */
583
584 depi 0,31,12,\pte
585 extru \pte,24,25,\pte
586
587 .endm
588
589 /* This is for ILP32 PA2.0 only. The TLB insertion needs
590 * to extend into I/O space if the address is 0xfXXXXXXX
591 * so we extend the f's into the top word of the pte in
592 * this case */
593 .macro f_extend pte,tmp
594 extrd,s \pte,42,4,\tmp
595 addi,<> 1,\tmp,%r0
596 extrd,s \pte,63,25,\pte
597 .endm
598
599 /* The alias region is an 8MB aligned 16MB to do clear and
600 * copy user pages at addresses congruent with the user
601 * virtual address.
602 *
603 * To use the alias page, you set %r26 up with the to TLB
604 * entry (identifying the physical page) and %r23 up with
605 * the from tlb entry (or nothing if only a to entry---for
606 * clear_user_page_asm) */
607 .macro do_alias spc,tmp,tmp1,va,pte,prot,fault
608 cmpib,COND(<>),n 0,\spc,\fault
609 ldil L%(TMPALIAS_MAP_START),\tmp
610#if defined(__LP64__) && (TMPALIAS_MAP_START >= 0x80000000)
611 /* on LP64, ldi will sign extend into the upper 32 bits,
612 * which is behaviour we don't want */
613 depdi 0,31,32,\tmp
614#endif
615 copy \va,\tmp1
616 DEPI 0,31,23,\tmp1
617 cmpb,COND(<>),n \tmp,\tmp1,\fault
618 ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
619 depd,z \prot,8,7,\prot
620 /*
621 * OK, it is in the temp alias region, check whether "from" or "to".
622 * Check "subtle" note in pacache.S re: r23/r26.
623 */
624#ifdef __LP64__
625 extrd,u,*= \va,41,1,%r0
626#else
627 extrw,u,= \va,9,1,%r0
628#endif
629 or,COND(tr) %r23,%r0,\pte
630 or %r26,%r0,\pte
631 .endm
632
633
634 /*
635 * Align fault_vector_20 on 4K boundary so that both
636 * fault_vector_11 and fault_vector_20 are on the
637 * same page. This is only necessary as long as we
638 * write protect the kernel text, which we may stop
639 * doing once we use large page translations to cover
640 * the static part of the kernel address space.
641 */
642
643 .export fault_vector_20
644
645 .text
646
647 .align 4096
648
649fault_vector_20:
650 /* First vector is invalid (0) */
651 .ascii "cows can fly"
652 .byte 0
653 .align 32
654
655 hpmc 1
656 def 2
657 def 3
658 extint 4
659 def 5
660 itlb_20 6
661 def 7
662 def 8
663 def 9
664 def 10
665 def 11
666 def 12
667 def 13
668 def 14
669 dtlb_20 15
670#if 0
671 naitlb_20 16
672#else
673 def 16
674#endif
675 nadtlb_20 17
676 def 18
677 def 19
678 dbit_20 20
679 def 21
680 def 22
681 def 23
682 def 24
683 def 25
684 def 26
685 def 27
686 def 28
687 def 29
688 def 30
689 def 31
690
691#ifndef __LP64__
692
693 .export fault_vector_11
694
695 .align 2048
696
697fault_vector_11:
698 /* First vector is invalid (0) */
699 .ascii "cows can fly"
700 .byte 0
701 .align 32
702
703 hpmc 1
704 def 2
705 def 3
706 extint 4
707 def 5
708 itlb_11 6
709 def 7
710 def 8
711 def 9
712 def 10
713 def 11
714 def 12
715 def 13
716 def 14
717 dtlb_11 15
718#if 0
719 naitlb_11 16
720#else
721 def 16
722#endif
723 nadtlb_11 17
724 def 18
725 def 19
726 dbit_11 20
727 def 21
728 def 22
729 def 23
730 def 24
731 def 25
732 def 26
733 def 27
734 def 28
735 def 29
736 def 30
737 def 31
738
739#endif
740
741 .import handle_interruption,code
742 .import do_cpu_irq_mask,code
743
744 /*
745 * r26 = function to be called
746 * r25 = argument to pass in
747 * r24 = flags for do_fork()
748 *
749 * Kernel threads don't ever return, so they don't need
750 * a true register context. We just save away the arguments
751 * for copy_thread/ret_ to properly set up the child.
752 */
753
754#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
755#define CLONE_UNTRACED 0x00800000
756
757 .export __kernel_thread, code
758 .import do_fork
759__kernel_thread:
760 STREG %r2, -RP_OFFSET(%r30)
761
762 copy %r30, %r1
763 ldo PT_SZ_ALGN(%r30),%r30
764#ifdef __LP64__
765 /* Yo, function pointers in wide mode are little structs... -PB */
766 ldd 24(%r26), %r2
767 STREG %r2, PT_GR27(%r1) /* Store childs %dp */
768 ldd 16(%r26), %r26
769
770 STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */
771 copy %r0, %r22 /* user_tid */
772#endif
773 STREG %r26, PT_GR26(%r1) /* Store function & argument for child */
774 STREG %r25, PT_GR25(%r1)
775 ldil L%CLONE_UNTRACED, %r26
776 ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */
777 or %r26, %r24, %r26 /* will have kernel mappings. */
778 ldi 1, %r25 /* stack_start, signals kernel thread */
779 stw %r0, -52(%r30) /* user_tid */
780#ifdef __LP64__
781 ldo -16(%r30),%r29 /* Reference param save area */
782#endif
783 BL do_fork, %r2
784 copy %r1, %r24 /* pt_regs */
785
786 /* Parent Returns here */
787
788 LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2
789 ldo -PT_SZ_ALGN(%r30), %r30
790 bv %r0(%r2)
791 nop
792
793 /*
794 * Child Returns here
795 *
796 * copy_thread moved args from temp save area set up above
797 * into task save area.
798 */
799
800 .export ret_from_kernel_thread
801ret_from_kernel_thread:
802
803 /* Call schedule_tail first though */
804 BL schedule_tail, %r2
805 nop
806
807 LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1
808 LDREG TASK_PT_GR25(%r1), %r26
809#ifdef __LP64__
810 LDREG TASK_PT_GR27(%r1), %r27
811 LDREG TASK_PT_GR22(%r1), %r22
812#endif
813 LDREG TASK_PT_GR26(%r1), %r1
814 ble 0(%sr7, %r1)
815 copy %r31, %r2
816
817#ifdef __LP64__
818 ldo -16(%r30),%r29 /* Reference param save area */
819 loadgp /* Thread could have been in a module */
820#endif
821 b sys_exit
822 ldi 0, %r26
823
824 .import sys_execve, code
825 .export __execve, code
826__execve:
827 copy %r2, %r15
828 copy %r30, %r16
829 ldo PT_SZ_ALGN(%r30), %r30
830 STREG %r26, PT_GR26(%r16)
831 STREG %r25, PT_GR25(%r16)
832 STREG %r24, PT_GR24(%r16)
833#ifdef __LP64__
834 ldo -16(%r30),%r29 /* Reference param save area */
835#endif
836 BL sys_execve, %r2
837 copy %r16, %r26
838
839 cmpib,=,n 0,%r28,intr_return /* forward */
840
841 /* yes, this will trap and die. */
842 copy %r15, %r2
843 copy %r16, %r30
844 bv %r0(%r2)
845 nop
846
847 .align 4
848
849 /*
850 * struct task_struct *_switch_to(struct task_struct *prev,
851 * struct task_struct *next)
852 *
853 * switch kernel stacks and return prev */
854 .export _switch_to, code
855_switch_to:
856 STREG %r2, -RP_OFFSET(%r30)
857
858 callee_save
859
860 load32 _switch_to_ret, %r2
861
862 STREG %r2, TASK_PT_KPC(%r26)
863 LDREG TASK_PT_KPC(%r25), %r2
864
865 STREG %r30, TASK_PT_KSP(%r26)
866 LDREG TASK_PT_KSP(%r25), %r30
867 LDREG TASK_THREAD_INFO(%r25), %r25
868 bv %r0(%r2)
869 mtctl %r25,%cr30
870
871_switch_to_ret:
872 mtctl %r0, %cr0 /* Needed for single stepping */
873 callee_rest
874
875 LDREG -RP_OFFSET(%r30), %r2
876 bv %r0(%r2)
877 copy %r26, %r28
878
879 /*
880 * Common rfi return path for interruptions, kernel execve, and
881 * sys_rt_sigreturn (sometimes). The sys_rt_sigreturn syscall will
882 * return via this path if the signal was received when the process
883 * was running; if the process was blocked on a syscall then the
884 * normal syscall_exit path is used. All syscalls for traced
885 * proceses exit via intr_restore.
886 *
887 * XXX If any syscalls that change a processes space id ever exit
888 * this way, then we will need to copy %sr3 in to PT_SR[3..7], and
889 * adjust IASQ[0..1].
890 *
891 * Note that the following code uses a "relied upon translation".
892 * See the parisc ACD for details. The ssm is necessary due to a
893 * PCXT bug.
894 */
895
896 .align 4096
897
898 .export syscall_exit_rfi
899syscall_exit_rfi:
900 mfctl %cr30,%r16
901 LDREG TI_TASK(%r16), %r16 /* thread_info -> task_struct */
902 ldo TASK_REGS(%r16),%r16
903 /* Force iaoq to userspace, as the user has had access to our current
904 * context via sigcontext. Also Filter the PSW for the same reason.
905 */
906 LDREG PT_IAOQ0(%r16),%r19
907 depi 3,31,2,%r19
908 STREG %r19,PT_IAOQ0(%r16)
909 LDREG PT_IAOQ1(%r16),%r19
910 depi 3,31,2,%r19
911 STREG %r19,PT_IAOQ1(%r16)
912 LDREG PT_PSW(%r16),%r19
913 load32 USER_PSW_MASK,%r1
914#ifdef __LP64__
915 load32 USER_PSW_HI_MASK,%r20
916 depd %r20,31,32,%r1
917#endif
918 and %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
919 load32 USER_PSW,%r1
920 or %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
921 STREG %r19,PT_PSW(%r16)
922
923 /*
924 * If we aren't being traced, we never saved space registers
925 * (we don't store them in the sigcontext), so set them
926 * to "proper" values now (otherwise we'll wind up restoring
927 * whatever was last stored in the task structure, which might
928 * be inconsistent if an interrupt occured while on the gateway
929 * page) Note that we may be "trashing" values the user put in
930 * them, but we don't support the the user changing them.
931 */
932
933 STREG %r0,PT_SR2(%r16)
934 mfsp %sr3,%r19
935 STREG %r19,PT_SR0(%r16)
936 STREG %r19,PT_SR1(%r16)
937 STREG %r19,PT_SR3(%r16)
938 STREG %r19,PT_SR4(%r16)
939 STREG %r19,PT_SR5(%r16)
940 STREG %r19,PT_SR6(%r16)
941 STREG %r19,PT_SR7(%r16)
942
943intr_return:
944 /* NOTE: Need to enable interrupts incase we schedule. */
945 ssm PSW_SM_I, %r0
946
947 /* Check for software interrupts */
948
949 .import irq_stat,data
950
951 load32 irq_stat,%r19
952#ifdef CONFIG_SMP
953 mfctl %cr30,%r1
954 ldw TI_CPU(%r1),%r1 /* get cpu # - int */
955 /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
956 ** irq_stat[] is defined using ____cacheline_aligned.
957 */
958#ifdef __LP64__
959 shld %r1, 6, %r20
960#else
961 shlw %r1, 5, %r20
962#endif
963 add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */
964#endif /* CONFIG_SMP */
965
966 LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */
967 cmpib,<>,n 0,%r20,intr_do_softirq /* forward */
968
969intr_check_resched:
970
971 /* check for reschedule */
972 mfctl %cr30,%r1
973 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
974 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
975
976intr_check_sig:
977 /* As above */
978 mfctl %cr30,%r1
979 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_SIGPENDING */
980 bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
981
982intr_restore:
983 copy %r16,%r29
984 ldo PT_FR31(%r29),%r1
985 rest_fp %r1
986 rest_general %r29
987
988 /* Create a "relied upon translation" PA 2.0 Arch. F-5 */
989 ssm 0,%r0
990 nop
991 nop
992 nop
993 nop
994 nop
995 nop
996 nop
997 tophys_r1 %r29
998 rsm (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
999
1000 /* Restore space id's and special cr's from PT_REGS
1001 * structure pointed to by r29 */
1002 rest_specials %r29
1003
1004 /* Important: Note that rest_stack restores r29
1005 * last (we are using it)! It also restores r1 and r30. */
1006 rest_stack
1007
1008 rfi
1009 nop
1010 nop
1011 nop
1012 nop
1013 nop
1014 nop
1015 nop
1016 nop
1017
1018 .import do_softirq,code
1019intr_do_softirq:
1020 bl do_softirq,%r2
1021#ifdef __LP64__
1022 ldo -16(%r30),%r29 /* Reference param save area */
1023#else
1024 nop
1025#endif
1026 b intr_check_resched
1027 nop
1028
1029 .import schedule,code
1030intr_do_resched:
1031 /* Only do reschedule if we are returning to user space */
1032 LDREG PT_IASQ0(%r16), %r20
1033 CMPIB= 0,%r20,intr_restore /* backward */
1034 nop
1035 LDREG PT_IASQ1(%r16), %r20
1036 CMPIB= 0,%r20,intr_restore /* backward */
1037 nop
1038
1039#ifdef __LP64__
1040 ldo -16(%r30),%r29 /* Reference param save area */
1041#endif
1042
1043 ldil L%intr_check_sig, %r2
1044 b schedule
1045 ldo R%intr_check_sig(%r2), %r2
1046
1047
1048 .import do_signal,code
1049intr_do_signal:
1050 /*
1051 This check is critical to having LWS
1052 working. The IASQ is zero on the gateway
1053 page and we cannot deliver any signals until
1054 we get off the gateway page.
1055
1056 Only do signals if we are returning to user space
1057 */
1058 LDREG PT_IASQ0(%r16), %r20
1059 CMPIB= 0,%r20,intr_restore /* backward */
1060 nop
1061 LDREG PT_IASQ1(%r16), %r20
1062 CMPIB= 0,%r20,intr_restore /* backward */
1063 nop
1064
1065 copy %r0, %r24 /* unsigned long in_syscall */
1066 copy %r16, %r25 /* struct pt_regs *regs */
1067#ifdef __LP64__
1068 ldo -16(%r30),%r29 /* Reference param save area */
1069#endif
1070
1071 BL do_signal,%r2
1072 copy %r0, %r26 /* sigset_t *oldset = NULL */
1073
1074 b intr_check_sig
1075 nop
1076
1077 /*
1078 * External interrupts.
1079 */
1080
1081intr_extint:
1082 CMPIB=,n 0,%r16,1f
1083 get_stack_use_cr30
1084 b,n 3f
1085
10861:
1087#if 0 /* Interrupt Stack support not working yet! */
1088 mfctl %cr31,%r1
1089 copy %r30,%r17
1090 /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
1091#ifdef __LP64__
1092 depdi 0,63,15,%r17
1093#else
1094 depi 0,31,15,%r17
1095#endif
1096 CMPB=,n %r1,%r17,2f
1097 get_stack_use_cr31
1098 b,n 3f
1099#endif
11002:
1101 get_stack_use_r30
1102
11033:
1104 save_specials %r29
1105 virt_map
1106 save_general %r29
1107
1108 ldo PT_FR0(%r29), %r24
1109 save_fp %r24
1110
1111 loadgp
1112
1113 copy %r29, %r26 /* arg0 is pt_regs */
1114 copy %r29, %r16 /* save pt_regs */
1115
1116 ldil L%intr_return, %r2
1117
1118#ifdef __LP64__
1119 ldo -16(%r30),%r29 /* Reference param save area */
1120#endif
1121
1122 b do_cpu_irq_mask
1123 ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */
1124
1125
1126 /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
1127
1128 .export intr_save, code /* for os_hpmc */
1129
1130intr_save:
1131 mfsp %sr7,%r16
1132 CMPIB=,n 0,%r16,1f
1133 get_stack_use_cr30
1134 b 2f
1135 copy %r8,%r26
1136
11371:
1138 get_stack_use_r30
1139 copy %r8,%r26
1140
11412:
1142 save_specials %r29
1143
1144 /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
1145
1146 /*
1147 * FIXME: 1) Use a #define for the hardwired "6" below (and in
1148 * traps.c.
1149 * 2) Once we start executing code above 4 Gb, we need
1150 * to adjust iasq/iaoq here in the same way we
1151 * adjust isr/ior below.
1152 */
1153
1154 CMPIB=,n 6,%r26,skip_save_ior
1155
1156 /* save_specials left ipsw value in r8 for us to test */
1157
1158 mfctl %cr20, %r16 /* isr */
1159 mfctl %cr21, %r17 /* ior */
1160
1161#ifdef __LP64__
1162 /*
1163 * If the interrupted code was running with W bit off (32 bit),
1164 * clear the b bits (bits 0 & 1) in the ior.
1165 */
1166 extrd,u,*<> %r8,PSW_W_BIT,1,%r0
1167 depdi 0,1,2,%r17
1168
1169 /*
1170 * FIXME: This code has hardwired assumptions about the split
1171 * between space bits and offset bits. This will change
1172 * when we allow alternate page sizes.
1173 */
1174
1175 /* adjust isr/ior. */
1176
1177 extrd,u %r16,63,7,%r1 /* get high bits from isr for ior */
1178 depd %r1,31,7,%r17 /* deposit them into ior */
1179 depdi 0,63,7,%r16 /* clear them from isr */
1180#endif
1181 STREG %r16, PT_ISR(%r29)
1182 STREG %r17, PT_IOR(%r29)
1183
1184
1185skip_save_ior:
1186 virt_map
1187 save_general %r29
1188
1189 ldo PT_FR0(%r29), %r25
1190 save_fp %r25
1191
1192 loadgp
1193
1194 copy %r29, %r25 /* arg1 is pt_regs */
1195#ifdef __LP64__
1196 ldo -16(%r30),%r29 /* Reference param save area */
1197#endif
1198
1199 ldil L%intr_check_sig, %r2
1200 copy %r25, %r16 /* save pt_regs */
1201
1202 b handle_interruption
1203 ldo R%intr_check_sig(%r2), %r2
1204
1205
1206 /*
1207 * Note for all tlb miss handlers:
1208 *
1209 * cr24 contains a pointer to the kernel address space
1210 * page directory.
1211 *
1212 * cr25 contains a pointer to the current user address
1213 * space page directory.
1214 *
1215 * sr3 will contain the space id of the user address space
1216 * of the current running thread while that thread is
1217 * running in the kernel.
1218 */
1219
1220 /*
1221 * register number allocations. Note that these are all
1222 * in the shadowed registers
1223 */
1224
1225 t0 = r1 /* temporary register 0 */
1226 va = r8 /* virtual address for which the trap occured */
1227 t1 = r9 /* temporary register 1 */
1228 pte = r16 /* pte/phys page # */
1229 prot = r17 /* prot bits */
1230 spc = r24 /* space for which the trap occured */
1231 ptp = r25 /* page directory/page table pointer */
1232
1233#ifdef __LP64__
1234
1235dtlb_miss_20w:
1236 space_adjust spc,va,t0
1237 get_pgd spc,ptp
1238 space_check spc,t0,dtlb_fault
1239
1240 L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w
1241
1242 update_ptep ptp,pte,t0,t1
1243
1244 make_insert_tlb spc,pte,prot
1245
1246 idtlbt pte,prot
1247
1248 rfir
1249 nop
1250
1251dtlb_check_alias_20w:
1252 do_alias spc,t0,t1,va,pte,prot,dtlb_fault
1253
1254 idtlbt pte,prot
1255
1256 rfir
1257 nop
1258
1259nadtlb_miss_20w:
1260 space_adjust spc,va,t0
1261 get_pgd spc,ptp
1262 space_check spc,t0,nadtlb_fault
1263
1264 L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w
1265
1266 update_ptep ptp,pte,t0,t1
1267
1268 make_insert_tlb spc,pte,prot
1269
1270 idtlbt pte,prot
1271
1272 rfir
1273 nop
1274
1275nadtlb_check_flush_20w:
1276 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1277
1278 /* Insert a "flush only" translation */
1279
1280 depdi,z 7,7,3,prot
1281 depdi 1,10,1,prot
1282
1283 /* Get rid of prot bits and convert to page addr for idtlbt */
1284
1285 depdi 0,63,12,pte
1286 extrd,u pte,56,52,pte
1287 idtlbt pte,prot
1288
1289 rfir
1290 nop
1291
1292#else
1293
1294dtlb_miss_11:
1295 get_pgd spc,ptp
1296
1297 space_check spc,t0,dtlb_fault
1298
1299 L2_ptep ptp,pte,t0,va,dtlb_check_alias_11
1300
1301 update_ptep ptp,pte,t0,t1
1302
1303 make_insert_tlb_11 spc,pte,prot
1304
1305 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1306 mtsp spc,%sr1
1307
1308 idtlba pte,(%sr1,va)
1309 idtlbp prot,(%sr1,va)
1310
1311 mtsp t0, %sr1 /* Restore sr1 */
1312
1313 rfir
1314 nop
1315
1316dtlb_check_alias_11:
1317
1318 /* Check to see if fault is in the temporary alias region */
1319
1320 cmpib,<>,n 0,spc,dtlb_fault /* forward */
1321 ldil L%(TMPALIAS_MAP_START),t0
1322 copy va,t1
1323 depwi 0,31,23,t1
1324 cmpb,<>,n t0,t1,dtlb_fault /* forward */
1325 ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1326 depw,z prot,8,7,prot
1327
1328 /*
1329 * OK, it is in the temp alias region, check whether "from" or "to".
1330 * Check "subtle" note in pacache.S re: r23/r26.
1331 */
1332
1333 extrw,u,= va,9,1,r0
1334 or,tr %r23,%r0,pte /* If "from" use "from" page */
1335 or %r26,%r0,pte /* else "to", use "to" page */
1336
1337 idtlba pte,(va)
1338 idtlbp prot,(va)
1339
1340 rfir
1341 nop
1342
1343nadtlb_miss_11:
1344 get_pgd spc,ptp
1345
1346 space_check spc,t0,nadtlb_fault
1347
1348 L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11
1349
1350 update_ptep ptp,pte,t0,t1
1351
1352 make_insert_tlb_11 spc,pte,prot
1353
1354
1355 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1356 mtsp spc,%sr1
1357
1358 idtlba pte,(%sr1,va)
1359 idtlbp prot,(%sr1,va)
1360
1361 mtsp t0, %sr1 /* Restore sr1 */
1362
1363 rfir
1364 nop
1365
1366nadtlb_check_flush_11:
1367 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1368
1369 /* Insert a "flush only" translation */
1370
1371 zdepi 7,7,3,prot
1372 depi 1,10,1,prot
1373
1374 /* Get rid of prot bits and convert to page addr for idtlba */
1375
1376 depi 0,31,12,pte
1377 extru pte,24,25,pte
1378
1379 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1380 mtsp spc,%sr1
1381
1382 idtlba pte,(%sr1,va)
1383 idtlbp prot,(%sr1,va)
1384
1385 mtsp t0, %sr1 /* Restore sr1 */
1386
1387 rfir
1388 nop
1389
1390dtlb_miss_20:
1391 space_adjust spc,va,t0
1392 get_pgd spc,ptp
1393 space_check spc,t0,dtlb_fault
1394
1395 L2_ptep ptp,pte,t0,va,dtlb_check_alias_20
1396
1397 update_ptep ptp,pte,t0,t1
1398
1399 make_insert_tlb spc,pte,prot
1400
1401 f_extend pte,t0
1402
1403 idtlbt pte,prot
1404
1405 rfir
1406 nop
1407
1408dtlb_check_alias_20:
1409 do_alias spc,t0,t1,va,pte,prot,dtlb_fault
1410
1411 idtlbt pte,prot
1412
1413 rfir
1414 nop
1415
1416nadtlb_miss_20:
1417 get_pgd spc,ptp
1418
1419 space_check spc,t0,nadtlb_fault
1420
1421 L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20
1422
1423 update_ptep ptp,pte,t0,t1
1424
1425 make_insert_tlb spc,pte,prot
1426
1427 f_extend pte,t0
1428
1429 idtlbt pte,prot
1430
1431 rfir
1432 nop
1433
1434nadtlb_check_flush_20:
1435 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1436
1437 /* Insert a "flush only" translation */
1438
1439 depdi,z 7,7,3,prot
1440 depdi 1,10,1,prot
1441
1442 /* Get rid of prot bits and convert to page addr for idtlbt */
1443
1444 depdi 0,63,12,pte
1445 extrd,u pte,56,32,pte
1446 idtlbt pte,prot
1447
1448 rfir
1449 nop
1450#endif
1451
1452nadtlb_emulate:
1453
1454 /*
1455 * Non access misses can be caused by fdc,fic,pdc,lpa,probe and
1456 * probei instructions. We don't want to fault for these
1457 * instructions (not only does it not make sense, it can cause
1458 * deadlocks, since some flushes are done with the mmap
1459 * semaphore held). If the translation doesn't exist, we can't
1460 * insert a translation, so have to emulate the side effects
1461 * of the instruction. Since we don't insert a translation
1462 * we can get a lot of faults during a flush loop, so it makes
1463 * sense to try to do it here with minimum overhead. We only
1464 * emulate fdc,fic,pdc,probew,prober instructions whose base
1465 * and index registers are not shadowed. We defer everything
1466 * else to the "slow" path.
1467 */
1468
1469 mfctl %cr19,%r9 /* Get iir */
1470
1471 /* PA 2.0 Arch Ref. Book pg 382 has a good description of the insn bits.
1472 Checks for fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw */
1473
1474 /* Checks for fdc,fdce,pdc,"fic,4f" only */
1475 ldi 0x280,%r16
1476 and %r9,%r16,%r17
1477 cmpb,<>,n %r16,%r17,nadtlb_probe_check
1478 bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */
1479 BL get_register,%r25
1480 extrw,u %r9,15,5,%r8 /* Get index register # */
1481 CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */
1482 copy %r1,%r24
1483 BL get_register,%r25
1484 extrw,u %r9,10,5,%r8 /* Get base register # */
1485 CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */
1486 BL set_register,%r25
1487 add,l %r1,%r24,%r1 /* doesn't affect c/b bits */
1488
1489nadtlb_nullify:
1490 mfctl %cr22,%r8 /* Get ipsw */
1491 ldil L%PSW_N,%r9
1492 or %r8,%r9,%r8 /* Set PSW_N */
1493 mtctl %r8,%cr22
1494
1495 rfir
1496 nop
1497
1498 /*
1499 When there is no translation for the probe address then we
1500 must nullify the insn and return zero in the target regsiter.
1501 This will indicate to the calling code that it does not have
1502 write/read privileges to this address.
1503
1504 This should technically work for prober and probew in PA 1.1,
1505 and also probe,r and probe,w in PA 2.0
1506
1507 WARNING: USE ONLY NON-SHADOW REGISTERS WITH PROBE INSN!
1508 THE SLOW-PATH EMULATION HAS NOT BEEN WRITTEN YET.
1509
1510 */
1511nadtlb_probe_check:
1512 ldi 0x80,%r16
1513 and %r9,%r16,%r17
1514 cmpb,<>,n %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/
1515 BL get_register,%r25 /* Find the target register */
1516 extrw,u %r9,31,5,%r8 /* Get target register */
1517 CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */
1518 BL set_register,%r25
1519 copy %r0,%r1 /* Write zero to target register */
1520 b nadtlb_nullify /* Nullify return insn */
1521 nop
1522
1523
1524#ifdef __LP64__
1525itlb_miss_20w:
1526
1527 /*
1528 * I miss is a little different, since we allow users to fault
1529 * on the gateway page which is in the kernel address space.
1530 */
1531
1532 space_adjust spc,va,t0
1533 get_pgd spc,ptp
1534 space_check spc,t0,itlb_fault
1535
1536 L3_ptep ptp,pte,t0,va,itlb_fault
1537
1538 update_ptep ptp,pte,t0,t1
1539
1540 make_insert_tlb spc,pte,prot
1541
1542 iitlbt pte,prot
1543
1544 rfir
1545 nop
1546
1547#else
1548
1549itlb_miss_11:
1550 get_pgd spc,ptp
1551
1552 space_check spc,t0,itlb_fault
1553
1554 L2_ptep ptp,pte,t0,va,itlb_fault
1555
1556 update_ptep ptp,pte,t0,t1
1557
1558 make_insert_tlb_11 spc,pte,prot
1559
1560 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1561 mtsp spc,%sr1
1562
1563 iitlba pte,(%sr1,va)
1564 iitlbp prot,(%sr1,va)
1565
1566 mtsp t0, %sr1 /* Restore sr1 */
1567
1568 rfir
1569 nop
1570
1571itlb_miss_20:
1572 get_pgd spc,ptp
1573
1574 space_check spc,t0,itlb_fault
1575
1576 L2_ptep ptp,pte,t0,va,itlb_fault
1577
1578 update_ptep ptp,pte,t0,t1
1579
1580 make_insert_tlb spc,pte,prot
1581
1582 f_extend pte,t0
1583
1584 iitlbt pte,prot
1585
1586 rfir
1587 nop
1588
1589#endif
1590
1591#ifdef __LP64__
1592
1593dbit_trap_20w:
1594 space_adjust spc,va,t0
1595 get_pgd spc,ptp
1596 space_check spc,t0,dbit_fault
1597
1598 L3_ptep ptp,pte,t0,va,dbit_fault
1599
1600#ifdef CONFIG_SMP
1601 CMPIB=,n 0,spc,dbit_nolock_20w
1602 load32 PA(pa_dbit_lock),t0
1603
1604dbit_spin_20w:
1605 ldcw 0(t0),t1
1606 cmpib,= 0,t1,dbit_spin_20w
1607 nop
1608
1609dbit_nolock_20w:
1610#endif
1611 update_dirty ptp,pte,t1
1612
1613 make_insert_tlb spc,pte,prot
1614
1615 idtlbt pte,prot
1616#ifdef CONFIG_SMP
1617 CMPIB=,n 0,spc,dbit_nounlock_20w
1618 ldi 1,t1
1619 stw t1,0(t0)
1620
1621dbit_nounlock_20w:
1622#endif
1623
1624 rfir
1625 nop
1626#else
1627
1628dbit_trap_11:
1629
1630 get_pgd spc,ptp
1631
1632 space_check spc,t0,dbit_fault
1633
1634 L2_ptep ptp,pte,t0,va,dbit_fault
1635
1636#ifdef CONFIG_SMP
1637 CMPIB=,n 0,spc,dbit_nolock_11
1638 load32 PA(pa_dbit_lock),t0
1639
1640dbit_spin_11:
1641 ldcw 0(t0),t1
1642 cmpib,= 0,t1,dbit_spin_11
1643 nop
1644
1645dbit_nolock_11:
1646#endif
1647 update_dirty ptp,pte,t1
1648
1649 make_insert_tlb_11 spc,pte,prot
1650
1651 mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */
1652 mtsp spc,%sr1
1653
1654 idtlba pte,(%sr1,va)
1655 idtlbp prot,(%sr1,va)
1656
1657 mtsp t1, %sr1 /* Restore sr1 */
1658#ifdef CONFIG_SMP
1659 CMPIB=,n 0,spc,dbit_nounlock_11
1660 ldi 1,t1
1661 stw t1,0(t0)
1662
1663dbit_nounlock_11:
1664#endif
1665
1666 rfir
1667 nop
1668
1669dbit_trap_20:
1670 get_pgd spc,ptp
1671
1672 space_check spc,t0,dbit_fault
1673
1674 L2_ptep ptp,pte,t0,va,dbit_fault
1675
1676#ifdef CONFIG_SMP
1677 CMPIB=,n 0,spc,dbit_nolock_20
1678 load32 PA(pa_dbit_lock),t0
1679
1680dbit_spin_20:
1681 ldcw 0(t0),t1
1682 cmpib,= 0,t1,dbit_spin_20
1683 nop
1684
1685dbit_nolock_20:
1686#endif
1687 update_dirty ptp,pte,t1
1688
1689 make_insert_tlb spc,pte,prot
1690
1691 f_extend pte,t1
1692
1693 idtlbt pte,prot
1694
1695#ifdef CONFIG_SMP
1696 CMPIB=,n 0,spc,dbit_nounlock_20
1697 ldi 1,t1
1698 stw t1,0(t0)
1699
1700dbit_nounlock_20:
1701#endif
1702
1703 rfir
1704 nop
1705#endif
1706
1707 .import handle_interruption,code
1708
1709kernel_bad_space:
1710 b intr_save
1711 ldi 31,%r8 /* Use an unused code */
1712
1713dbit_fault:
1714 b intr_save
1715 ldi 20,%r8
1716
1717itlb_fault:
1718 b intr_save
1719 ldi 6,%r8
1720
1721nadtlb_fault:
1722 b intr_save
1723 ldi 17,%r8
1724
1725dtlb_fault:
1726 b intr_save
1727 ldi 15,%r8
1728
1729 /* Register saving semantics for system calls:
1730
1731 %r1 clobbered by system call macro in userspace
1732 %r2 saved in PT_REGS by gateway page
1733 %r3 - %r18 preserved by C code (saved by signal code)
1734 %r19 - %r20 saved in PT_REGS by gateway page
1735 %r21 - %r22 non-standard syscall args
1736 stored in kernel stack by gateway page
1737 %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page
1738 %r27 - %r30 saved in PT_REGS by gateway page
1739 %r31 syscall return pointer
1740 */
1741
1742 /* Floating point registers (FIXME: what do we do with these?)
1743
1744 %fr0 - %fr3 status/exception, not preserved
1745 %fr4 - %fr7 arguments
1746 %fr8 - %fr11 not preserved by C code
1747 %fr12 - %fr21 preserved by C code
1748 %fr22 - %fr31 not preserved by C code
1749 */
1750
1751 .macro reg_save regs
1752 STREG %r3, PT_GR3(\regs)
1753 STREG %r4, PT_GR4(\regs)
1754 STREG %r5, PT_GR5(\regs)
1755 STREG %r6, PT_GR6(\regs)
1756 STREG %r7, PT_GR7(\regs)
1757 STREG %r8, PT_GR8(\regs)
1758 STREG %r9, PT_GR9(\regs)
1759 STREG %r10,PT_GR10(\regs)
1760 STREG %r11,PT_GR11(\regs)
1761 STREG %r12,PT_GR12(\regs)
1762 STREG %r13,PT_GR13(\regs)
1763 STREG %r14,PT_GR14(\regs)
1764 STREG %r15,PT_GR15(\regs)
1765 STREG %r16,PT_GR16(\regs)
1766 STREG %r17,PT_GR17(\regs)
1767 STREG %r18,PT_GR18(\regs)
1768 .endm
1769
1770 .macro reg_restore regs
1771 LDREG PT_GR3(\regs), %r3
1772 LDREG PT_GR4(\regs), %r4
1773 LDREG PT_GR5(\regs), %r5
1774 LDREG PT_GR6(\regs), %r6
1775 LDREG PT_GR7(\regs), %r7
1776 LDREG PT_GR8(\regs), %r8
1777 LDREG PT_GR9(\regs), %r9
1778 LDREG PT_GR10(\regs),%r10
1779 LDREG PT_GR11(\regs),%r11
1780 LDREG PT_GR12(\regs),%r12
1781 LDREG PT_GR13(\regs),%r13
1782 LDREG PT_GR14(\regs),%r14
1783 LDREG PT_GR15(\regs),%r15
1784 LDREG PT_GR16(\regs),%r16
1785 LDREG PT_GR17(\regs),%r17
1786 LDREG PT_GR18(\regs),%r18
1787 .endm
1788
1789 .export sys_fork_wrapper
1790 .export child_return
1791sys_fork_wrapper:
1792 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1793 ldo TASK_REGS(%r1),%r1
1794 reg_save %r1
1795 mfctl %cr27, %r3
1796 STREG %r3, PT_CR27(%r1)
1797
1798 STREG %r2,-RP_OFFSET(%r30)
1799 ldo FRAME_SIZE(%r30),%r30
1800#ifdef __LP64__
1801 ldo -16(%r30),%r29 /* Reference param save area */
1802#endif
1803
1804 /* These are call-clobbered registers and therefore
1805 also syscall-clobbered (we hope). */
1806 STREG %r2,PT_GR19(%r1) /* save for child */
1807 STREG %r30,PT_GR21(%r1)
1808
1809 LDREG PT_GR30(%r1),%r25
1810 copy %r1,%r24
1811 BL sys_clone,%r2
1812 ldi SIGCHLD,%r26
1813
1814 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1815wrapper_exit:
1816 ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */
1817 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1818 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1819
1820 LDREG PT_CR27(%r1), %r3
1821 mtctl %r3, %cr27
1822 reg_restore %r1
1823
1824 /* strace expects syscall # to be preserved in r20 */
1825 ldi __NR_fork,%r20
1826 bv %r0(%r2)
1827 STREG %r20,PT_GR20(%r1)
1828
1829 /* Set the return value for the child */
1830child_return:
1831 BL schedule_tail, %r2
1832 nop
1833
1834 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
1835 LDREG TASK_PT_GR19(%r1),%r2
1836 b wrapper_exit
1837 copy %r0,%r28
1838
1839
1840 .export sys_clone_wrapper
1841sys_clone_wrapper:
1842 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1843 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1844 reg_save %r1
1845 mfctl %cr27, %r3
1846 STREG %r3, PT_CR27(%r1)
1847
1848 STREG %r2,-RP_OFFSET(%r30)
1849 ldo FRAME_SIZE(%r30),%r30
1850#ifdef __LP64__
1851 ldo -16(%r30),%r29 /* Reference param save area */
1852#endif
1853
1854 STREG %r2,PT_GR19(%r1) /* save for child */
1855 STREG %r30,PT_GR21(%r1)
1856 BL sys_clone,%r2
1857 copy %r1,%r24
1858
1859 b wrapper_exit
1860 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1861
1862 .export sys_vfork_wrapper
1863sys_vfork_wrapper:
1864 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1865 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1866 reg_save %r1
1867 mfctl %cr27, %r3
1868 STREG %r3, PT_CR27(%r1)
1869
1870 STREG %r2,-RP_OFFSET(%r30)
1871 ldo FRAME_SIZE(%r30),%r30
1872#ifdef __LP64__
1873 ldo -16(%r30),%r29 /* Reference param save area */
1874#endif
1875
1876 STREG %r2,PT_GR19(%r1) /* save for child */
1877 STREG %r30,PT_GR21(%r1)
1878
1879 BL sys_vfork,%r2
1880 copy %r1,%r26
1881
1882 b wrapper_exit
1883 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1884
1885
1886 .macro execve_wrapper execve
1887 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1888 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1889
1890 /*
1891 * Do we need to save/restore r3-r18 here?
1892 * I don't think so. why would new thread need old
1893 * threads registers?
1894 */
1895
1896 /* %arg0 - %arg3 are already saved for us. */
1897
1898 STREG %r2,-RP_OFFSET(%r30)
1899 ldo FRAME_SIZE(%r30),%r30
1900#ifdef __LP64__
1901 ldo -16(%r30),%r29 /* Reference param save area */
1902#endif
1903 bl \execve,%r2
1904 copy %r1,%arg0
1905
1906 ldo -FRAME_SIZE(%r30),%r30
1907 LDREG -RP_OFFSET(%r30),%r2
1908
1909 /* If exec succeeded we need to load the args */
1910
1911 ldo -1024(%r0),%r1
1912 cmpb,>>= %r28,%r1,error_\execve
1913 copy %r2,%r19
1914
1915error_\execve:
1916 bv %r0(%r19)
1917 nop
1918 .endm
1919
1920 .export sys_execve_wrapper
1921 .import sys_execve
1922
1923sys_execve_wrapper:
1924 execve_wrapper sys_execve
1925
1926#ifdef __LP64__
1927 .export sys32_execve_wrapper
1928 .import sys32_execve
1929
1930sys32_execve_wrapper:
1931 execve_wrapper sys32_execve
1932#endif
1933
1934 .export sys_rt_sigreturn_wrapper
1935sys_rt_sigreturn_wrapper:
1936 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
1937 ldo TASK_REGS(%r26),%r26 /* get pt regs */
1938 /* Don't save regs, we are going to restore them from sigcontext. */
1939 STREG %r2, -RP_OFFSET(%r30)
1940#ifdef __LP64__
1941 ldo FRAME_SIZE(%r30), %r30
1942 BL sys_rt_sigreturn,%r2
1943 ldo -16(%r30),%r29 /* Reference param save area */
1944#else
1945 BL sys_rt_sigreturn,%r2
1946 ldo FRAME_SIZE(%r30), %r30
1947#endif
1948
1949 ldo -FRAME_SIZE(%r30), %r30
1950 LDREG -RP_OFFSET(%r30), %r2
1951
1952 /* FIXME: I think we need to restore a few more things here. */
1953 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1954 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1955 reg_restore %r1
1956
1957 /* If the signal was received while the process was blocked on a
1958 * syscall, then r2 will take us to syscall_exit; otherwise r2 will
1959 * take us to syscall_exit_rfi and on to intr_return.
1960 */
1961 bv %r0(%r2)
1962 LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
1963
1964 .export sys_sigaltstack_wrapper
1965sys_sigaltstack_wrapper:
1966 /* Get the user stack pointer */
1967 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1968 ldo TASK_REGS(%r1),%r24 /* get pt regs */
1969 LDREG TASK_PT_GR30(%r24),%r24
1970 STREG %r2, -RP_OFFSET(%r30)
1971#ifdef __LP64__
1972 ldo FRAME_SIZE(%r30), %r30
1973 b,l do_sigaltstack,%r2
1974 ldo -16(%r30),%r29 /* Reference param save area */
1975#else
1976 bl do_sigaltstack,%r2
1977 ldo FRAME_SIZE(%r30), %r30
1978#endif
1979
1980 ldo -FRAME_SIZE(%r30), %r30
1981 LDREG -RP_OFFSET(%r30), %r2
1982 bv %r0(%r2)
1983 nop
1984
1985#ifdef __LP64__
1986 .export sys32_sigaltstack_wrapper
1987sys32_sigaltstack_wrapper:
1988 /* Get the user stack pointer */
1989 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24
1990 LDREG TASK_PT_GR30(%r24),%r24
1991 STREG %r2, -RP_OFFSET(%r30)
1992 ldo FRAME_SIZE(%r30), %r30
1993 b,l do_sigaltstack32,%r2
1994 ldo -16(%r30),%r29 /* Reference param save area */
1995
1996 ldo -FRAME_SIZE(%r30), %r30
1997 LDREG -RP_OFFSET(%r30), %r2
1998 bv %r0(%r2)
1999 nop
2000#endif
2001
2002 .export sys_rt_sigsuspend_wrapper
2003sys_rt_sigsuspend_wrapper:
2004 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
2005 ldo TASK_REGS(%r1),%r24
2006 reg_save %r24
2007
2008 STREG %r2, -RP_OFFSET(%r30)
2009#ifdef __LP64__
2010 ldo FRAME_SIZE(%r30), %r30
2011 b,l sys_rt_sigsuspend,%r2
2012 ldo -16(%r30),%r29 /* Reference param save area */
2013#else
2014 bl sys_rt_sigsuspend,%r2
2015 ldo FRAME_SIZE(%r30), %r30
2016#endif
2017
2018 ldo -FRAME_SIZE(%r30), %r30
2019 LDREG -RP_OFFSET(%r30), %r2
2020
2021 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
2022 ldo TASK_REGS(%r1),%r1
2023 reg_restore %r1
2024
2025 bv %r0(%r2)
2026 nop
2027
2028 .export syscall_exit
2029syscall_exit:
2030
2031 /* NOTE: HP-UX syscalls also come through here
2032 * after hpux_syscall_exit fixes up return
2033 * values. */
2034
2035 /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
2036 * via syscall_exit_rfi if the signal was received while the process
2037 * was running.
2038 */
2039
2040 /* save return value now */
2041
2042 mfctl %cr30, %r1
2043 LDREG TI_TASK(%r1),%r1
2044 STREG %r28,TASK_PT_GR28(%r1)
2045
2046#ifdef CONFIG_HPUX
2047
2048/* <linux/personality.h> cannot be easily included */
2049#define PER_HPUX 0x10
2050 LDREG TASK_PERSONALITY(%r1),%r19
2051
2052 /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
2053 ldo -PER_HPUX(%r19), %r19
2054 CMPIB<>,n 0,%r19,1f
2055
2056 /* Save other hpux returns if personality is PER_HPUX */
2057 STREG %r22,TASK_PT_GR22(%r1)
2058 STREG %r29,TASK_PT_GR29(%r1)
20591:
2060
2061#endif /* CONFIG_HPUX */
2062
2063 /* Seems to me that dp could be wrong here, if the syscall involved
2064 * calling a module, and nothing got round to restoring dp on return.
2065 */
2066 loadgp
2067
2068syscall_check_bh:
2069
2070 /* Check for software interrupts */
2071
2072 .import irq_stat,data
2073
2074 load32 irq_stat,%r19
2075
2076#ifdef CONFIG_SMP
2077 /* sched.h: int processor */
2078 /* %r26 is used as scratch register to index into irq_stat[] */
2079 ldw TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
2080
2081 /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
2082#ifdef __LP64__
2083 shld %r26, 6, %r20
2084#else
2085 shlw %r26, 5, %r20
2086#endif
2087 add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */
2088#endif /* CONFIG_SMP */
2089
2090 LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */
2091 cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */
2092
2093syscall_check_resched:
2094
2095 /* check for reschedule */
2096
2097 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */
2098 bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
2099
2100syscall_check_sig:
2101 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* get ti flags */
2102 bb,<,n %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
2103
2104syscall_restore:
2105 /* Are we being ptraced? */
2106 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2107
2108 LDREG TASK_PTRACE(%r1), %r19
2109 bb,< %r19,31,syscall_restore_rfi
2110 nop
2111
2112 ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */
2113 rest_fp %r19
2114
2115 LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */
2116 mtsar %r19
2117
2118 LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */
2119 LDREG TASK_PT_GR19(%r1),%r19
2120 LDREG TASK_PT_GR20(%r1),%r20
2121 LDREG TASK_PT_GR21(%r1),%r21
2122 LDREG TASK_PT_GR22(%r1),%r22
2123 LDREG TASK_PT_GR23(%r1),%r23
2124 LDREG TASK_PT_GR24(%r1),%r24
2125 LDREG TASK_PT_GR25(%r1),%r25
2126 LDREG TASK_PT_GR26(%r1),%r26
2127 LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */
2128 LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */
2129 LDREG TASK_PT_GR29(%r1),%r29
2130 LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */
2131
2132 /* NOTE: We use rsm/ssm pair to make this operation atomic */
2133 rsm PSW_SM_I, %r0
2134 LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */
2135 mfsp %sr3,%r1 /* Get users space id */
2136 mtsp %r1,%sr7 /* Restore sr7 */
2137 ssm PSW_SM_I, %r0
2138
2139 /* Set sr2 to zero for userspace syscalls to work. */
2140 mtsp %r0,%sr2
2141 mtsp %r1,%sr4 /* Restore sr4 */
2142 mtsp %r1,%sr5 /* Restore sr5 */
2143 mtsp %r1,%sr6 /* Restore sr6 */
2144
2145 depi 3,31,2,%r31 /* ensure return to user mode. */
2146
2147#ifdef __LP64__
2148 /* decide whether to reset the wide mode bit
2149 *
2150 * For a syscall, the W bit is stored in the lowest bit
2151 * of sp. Extract it and reset W if it is zero */
2152 extrd,u,*<> %r30,63,1,%r1
2153 rsm PSW_SM_W, %r0
2154 /* now reset the lowest bit of sp if it was set */
2155 xor %r30,%r1,%r30
2156#endif
2157 be,n 0(%sr3,%r31) /* return to user space */
2158
2159 /* We have to return via an RFI, so that PSW T and R bits can be set
2160 * appropriately.
2161 * This sets up pt_regs so we can return via intr_restore, which is not
2162 * the most efficient way of doing things, but it works.
2163 */
2164syscall_restore_rfi:
2165 ldo -1(%r0),%r2 /* Set recovery cntr to -1 */
2166 mtctl %r2,%cr0 /* for immediate trap */
2167 LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */
2168 ldi 0x0b,%r20 /* Create new PSW */
2169 depi -1,13,1,%r20 /* C, Q, D, and I bits */
2170
2171 /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are
2172 * set in include/linux/ptrace.h and converted to PA bitmap
2173 * numbers in asm-offsets.c */
2174
2175 /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */
2176 extru,= %r19,PA_SINGLESTEP_BIT,1,%r0
2177 depi -1,27,1,%r20 /* R bit */
2178
2179 /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */
2180 extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0
2181 depi -1,7,1,%r20 /* T bit */
2182
2183 STREG %r20,TASK_PT_PSW(%r1)
2184
2185 /* Always store space registers, since sr3 can be changed (e.g. fork) */
2186
2187 mfsp %sr3,%r25
2188 STREG %r25,TASK_PT_SR3(%r1)
2189 STREG %r25,TASK_PT_SR4(%r1)
2190 STREG %r25,TASK_PT_SR5(%r1)
2191 STREG %r25,TASK_PT_SR6(%r1)
2192 STREG %r25,TASK_PT_SR7(%r1)
2193 STREG %r25,TASK_PT_IASQ0(%r1)
2194 STREG %r25,TASK_PT_IASQ1(%r1)
2195
2196 /* XXX W bit??? */
2197 /* Now if old D bit is clear, it means we didn't save all registers
2198 * on syscall entry, so do that now. This only happens on TRACEME
2199 * calls, or if someone attached to us while we were on a syscall.
2200 * We could make this more efficient by not saving r3-r18, but
2201 * then we wouldn't be able to use the common intr_restore path.
2202 * It is only for traced processes anyway, so performance is not
2203 * an issue.
2204 */
2205 bb,< %r2,30,pt_regs_ok /* Branch if D set */
2206 ldo TASK_REGS(%r1),%r25
2207 reg_save %r25 /* Save r3 to r18 */
2208
2209 /* Save the current sr */
2210 mfsp %sr0,%r2
2211 STREG %r2,TASK_PT_SR0(%r1)
2212
2213 /* Save the scratch sr */
2214 mfsp %sr1,%r2
2215 STREG %r2,TASK_PT_SR1(%r1)
2216
2217 /* sr2 should be set to zero for userspace syscalls */
2218 STREG %r0,TASK_PT_SR2(%r1)
2219
2220pt_regs_ok:
2221 LDREG TASK_PT_GR31(%r1),%r2
2222 depi 3,31,2,%r2 /* ensure return to user mode. */
2223 STREG %r2,TASK_PT_IAOQ0(%r1)
2224 ldo 4(%r2),%r2
2225 STREG %r2,TASK_PT_IAOQ1(%r1)
2226 copy %r25,%r16
2227 b intr_restore
2228 nop
2229
2230 .import do_softirq,code
2231syscall_do_softirq:
2232 bl do_softirq,%r2
2233 nop
2234 /* NOTE: We enable I-bit incase we schedule later,
2235 * and we might be going back to userspace if we were
2236 * traced. */
2237 b syscall_check_resched
2238 ssm PSW_SM_I, %r0 /* do_softirq returns with I bit off */
2239
2240 .import schedule,code
2241syscall_do_resched:
2242 BL schedule,%r2
2243#ifdef __LP64__
2244 ldo -16(%r30),%r29 /* Reference param save area */
2245#else
2246 nop
2247#endif
2248 b syscall_check_bh /* if resched, we start over again */
2249 nop
2250
2251 .import do_signal,code
2252syscall_do_signal:
2253 /* Save callee-save registers (for sigcontext).
2254 FIXME: After this point the process structure should be
2255 consistent with all the relevant state of the process
2256 before the syscall. We need to verify this. */
2257 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2258 ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */
2259 reg_save %r25
2260
2261 ldi 1, %r24 /* unsigned long in_syscall */
2262
2263#ifdef __LP64__
2264 ldo -16(%r30),%r29 /* Reference param save area */
2265#endif
2266 BL do_signal,%r2
2267 copy %r0, %r26 /* sigset_t *oldset = NULL */
2268
2269 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2270 ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
2271 reg_restore %r20
2272
2273 b,n syscall_check_sig
2274
2275 /*
2276 * get_register is used by the non access tlb miss handlers to
2277 * copy the value of the general register specified in r8 into
2278 * r1. This routine can't be used for shadowed registers, since
2279 * the rfir will restore the original value. So, for the shadowed
2280 * registers we put a -1 into r1 to indicate that the register
2281 * should not be used (the register being copied could also have
2282 * a -1 in it, but that is OK, it just means that we will have
2283 * to use the slow path instead).
2284 */
2285
2286get_register:
2287 blr %r8,%r0
2288 nop
2289 bv %r0(%r25) /* r0 */
2290 copy %r0,%r1
2291 bv %r0(%r25) /* r1 - shadowed */
2292 ldi -1,%r1
2293 bv %r0(%r25) /* r2 */
2294 copy %r2,%r1
2295 bv %r0(%r25) /* r3 */
2296 copy %r3,%r1
2297 bv %r0(%r25) /* r4 */
2298 copy %r4,%r1
2299 bv %r0(%r25) /* r5 */
2300 copy %r5,%r1
2301 bv %r0(%r25) /* r6 */
2302 copy %r6,%r1
2303 bv %r0(%r25) /* r7 */
2304 copy %r7,%r1
2305 bv %r0(%r25) /* r8 - shadowed */
2306 ldi -1,%r1
2307 bv %r0(%r25) /* r9 - shadowed */
2308 ldi -1,%r1
2309 bv %r0(%r25) /* r10 */
2310 copy %r10,%r1
2311 bv %r0(%r25) /* r11 */
2312 copy %r11,%r1
2313 bv %r0(%r25) /* r12 */
2314 copy %r12,%r1
2315 bv %r0(%r25) /* r13 */
2316 copy %r13,%r1
2317 bv %r0(%r25) /* r14 */
2318 copy %r14,%r1
2319 bv %r0(%r25) /* r15 */
2320 copy %r15,%r1
2321 bv %r0(%r25) /* r16 - shadowed */
2322 ldi -1,%r1
2323 bv %r0(%r25) /* r17 - shadowed */
2324 ldi -1,%r1
2325 bv %r0(%r25) /* r18 */
2326 copy %r18,%r1
2327 bv %r0(%r25) /* r19 */
2328 copy %r19,%r1
2329 bv %r0(%r25) /* r20 */
2330 copy %r20,%r1
2331 bv %r0(%r25) /* r21 */
2332 copy %r21,%r1
2333 bv %r0(%r25) /* r22 */
2334 copy %r22,%r1
2335 bv %r0(%r25) /* r23 */
2336 copy %r23,%r1
2337 bv %r0(%r25) /* r24 - shadowed */
2338 ldi -1,%r1
2339 bv %r0(%r25) /* r25 - shadowed */
2340 ldi -1,%r1
2341 bv %r0(%r25) /* r26 */
2342 copy %r26,%r1
2343 bv %r0(%r25) /* r27 */
2344 copy %r27,%r1
2345 bv %r0(%r25) /* r28 */
2346 copy %r28,%r1
2347 bv %r0(%r25) /* r29 */
2348 copy %r29,%r1
2349 bv %r0(%r25) /* r30 */
2350 copy %r30,%r1
2351 bv %r0(%r25) /* r31 */
2352 copy %r31,%r1
2353
2354 /*
2355 * set_register is used by the non access tlb miss handlers to
2356 * copy the value of r1 into the general register specified in
2357 * r8.
2358 */
2359
2360set_register:
2361 blr %r8,%r0
2362 nop
2363 bv %r0(%r25) /* r0 (silly, but it is a place holder) */
2364 copy %r1,%r0
2365 bv %r0(%r25) /* r1 */
2366 copy %r1,%r1
2367 bv %r0(%r25) /* r2 */
2368 copy %r1,%r2
2369 bv %r0(%r25) /* r3 */
2370 copy %r1,%r3
2371 bv %r0(%r25) /* r4 */
2372 copy %r1,%r4
2373 bv %r0(%r25) /* r5 */
2374 copy %r1,%r5
2375 bv %r0(%r25) /* r6 */
2376 copy %r1,%r6
2377 bv %r0(%r25) /* r7 */
2378 copy %r1,%r7
2379 bv %r0(%r25) /* r8 */
2380 copy %r1,%r8
2381 bv %r0(%r25) /* r9 */
2382 copy %r1,%r9
2383 bv %r0(%r25) /* r10 */
2384 copy %r1,%r10
2385 bv %r0(%r25) /* r11 */
2386 copy %r1,%r11
2387 bv %r0(%r25) /* r12 */
2388 copy %r1,%r12
2389 bv %r0(%r25) /* r13 */
2390 copy %r1,%r13
2391 bv %r0(%r25) /* r14 */
2392 copy %r1,%r14
2393 bv %r0(%r25) /* r15 */
2394 copy %r1,%r15
2395 bv %r0(%r25) /* r16 */
2396 copy %r1,%r16
2397 bv %r0(%r25) /* r17 */
2398 copy %r1,%r17
2399 bv %r0(%r25) /* r18 */
2400 copy %r1,%r18
2401 bv %r0(%r25) /* r19 */
2402 copy %r1,%r19
2403 bv %r0(%r25) /* r20 */
2404 copy %r1,%r20
2405 bv %r0(%r25) /* r21 */
2406 copy %r1,%r21
2407 bv %r0(%r25) /* r22 */
2408 copy %r1,%r22
2409 bv %r0(%r25) /* r23 */
2410 copy %r1,%r23
2411 bv %r0(%r25) /* r24 */
2412 copy %r1,%r24
2413 bv %r0(%r25) /* r25 */
2414 copy %r1,%r25
2415 bv %r0(%r25) /* r26 */
2416 copy %r1,%r26
2417 bv %r0(%r25) /* r27 */
2418 copy %r1,%r27
2419 bv %r0(%r25) /* r28 */
2420 copy %r1,%r28
2421 bv %r0(%r25) /* r29 */
2422 copy %r1,%r29
2423 bv %r0(%r25) /* r30 */
2424 copy %r1,%r30
2425 bv %r0(%r25) /* r31 */
2426 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 @@
1/*
2 * arch/parisc/kernel/firmware.c - safe PDC access routines
3 *
4 * PDC == Processor Dependent Code
5 *
6 * See http://www.parisc-linux.org/documentation/index.html
7 * for documentation describing the entry points and calling
8 * conventions defined below.
9 *
10 * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org)
11 * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
12 * Copyright 2003 Grant Grundler <grundler parisc-linux org>
13 * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org>
14 * Copyright 2004 Thibaut VARENE <varenet@parisc-linux.org>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 */
22
23/* I think it would be in everyone's best interest to follow this
24 * guidelines when writing PDC wrappers:
25 *
26 * - the name of the pdc wrapper should match one of the macros
27 * used for the first two arguments
28 * - don't use caps for random parts of the name
29 * - use the static PDC result buffers and "copyout" to structs
30 * supplied by the caller to encapsulate alignment restrictions
31 * - hold pdc_lock while in PDC or using static result buffers
32 * - use __pa() to convert virtual (kernel) pointers to physical
33 * ones.
34 * - the name of the struct used for pdc return values should equal
35 * one of the macros used for the first two arguments to the
36 * corresponding PDC call
37 * - keep the order of arguments
38 * - don't be smart (setting trailing NUL bytes for strings, return
39 * something useful even if the call failed) unless you are sure
40 * it's not going to affect functionality or performance
41 *
42 * Example:
43 * int pdc_cache_info(struct pdc_cache_info *cache_info )
44 * {
45 * int retval;
46 *
47 * spin_lock_irq(&pdc_lock);
48 * retval = mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
49 * convert_to_wide(pdc_result);
50 * memcpy(cache_info, pdc_result, sizeof(*cache_info));
51 * spin_unlock_irq(&pdc_lock);
52 *
53 * return retval;
54 * }
55 * prumpf 991016
56 */
57
58#include <stdarg.h>
59
60#include <linux/delay.h>
61#include <linux/init.h>
62#include <linux/kernel.h>
63#include <linux/module.h>
64#include <linux/string.h>
65#include <linux/spinlock.h>
66
67#include <asm/page.h>
68#include <asm/pdc.h>
69#include <asm/pdcpat.h>
70#include <asm/system.h>
71#include <asm/processor.h> /* for boot_cpu_data */
72
73static DEFINE_SPINLOCK(pdc_lock);
74static unsigned long pdc_result[32] __attribute__ ((aligned (8)));
75static unsigned long pdc_result2[32] __attribute__ ((aligned (8)));
76
77#ifdef __LP64__
78#define WIDE_FIRMWARE 0x1
79#define NARROW_FIRMWARE 0x2
80
81/* Firmware needs to be initially set to narrow to determine the
82 * actual firmware width. */
83int parisc_narrow_firmware = 1;
84#endif
85
86/* on all currently-supported platforms, IODC I/O calls are always
87 * 32-bit calls, and MEM_PDC calls are always the same width as the OS.
88 * This means Cxxx boxes can't run wide kernels right now. -PB
89 *
90 * CONFIG_PDC_NARROW has been added to allow 64-bit kernels to run on
91 * systems with 32-bit MEM_PDC calls. This will allow wide kernels to
92 * run on Cxxx boxes now. -RB
93 *
94 * Note that some PAT boxes may have 64-bit IODC I/O...
95 */
96
97#ifdef __LP64__
98long real64_call(unsigned long function, ...);
99#endif
100long real32_call(unsigned long function, ...);
101
102#ifdef __LP64__
103# define MEM_PDC (unsigned long)(PAGE0->mem_pdc_hi) << 32 | PAGE0->mem_pdc
104# define mem_pdc_call(args...) unlikely(parisc_narrow_firmware) ? real32_call(MEM_PDC, args) : real64_call(MEM_PDC, args)
105#else
106# define MEM_PDC (unsigned long)PAGE0->mem_pdc
107# define mem_pdc_call(args...) real32_call(MEM_PDC, args)
108#endif
109
110
111/**
112 * f_extend - Convert PDC addresses to kernel addresses.
113 * @address: Address returned from PDC.
114 *
115 * This function is used to convert PDC addresses into kernel addresses
116 * when the PDC address size and kernel address size are different.
117 */
118static unsigned long f_extend(unsigned long address)
119{
120#ifdef __LP64__
121 if(unlikely(parisc_narrow_firmware)) {
122 if((address & 0xff000000) == 0xf0000000)
123 return 0xf0f0f0f000000000UL | (u32)address;
124
125 if((address & 0xf0000000) == 0xf0000000)
126 return 0xffffffff00000000UL | (u32)address;
127 }
128#endif
129 return address;
130}
131
132/**
133 * convert_to_wide - Convert the return buffer addresses into kernel addresses.
134 * @address: The return buffer from PDC.
135 *
136 * This function is used to convert the return buffer addresses retrieved from PDC
137 * into kernel addresses when the PDC address size and kernel address size are
138 * different.
139 */
140static void convert_to_wide(unsigned long *addr)
141{
142#ifdef __LP64__
143 int i;
144 unsigned int *p = (unsigned int *)addr;
145
146 if(unlikely(parisc_narrow_firmware)) {
147 for(i = 31; i >= 0; --i)
148 addr[i] = p[i];
149 }
150#endif
151}
152
153/**
154 * set_firmware_width - Determine if the firmware is wide or narrow.
155 *
156 * This function must be called before any pdc_* function that uses the convert_to_wide
157 * function.
158 */
159void __init set_firmware_width(void)
160{
161#ifdef __LP64__
162 int retval;
163
164 spin_lock_irq(&pdc_lock);
165 retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0);
166 convert_to_wide(pdc_result);
167 if(pdc_result[0] != NARROW_FIRMWARE)
168 parisc_narrow_firmware = 0;
169 spin_unlock_irq(&pdc_lock);
170#endif
171}
172
173/**
174 * pdc_emergency_unlock - Unlock the linux pdc lock
175 *
176 * This call unlocks the linux pdc lock in case we need some PDC functions
177 * (like pdc_add_valid) during kernel stack dump.
178 */
179void pdc_emergency_unlock(void)
180{
181 /* Spinlock DEBUG code freaks out if we unconditionally unlock */
182 if (spin_is_locked(&pdc_lock))
183 spin_unlock(&pdc_lock);
184}
185
186
187/**
188 * pdc_add_valid - Verify address can be accessed without causing a HPMC.
189 * @address: Address to be verified.
190 *
191 * This PDC call attempts to read from the specified address and verifies
192 * if the address is valid.
193 *
194 * The return value is PDC_OK (0) in case accessing this address is valid.
195 */
196int pdc_add_valid(unsigned long address)
197{
198 int retval;
199
200 spin_lock_irq(&pdc_lock);
201 retval = mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, address);
202 spin_unlock_irq(&pdc_lock);
203
204 return retval;
205}
206EXPORT_SYMBOL(pdc_add_valid);
207
208/**
209 * pdc_chassis_info - Return chassis information.
210 * @result: The return buffer.
211 * @chassis_info: The memory buffer address.
212 * @len: The size of the memory buffer address.
213 *
214 * An HVERSION dependent call for returning the chassis information.
215 */
216int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len)
217{
218 int retval;
219
220 spin_lock_irq(&pdc_lock);
221 memcpy(&pdc_result, chassis_info, sizeof(*chassis_info));
222 memcpy(&pdc_result2, led_info, len);
223 retval = mem_pdc_call(PDC_CHASSIS, PDC_RETURN_CHASSIS_INFO,
224 __pa(pdc_result), __pa(pdc_result2), len);
225 memcpy(chassis_info, pdc_result, sizeof(*chassis_info));
226 memcpy(led_info, pdc_result2, len);
227 spin_unlock_irq(&pdc_lock);
228
229 return retval;
230}
231
232/**
233 * pdc_pat_chassis_send_log - Sends a PDC PAT CHASSIS log message.
234 * @retval: -1 on error, 0 on success. Other value are PDC errors
235 *
236 * Must be correctly formatted or expect system crash
237 */
238#ifdef __LP64__
239int pdc_pat_chassis_send_log(unsigned long state, unsigned long data)
240{
241 int retval = 0;
242
243 if (!is_pdc_pat())
244 return -1;
245
246 spin_lock_irq(&pdc_lock);
247 retval = mem_pdc_call(PDC_PAT_CHASSIS_LOG, PDC_PAT_CHASSIS_WRITE_LOG, __pa(&state), __pa(&data));
248 spin_unlock_irq(&pdc_lock);
249
250 return retval;
251}
252#endif
253
254/**
255 * pdc_chassis_disp - Updates display
256 * @retval: -1 on error, 0 on success
257 *
258 * Works on old PDC only (E class, others?)
259 */
260int pdc_chassis_disp(unsigned long disp)
261{
262 int retval = 0;
263
264 spin_lock_irq(&pdc_lock);
265 retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
266 spin_unlock_irq(&pdc_lock);
267
268 return retval;
269}
270
271/**
272 * pdc_coproc_cfg - To identify coprocessors attached to the processor.
273 * @pdc_coproc_info: Return buffer address.
274 *
275 * This PDC call returns the presence and status of all the coprocessors
276 * attached to the processor.
277 */
278int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info)
279{
280 int retval;
281
282 spin_lock_irq(&pdc_lock);
283 retval = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result));
284 convert_to_wide(pdc_result);
285 pdc_coproc_info->ccr_functional = pdc_result[0];
286 pdc_coproc_info->ccr_present = pdc_result[1];
287 pdc_coproc_info->revision = pdc_result[17];
288 pdc_coproc_info->model = pdc_result[18];
289 spin_unlock_irq(&pdc_lock);
290
291 return retval;
292}
293
294/**
295 * pdc_iodc_read - Read data from the modules IODC.
296 * @actcnt: The actual number of bytes.
297 * @hpa: The HPA of the module for the iodc read.
298 * @index: The iodc entry point.
299 * @iodc_data: A buffer memory for the iodc options.
300 * @iodc_data_size: Size of the memory buffer.
301 *
302 * This PDC call reads from the IODC of the module specified by the hpa
303 * argument.
304 */
305int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index,
306 void *iodc_data, unsigned int iodc_data_size)
307{
308 int retval;
309
310 spin_lock_irq(&pdc_lock);
311 retval = mem_pdc_call(PDC_IODC, PDC_IODC_READ, __pa(pdc_result), hpa,
312 index, __pa(pdc_result2), iodc_data_size);
313 convert_to_wide(pdc_result);
314 *actcnt = pdc_result[0];
315 memcpy(iodc_data, pdc_result2, iodc_data_size);
316 spin_unlock_irq(&pdc_lock);
317
318 return retval;
319}
320EXPORT_SYMBOL(pdc_iodc_read);
321
322/**
323 * pdc_system_map_find_mods - Locate unarchitected modules.
324 * @pdc_mod_info: Return buffer address.
325 * @mod_path: pointer to dev path structure.
326 * @mod_index: fixed address module index.
327 *
328 * To locate and identify modules which reside at fixed I/O addresses, which
329 * do not self-identify via architected bus walks.
330 */
331int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
332 struct pdc_module_path *mod_path, long mod_index)
333{
334 int retval;
335
336 spin_lock_irq(&pdc_lock);
337 retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
338 __pa(pdc_result2), mod_index);
339 convert_to_wide(pdc_result);
340 memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info));
341 memcpy(mod_path, pdc_result2, sizeof(*mod_path));
342 spin_unlock_irq(&pdc_lock);
343
344 pdc_mod_info->mod_addr = f_extend(pdc_mod_info->mod_addr);
345 return retval;
346}
347
348/**
349 * pdc_system_map_find_addrs - Retrieve additional address ranges.
350 * @pdc_addr_info: Return buffer address.
351 * @mod_index: Fixed address module index.
352 * @addr_index: Address range index.
353 *
354 * Retrieve additional information about subsequent address ranges for modules
355 * with multiple address ranges.
356 */
357int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info,
358 long mod_index, long addr_index)
359{
360 int retval;
361
362 spin_lock_irq(&pdc_lock);
363 retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_ADDRESS, __pa(pdc_result),
364 mod_index, addr_index);
365 convert_to_wide(pdc_result);
366 memcpy(pdc_addr_info, pdc_result, sizeof(*pdc_addr_info));
367 spin_unlock_irq(&pdc_lock);
368
369 pdc_addr_info->mod_addr = f_extend(pdc_addr_info->mod_addr);
370 return retval;
371}
372
373/**
374 * pdc_model_info - Return model information about the processor.
375 * @model: The return buffer.
376 *
377 * Returns the version numbers, identifiers, and capabilities from the processor module.
378 */
379int pdc_model_info(struct pdc_model *model)
380{
381 int retval;
382
383 spin_lock_irq(&pdc_lock);
384 retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_INFO, __pa(pdc_result), 0);
385 convert_to_wide(pdc_result);
386 memcpy(model, pdc_result, sizeof(*model));
387 spin_unlock_irq(&pdc_lock);
388
389 return retval;
390}
391
392/**
393 * pdc_model_sysmodel - Get the system model name.
394 * @name: A char array of at least 81 characters.
395 *
396 * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L)
397 */
398int pdc_model_sysmodel(char *name)
399{
400 int retval;
401
402 spin_lock_irq(&pdc_lock);
403 retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_SYSMODEL, __pa(pdc_result),
404 OS_ID_HPUX, __pa(name));
405 convert_to_wide(pdc_result);
406
407 if (retval == PDC_OK) {
408 name[pdc_result[0]] = '\0'; /* add trailing '\0' */
409 } else {
410 name[0] = 0;
411 }
412 spin_unlock_irq(&pdc_lock);
413
414 return retval;
415}
416
417/**
418 * pdc_model_versions - Identify the version number of each processor.
419 * @cpu_id: The return buffer.
420 * @id: The id of the processor to check.
421 *
422 * Returns the version number for each processor component.
423 *
424 * This comment was here before, but I do not know what it means :( -RB
425 * id: 0 = cpu revision, 1 = boot-rom-version
426 */
427int pdc_model_versions(unsigned long *versions, int id)
428{
429 int retval;
430
431 spin_lock_irq(&pdc_lock);
432 retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_VERSIONS, __pa(pdc_result), id);
433 convert_to_wide(pdc_result);
434 *versions = pdc_result[0];
435 spin_unlock_irq(&pdc_lock);
436
437 return retval;
438}
439
440/**
441 * pdc_model_cpuid - Returns the CPU_ID.
442 * @cpu_id: The return buffer.
443 *
444 * Returns the CPU_ID value which uniquely identifies the cpu portion of
445 * the processor module.
446 */
447int pdc_model_cpuid(unsigned long *cpu_id)
448{
449 int retval;
450
451 spin_lock_irq(&pdc_lock);
452 pdc_result[0] = 0; /* preset zero (call may not be implemented!) */
453 retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CPU_ID, __pa(pdc_result), 0);
454 convert_to_wide(pdc_result);
455 *cpu_id = pdc_result[0];
456 spin_unlock_irq(&pdc_lock);
457
458 return retval;
459}
460
461/**
462 * pdc_model_capabilities - Returns the platform capabilities.
463 * @capabilities: The return buffer.
464 *
465 * Returns information about platform support for 32- and/or 64-bit
466 * OSes, IO-PDIR coherency, and virtual aliasing.
467 */
468int pdc_model_capabilities(unsigned long *capabilities)
469{
470 int retval;
471
472 spin_lock_irq(&pdc_lock);
473 pdc_result[0] = 0; /* preset zero (call may not be implemented!) */
474 retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0);
475 convert_to_wide(pdc_result);
476 *capabilities = pdc_result[0];
477 spin_unlock_irq(&pdc_lock);
478
479 return retval;
480}
481
482/**
483 * pdc_cache_info - Return cache and TLB information.
484 * @cache_info: The return buffer.
485 *
486 * Returns information about the processor's cache and TLB.
487 */
488int pdc_cache_info(struct pdc_cache_info *cache_info)
489{
490 int retval;
491
492 spin_lock_irq(&pdc_lock);
493 retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_INFO, __pa(pdc_result), 0);
494 convert_to_wide(pdc_result);
495 memcpy(cache_info, pdc_result, sizeof(*cache_info));
496 spin_unlock_irq(&pdc_lock);
497
498 return retval;
499}
500
501#ifndef CONFIG_PA20
502/**
503 * pdc_btlb_info - Return block TLB information.
504 * @btlb: The return buffer.
505 *
506 * Returns information about the hardware Block TLB.
507 */
508int pdc_btlb_info(struct pdc_btlb_info *btlb)
509{
510 int retval;
511
512 spin_lock_irq(&pdc_lock);
513 retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0);
514 memcpy(btlb, pdc_result, sizeof(*btlb));
515 spin_unlock_irq(&pdc_lock);
516
517 if(retval < 0) {
518 btlb->max_size = 0;
519 }
520 return retval;
521}
522
523/**
524 * pdc_mem_map_hpa - Find fixed module information.
525 * @address: The return buffer
526 * @mod_path: pointer to dev path structure.
527 *
528 * This call was developed for S700 workstations to allow the kernel to find
529 * the I/O devices (Core I/O). In the future (Kittyhawk and beyond) this
530 * call will be replaced (on workstations) by the architected PDC_SYSTEM_MAP
531 * call.
532 *
533 * This call is supported by all existing S700 workstations (up to Gecko).
534 */
535int pdc_mem_map_hpa(struct pdc_memory_map *address,
536 struct pdc_module_path *mod_path)
537{
538 int retval;
539
540 spin_lock_irq(&pdc_lock);
541 memcpy(pdc_result2, mod_path, sizeof(*mod_path));
542 retval = mem_pdc_call(PDC_MEM_MAP, PDC_MEM_MAP_HPA, __pa(pdc_result),
543 __pa(pdc_result2));
544 memcpy(address, pdc_result, sizeof(*address));
545 spin_unlock_irq(&pdc_lock);
546
547 return retval;
548}
549#endif /* !CONFIG_PA20 */
550
551/**
552 * pdc_lan_station_id - Get the LAN address.
553 * @lan_addr: The return buffer.
554 * @hpa: The network device HPA.
555 *
556 * Get the LAN station address when it is not directly available from the LAN hardware.
557 */
558int pdc_lan_station_id(char *lan_addr, unsigned long hpa)
559{
560 int retval;
561
562 spin_lock_irq(&pdc_lock);
563 retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
564 __pa(pdc_result), hpa);
565 if (retval < 0) {
566 /* FIXME: else read MAC from NVRAM */
567 memset(lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
568 } else {
569 memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE);
570 }
571 spin_unlock_irq(&pdc_lock);
572
573 return retval;
574}
575EXPORT_SYMBOL(pdc_lan_station_id);
576
577/**
578 * pdc_stable_read - Read data from Stable Storage.
579 * @staddr: Stable Storage address to access.
580 * @memaddr: The memory address where Stable Storage data shall be copied.
581 * @count: number of bytes to transfert. count is multiple of 4.
582 *
583 * This PDC call reads from the Stable Storage address supplied in staddr
584 * and copies count bytes to the memory address memaddr.
585 * The call will fail if staddr+count > PDC_STABLE size.
586 */
587int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count)
588{
589 int retval;
590
591 spin_lock_irq(&pdc_lock);
592 retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_READ, staddr,
593 __pa(pdc_result), count);
594 convert_to_wide(pdc_result);
595 memcpy(memaddr, pdc_result, count);
596 spin_unlock_irq(&pdc_lock);
597
598 return retval;
599}
600EXPORT_SYMBOL(pdc_stable_read);
601
602/**
603 * pdc_stable_write - Write data to Stable Storage.
604 * @staddr: Stable Storage address to access.
605 * @memaddr: The memory address where Stable Storage data shall be read from.
606 * @count: number of bytes to transfert. count is multiple of 4.
607 *
608 * This PDC call reads count bytes from the supplied memaddr address,
609 * and copies count bytes to the Stable Storage address staddr.
610 * The call will fail if staddr+count > PDC_STABLE size.
611 */
612int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count)
613{
614 int retval;
615
616 spin_lock_irq(&pdc_lock);
617 memcpy(pdc_result, memaddr, count);
618 convert_to_wide(pdc_result);
619 retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_WRITE, staddr,
620 __pa(pdc_result), count);
621 spin_unlock_irq(&pdc_lock);
622
623 return retval;
624}
625EXPORT_SYMBOL(pdc_stable_write);
626
627/**
628 * pdc_stable_get_size - Get Stable Storage size in bytes.
629 * @size: pointer where the size will be stored.
630 *
631 * This PDC call returns the number of bytes in the processor's Stable
632 * Storage, which is the number of contiguous bytes implemented in Stable
633 * Storage starting from staddr=0. size in an unsigned 64-bit integer
634 * which is a multiple of four.
635 */
636int pdc_stable_get_size(unsigned long *size)
637{
638 int retval;
639
640 spin_lock_irq(&pdc_lock);
641 retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_RETURN_SIZE, __pa(pdc_result));
642 *size = pdc_result[0];
643 spin_unlock_irq(&pdc_lock);
644
645 return retval;
646}
647EXPORT_SYMBOL(pdc_stable_get_size);
648
649/**
650 * pdc_stable_verify_contents - Checks that Stable Storage contents are valid.
651 *
652 * This PDC call is meant to be used to check the integrity of the current
653 * contents of Stable Storage.
654 */
655int pdc_stable_verify_contents(void)
656{
657 int retval;
658
659 spin_lock_irq(&pdc_lock);
660 retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_VERIFY_CONTENTS);
661 spin_unlock_irq(&pdc_lock);
662
663 return retval;
664}
665EXPORT_SYMBOL(pdc_stable_verify_contents);
666
667/**
668 * pdc_stable_initialize - Sets Stable Storage contents to zero and initialize
669 * the validity indicator.
670 *
671 * This PDC call will erase all contents of Stable Storage. Use with care!
672 */
673int pdc_stable_initialize(void)
674{
675 int retval;
676
677 spin_lock_irq(&pdc_lock);
678 retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_INITIALIZE);
679 spin_unlock_irq(&pdc_lock);
680
681 return retval;
682}
683EXPORT_SYMBOL(pdc_stable_initialize);
684
685/**
686 * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD)
687 * @hwpath: fully bc.mod style path to the device.
688 * @initiator: the array to return the result into
689 *
690 * Get the SCSI operational parameters from PDC.
691 * Needed since HPUX never used BIOS or symbios card NVRAM.
692 * Most ncr/sym cards won't have an entry and just use whatever
693 * capabilities of the card are (eg Ultra, LVD). But there are
694 * several cases where it's useful:
695 * o set SCSI id for Multi-initiator clusters,
696 * o cable too long (ie SE scsi 10Mhz won't support 6m length),
697 * o bus width exported is less than what the interface chip supports.
698 */
699int pdc_get_initiator(struct hardware_path *hwpath, struct pdc_initiator *initiator)
700{
701 int retval;
702
703 spin_lock_irq(&pdc_lock);
704
705/* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */
706#define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \
707 strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 8) == 0)
708
709 retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR,
710 __pa(pdc_result), __pa(hwpath));
711 if (retval < PDC_OK)
712 goto out;
713
714 if (pdc_result[0] < 16) {
715 initiator->host_id = pdc_result[0];
716 } else {
717 initiator->host_id = -1;
718 }
719
720 /*
721 * Sprockets and Piranha return 20 or 40 (MT/s). Prelude returns
722 * 1, 2, 5 or 10 for 5, 10, 20 or 40 MT/s, respectively
723 */
724 switch (pdc_result[1]) {
725 case 1: initiator->factor = 50; break;
726 case 2: initiator->factor = 25; break;
727 case 5: initiator->factor = 12; break;
728 case 25: initiator->factor = 10; break;
729 case 20: initiator->factor = 12; break;
730 case 40: initiator->factor = 10; break;
731 default: initiator->factor = -1; break;
732 }
733
734 if (IS_SPROCKETS()) {
735 initiator->width = pdc_result[4];
736 initiator->mode = pdc_result[5];
737 } else {
738 initiator->width = -1;
739 initiator->mode = -1;
740 }
741
742 out:
743 spin_unlock_irq(&pdc_lock);
744 return (retval >= PDC_OK);
745}
746EXPORT_SYMBOL(pdc_get_initiator);
747
748
749/**
750 * pdc_pci_irt_size - Get the number of entries in the interrupt routing table.
751 * @num_entries: The return value.
752 * @hpa: The HPA for the device.
753 *
754 * This PDC function returns the number of entries in the specified cell's
755 * interrupt table.
756 * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes
757 */
758int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa)
759{
760 int retval;
761
762 spin_lock_irq(&pdc_lock);
763 retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE,
764 __pa(pdc_result), hpa);
765 convert_to_wide(pdc_result);
766 *num_entries = pdc_result[0];
767 spin_unlock_irq(&pdc_lock);
768
769 return retval;
770}
771
772/**
773 * pdc_pci_irt - Get the PCI interrupt routing table.
774 * @num_entries: The number of entries in the table.
775 * @hpa: The Hard Physical Address of the device.
776 * @tbl:
777 *
778 * Get the PCI interrupt routing table for the device at the given HPA.
779 * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes
780 */
781int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl)
782{
783 int retval;
784
785 BUG_ON((unsigned long)tbl & 0x7);
786
787 spin_lock_irq(&pdc_lock);
788 pdc_result[0] = num_entries;
789 retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
790 __pa(pdc_result), hpa, __pa(tbl));
791 spin_unlock_irq(&pdc_lock);
792
793 return retval;
794}
795
796
797#if 0 /* UNTEST CODE - left here in case someone needs it */
798
799/**
800 * pdc_pci_config_read - read PCI config space.
801 * @hpa token from PDC to indicate which PCI device
802 * @pci_addr configuration space address to read from
803 *
804 * Read PCI Configuration space *before* linux PCI subsystem is running.
805 */
806unsigned int pdc_pci_config_read(void *hpa, unsigned long cfg_addr)
807{
808 int retval;
809 spin_lock_irq(&pdc_lock);
810 pdc_result[0] = 0;
811 pdc_result[1] = 0;
812 retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_READ_CONFIG,
813 __pa(pdc_result), hpa, cfg_addr&~3UL, 4UL);
814 spin_unlock_irq(&pdc_lock);
815 return retval ? ~0 : (unsigned int) pdc_result[0];
816}
817
818
819/**
820 * pdc_pci_config_write - read PCI config space.
821 * @hpa token from PDC to indicate which PCI device
822 * @pci_addr configuration space address to write
823 * @val value we want in the 32-bit register
824 *
825 * Write PCI Configuration space *before* linux PCI subsystem is running.
826 */
827void pdc_pci_config_write(void *hpa, unsigned long cfg_addr, unsigned int val)
828{
829 int retval;
830 spin_lock_irq(&pdc_lock);
831 pdc_result[0] = 0;
832 retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_WRITE_CONFIG,
833 __pa(pdc_result), hpa,
834 cfg_addr&~3UL, 4UL, (unsigned long) val);
835 spin_unlock_irq(&pdc_lock);
836 return retval;
837}
838#endif /* UNTESTED CODE */
839
840/**
841 * pdc_tod_read - Read the Time-Of-Day clock.
842 * @tod: The return buffer:
843 *
844 * Read the Time-Of-Day clock
845 */
846int pdc_tod_read(struct pdc_tod *tod)
847{
848 int retval;
849
850 spin_lock_irq(&pdc_lock);
851 retval = mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(pdc_result), 0);
852 convert_to_wide(pdc_result);
853 memcpy(tod, pdc_result, sizeof(*tod));
854 spin_unlock_irq(&pdc_lock);
855
856 return retval;
857}
858EXPORT_SYMBOL(pdc_tod_read);
859
860/**
861 * pdc_tod_set - Set the Time-Of-Day clock.
862 * @sec: The number of seconds since epoch.
863 * @usec: The number of micro seconds.
864 *
865 * Set the Time-Of-Day clock.
866 */
867int pdc_tod_set(unsigned long sec, unsigned long usec)
868{
869 int retval;
870
871 spin_lock_irq(&pdc_lock);
872 retval = mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
873 spin_unlock_irq(&pdc_lock);
874
875 return retval;
876}
877EXPORT_SYMBOL(pdc_tod_set);
878
879#ifdef __LP64__
880int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
881 struct pdc_memory_table *tbl, unsigned long entries)
882{
883 int retval;
884
885 spin_lock_irq(&pdc_lock);
886 retval = mem_pdc_call(PDC_MEM, PDC_MEM_TABLE, __pa(pdc_result), __pa(pdc_result2), entries);
887 convert_to_wide(pdc_result);
888 memcpy(r_addr, pdc_result, sizeof(*r_addr));
889 memcpy(tbl, pdc_result2, entries * sizeof(*tbl));
890 spin_unlock_irq(&pdc_lock);
891
892 return retval;
893}
894#endif /* __LP64__ */
895
896/* FIXME: Is this pdc used? I could not find type reference to ftc_bitmap
897 * so I guessed at unsigned long. Someone who knows what this does, can fix
898 * it later. :)
899 */
900int pdc_do_firm_test_reset(unsigned long ftc_bitmap)
901{
902 int retval;
903
904 spin_lock_irq(&pdc_lock);
905 retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_FIRM_TEST_RESET,
906 PDC_FIRM_TEST_MAGIC, ftc_bitmap);
907 spin_unlock_irq(&pdc_lock);
908
909 return retval;
910}
911
912/*
913 * pdc_do_reset - Reset the system.
914 *
915 * Reset the system.
916 */
917int pdc_do_reset(void)
918{
919 int retval;
920
921 spin_lock_irq(&pdc_lock);
922 retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET);
923 spin_unlock_irq(&pdc_lock);
924
925 return retval;
926}
927
928/*
929 * pdc_soft_power_info - Enable soft power switch.
930 * @power_reg: address of soft power register
931 *
932 * Return the absolute address of the soft power switch register
933 */
934int __init pdc_soft_power_info(unsigned long *power_reg)
935{
936 int retval;
937
938 *power_reg = (unsigned long) (-1);
939
940 spin_lock_irq(&pdc_lock);
941 retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0);
942 if (retval == PDC_OK) {
943 convert_to_wide(pdc_result);
944 *power_reg = f_extend(pdc_result[0]);
945 }
946 spin_unlock_irq(&pdc_lock);
947
948 return retval;
949}
950
951/*
952 * pdc_soft_power_button - Control the soft power button behaviour
953 * @sw_control: 0 for hardware control, 1 for software control
954 *
955 *
956 * This PDC function places the soft power button under software or
957 * hardware control.
958 * Under software control the OS may control to when to allow to shut
959 * down the system. Under hardware control pressing the power button
960 * powers off the system immediately.
961 */
962int pdc_soft_power_button(int sw_control)
963{
964 int retval;
965 spin_lock_irq(&pdc_lock);
966 retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control);
967 spin_unlock_irq(&pdc_lock);
968 return retval;
969}
970
971/*
972 * pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices.
973 * Primarily a problem on T600 (which parisc-linux doesn't support) but
974 * who knows what other platform firmware might do with this OS "hook".
975 */
976void pdc_io_reset(void)
977{
978 spin_lock_irq(&pdc_lock);
979 mem_pdc_call(PDC_IO, PDC_IO_RESET, 0);
980 spin_unlock_irq(&pdc_lock);
981}
982
983/*
984 * pdc_io_reset_devices - Hack to Stop USB controller
985 *
986 * If PDC used the usb controller, the usb controller
987 * is still running and will crash the machines during iommu
988 * setup, because of still running DMA. This PDC call
989 * stops the USB controller.
990 * Normally called after calling pdc_io_reset().
991 */
992void pdc_io_reset_devices(void)
993{
994 spin_lock_irq(&pdc_lock);
995 mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0);
996 spin_unlock_irq(&pdc_lock);
997}
998
999
1000/**
1001 * pdc_iodc_putc - Console character print using IODC.
1002 * @c: the character to output.
1003 *
1004 * Note that only these special chars are architected for console IODC io:
1005 * BEL, BS, CR, and LF. Others are passed through.
1006 * Since the HP console requires CR+LF to perform a 'newline', we translate
1007 * "\n" to "\r\n".
1008 */
1009void pdc_iodc_putc(unsigned char c)
1010{
1011 /* XXX Should we spinlock posx usage */
1012 static int posx; /* for simple TAB-Simulation... */
1013 static int __attribute__((aligned(8))) iodc_retbuf[32];
1014 static char __attribute__((aligned(64))) iodc_dbuf[4096];
1015 unsigned int n;
1016 unsigned int flags;
1017
1018 switch (c) {
1019 case '\n':
1020 iodc_dbuf[0] = '\r';
1021 iodc_dbuf[1] = '\n';
1022 n = 2;
1023 posx = 0;
1024 break;
1025 case '\t':
1026 pdc_iodc_putc(' ');
1027 while (posx & 7) /* expand TAB */
1028 pdc_iodc_putc(' ');
1029 return; /* return since IODC can't handle this */
1030 case '\b':
1031 posx-=2; /* BS */
1032 default:
1033 iodc_dbuf[0] = c;
1034 n = 1;
1035 posx++;
1036 break;
1037 }
1038
1039 spin_lock_irqsave(&pdc_lock, flags);
1040 real32_call(PAGE0->mem_cons.iodc_io,
1041 (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
1042 PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
1043 __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
1044 spin_unlock_irqrestore(&pdc_lock, flags);
1045}
1046
1047/**
1048 * pdc_iodc_outc - Console character print using IODC (without conversions).
1049 * @c: the character to output.
1050 *
1051 * Write the character directly to the IODC console.
1052 */
1053void pdc_iodc_outc(unsigned char c)
1054{
1055 unsigned int n, flags;
1056
1057 /* fill buffer with one caracter and print it */
1058 static int __attribute__((aligned(8))) iodc_retbuf[32];
1059 static char __attribute__((aligned(64))) iodc_dbuf[4096];
1060
1061 n = 1;
1062 iodc_dbuf[0] = c;
1063
1064 spin_lock_irqsave(&pdc_lock, flags);
1065 real32_call(PAGE0->mem_cons.iodc_io,
1066 (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
1067 PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
1068 __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
1069 spin_unlock_irqrestore(&pdc_lock, flags);
1070}
1071
1072/**
1073 * pdc_iodc_getc - Read a character (non-blocking) from the PDC console.
1074 *
1075 * Read a character (non-blocking) from the PDC console, returns -1 if
1076 * key is not present.
1077 */
1078int pdc_iodc_getc(void)
1079{
1080 unsigned int flags;
1081 static int __attribute__((aligned(8))) iodc_retbuf[32];
1082 static char __attribute__((aligned(64))) iodc_dbuf[4096];
1083 int ch;
1084 int status;
1085
1086 /* Bail if no console input device. */
1087 if (!PAGE0->mem_kbd.iodc_io)
1088 return 0;
1089
1090 /* wait for a keyboard (rs232)-input */
1091 spin_lock_irqsave(&pdc_lock, flags);
1092 real32_call(PAGE0->mem_kbd.iodc_io,
1093 (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
1094 PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
1095 __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
1096
1097 ch = *iodc_dbuf;
1098 status = *iodc_retbuf;
1099 spin_unlock_irqrestore(&pdc_lock, flags);
1100
1101 if (status == 0)
1102 return -1;
1103
1104 return ch;
1105}
1106
1107int pdc_sti_call(unsigned long func, unsigned long flags,
1108 unsigned long inptr, unsigned long outputr,
1109 unsigned long glob_cfg)
1110{
1111 int retval;
1112
1113 spin_lock_irq(&pdc_lock);
1114 retval = real32_call(func, flags, inptr, outputr, glob_cfg);
1115 spin_unlock_irq(&pdc_lock);
1116
1117 return retval;
1118}
1119EXPORT_SYMBOL(pdc_sti_call);
1120
1121#ifdef __LP64__
1122/**
1123 * pdc_pat_cell_get_number - Returns the cell number.
1124 * @cell_info: The return buffer.
1125 *
1126 * This PDC call returns the cell number of the cell from which the call
1127 * is made.
1128 */
1129int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info)
1130{
1131 int retval;
1132
1133 spin_lock_irq(&pdc_lock);
1134 retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_NUMBER, __pa(pdc_result));
1135 memcpy(cell_info, pdc_result, sizeof(*cell_info));
1136 spin_unlock_irq(&pdc_lock);
1137
1138 return retval;
1139}
1140
1141/**
1142 * pdc_pat_cell_module - Retrieve the cell's module information.
1143 * @actcnt: The number of bytes written to mem_addr.
1144 * @ploc: The physical location.
1145 * @mod: The module index.
1146 * @view_type: The view of the address type.
1147 * @mem_addr: The return buffer.
1148 *
1149 * This PDC call returns information about each module attached to the cell
1150 * at the specified location.
1151 */
1152int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod,
1153 unsigned long view_type, void *mem_addr)
1154{
1155 int retval;
1156 static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8)));
1157
1158 spin_lock_irq(&pdc_lock);
1159 retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result),
1160 ploc, mod, view_type, __pa(&result));
1161 if(!retval) {
1162 *actcnt = pdc_result[0];
1163 memcpy(mem_addr, &result, *actcnt);
1164 }
1165 spin_unlock_irq(&pdc_lock);
1166
1167 return retval;
1168}
1169
1170/**
1171 * pdc_pat_cpu_get_number - Retrieve the cpu number.
1172 * @cpu_info: The return buffer.
1173 * @hpa: The Hard Physical Address of the CPU.
1174 *
1175 * Retrieve the cpu number for the cpu at the specified HPA.
1176 */
1177int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa)
1178{
1179 int retval;
1180
1181 spin_lock_irq(&pdc_lock);
1182 retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER,
1183 __pa(&pdc_result), hpa);
1184 memcpy(cpu_info, pdc_result, sizeof(*cpu_info));
1185 spin_unlock_irq(&pdc_lock);
1186
1187 return retval;
1188}
1189
1190/**
1191 * pdc_pat_get_irt_size - Retrieve the number of entries in the cell's interrupt table.
1192 * @num_entries: The return value.
1193 * @cell_num: The target cell.
1194 *
1195 * This PDC function returns the number of entries in the specified cell's
1196 * interrupt table.
1197 */
1198int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num)
1199{
1200 int retval;
1201
1202 spin_lock_irq(&pdc_lock);
1203 retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE,
1204 __pa(pdc_result), cell_num);
1205 *num_entries = pdc_result[0];
1206 spin_unlock_irq(&pdc_lock);
1207
1208 return retval;
1209}
1210
1211/**
1212 * pdc_pat_get_irt - Retrieve the cell's interrupt table.
1213 * @r_addr: The return buffer.
1214 * @cell_num: The target cell.
1215 *
1216 * This PDC function returns the actual interrupt table for the specified cell.
1217 */
1218int pdc_pat_get_irt(void *r_addr, unsigned long cell_num)
1219{
1220 int retval;
1221
1222 spin_lock_irq(&pdc_lock);
1223 retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE,
1224 __pa(r_addr), cell_num);
1225 spin_unlock_irq(&pdc_lock);
1226
1227 return retval;
1228}
1229
1230/**
1231 * pdc_pat_pd_get_addr_map - Retrieve information about memory address ranges.
1232 * @actlen: The return buffer.
1233 * @mem_addr: Pointer to the memory buffer.
1234 * @count: The number of bytes to read from the buffer.
1235 * @offset: The offset with respect to the beginning of the buffer.
1236 *
1237 */
1238int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr,
1239 unsigned long count, unsigned long offset)
1240{
1241 int retval;
1242
1243 spin_lock_irq(&pdc_lock);
1244 retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_ADDR_MAP, __pa(pdc_result),
1245 __pa(pdc_result2), count, offset);
1246 *actual_len = pdc_result[0];
1247 memcpy(mem_addr, pdc_result2, *actual_len);
1248 spin_unlock_irq(&pdc_lock);
1249
1250 return retval;
1251}
1252
1253/**
1254 * pdc_pat_io_pci_cfg_read - Read PCI configuration space.
1255 * @pci_addr: PCI configuration space address for which the read request is being made.
1256 * @pci_size: Size of read in bytes. Valid values are 1, 2, and 4.
1257 * @mem_addr: Pointer to return memory buffer.
1258 *
1259 */
1260int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr)
1261{
1262 int retval;
1263 spin_lock_irq(&pdc_lock);
1264 retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ,
1265 __pa(pdc_result), pci_addr, pci_size);
1266 switch(pci_size) {
1267 case 1: *(u8 *) mem_addr = (u8) pdc_result[0];
1268 case 2: *(u16 *)mem_addr = (u16) pdc_result[0];
1269 case 4: *(u32 *)mem_addr = (u32) pdc_result[0];
1270 }
1271 spin_unlock_irq(&pdc_lock);
1272
1273 return retval;
1274}
1275
1276/**
1277 * pdc_pat_io_pci_cfg_write - Retrieve information about memory address ranges.
1278 * @pci_addr: PCI configuration space address for which the write request is being made.
1279 * @pci_size: Size of write in bytes. Valid values are 1, 2, and 4.
1280 * @value: Pointer to 1, 2, or 4 byte value in low order end of argument to be
1281 * written to PCI Config space.
1282 *
1283 */
1284int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val)
1285{
1286 int retval;
1287
1288 spin_lock_irq(&pdc_lock);
1289 retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_WRITE,
1290 pci_addr, pci_size, val);
1291 spin_unlock_irq(&pdc_lock);
1292
1293 return retval;
1294}
1295#endif /* __LP64__ */
1296
1297
1298/***************** 32-bit real-mode calls ***********/
1299/* The struct below is used
1300 * to overlay real_stack (real2.S), preparing a 32-bit call frame.
1301 * real32_call_asm() then uses this stack in narrow real mode
1302 */
1303
1304struct narrow_stack {
1305 /* use int, not long which is 64 bits */
1306 unsigned int arg13;
1307 unsigned int arg12;
1308 unsigned int arg11;
1309 unsigned int arg10;
1310 unsigned int arg9;
1311 unsigned int arg8;
1312 unsigned int arg7;
1313 unsigned int arg6;
1314 unsigned int arg5;
1315 unsigned int arg4;
1316 unsigned int arg3;
1317 unsigned int arg2;
1318 unsigned int arg1;
1319 unsigned int arg0;
1320 unsigned int frame_marker[8];
1321 unsigned int sp;
1322 /* in reality, there's nearly 8k of stack after this */
1323};
1324
1325long real32_call(unsigned long fn, ...)
1326{
1327 va_list args;
1328 extern struct narrow_stack real_stack;
1329 extern unsigned long real32_call_asm(unsigned int *,
1330 unsigned int *,
1331 unsigned int);
1332
1333 va_start(args, fn);
1334 real_stack.arg0 = va_arg(args, unsigned int);
1335 real_stack.arg1 = va_arg(args, unsigned int);
1336 real_stack.arg2 = va_arg(args, unsigned int);
1337 real_stack.arg3 = va_arg(args, unsigned int);
1338 real_stack.arg4 = va_arg(args, unsigned int);
1339 real_stack.arg5 = va_arg(args, unsigned int);
1340 real_stack.arg6 = va_arg(args, unsigned int);
1341 real_stack.arg7 = va_arg(args, unsigned int);
1342 real_stack.arg8 = va_arg(args, unsigned int);
1343 real_stack.arg9 = va_arg(args, unsigned int);
1344 real_stack.arg10 = va_arg(args, unsigned int);
1345 real_stack.arg11 = va_arg(args, unsigned int);
1346 real_stack.arg12 = va_arg(args, unsigned int);
1347 real_stack.arg13 = va_arg(args, unsigned int);
1348 va_end(args);
1349
1350 return real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
1351}
1352
1353#ifdef __LP64__
1354/***************** 64-bit real-mode calls ***********/
1355
1356struct wide_stack {
1357 unsigned long arg0;
1358 unsigned long arg1;
1359 unsigned long arg2;
1360 unsigned long arg3;
1361 unsigned long arg4;
1362 unsigned long arg5;
1363 unsigned long arg6;
1364 unsigned long arg7;
1365 unsigned long arg8;
1366 unsigned long arg9;
1367 unsigned long arg10;
1368 unsigned long arg11;
1369 unsigned long arg12;
1370 unsigned long arg13;
1371 unsigned long frame_marker[2]; /* rp, previous sp */
1372 unsigned long sp;
1373 /* in reality, there's nearly 8k of stack after this */
1374};
1375
1376long real64_call(unsigned long fn, ...)
1377{
1378 va_list args;
1379 extern struct wide_stack real64_stack;
1380 extern unsigned long real64_call_asm(unsigned long *,
1381 unsigned long *,
1382 unsigned long);
1383
1384 va_start(args, fn);
1385 real64_stack.arg0 = va_arg(args, unsigned long);
1386 real64_stack.arg1 = va_arg(args, unsigned long);
1387 real64_stack.arg2 = va_arg(args, unsigned long);
1388 real64_stack.arg3 = va_arg(args, unsigned long);
1389 real64_stack.arg4 = va_arg(args, unsigned long);
1390 real64_stack.arg5 = va_arg(args, unsigned long);
1391 real64_stack.arg6 = va_arg(args, unsigned long);
1392 real64_stack.arg7 = va_arg(args, unsigned long);
1393 real64_stack.arg8 = va_arg(args, unsigned long);
1394 real64_stack.arg9 = va_arg(args, unsigned long);
1395 real64_stack.arg10 = va_arg(args, unsigned long);
1396 real64_stack.arg11 = va_arg(args, unsigned long);
1397 real64_stack.arg12 = va_arg(args, unsigned long);
1398 real64_stack.arg13 = va_arg(args, unsigned long);
1399 va_end(args);
1400
1401 return real64_call_asm(&real64_stack.sp, &real64_stack.arg0, fn);
1402}
1403
1404#endif /* __LP64__ */
1405
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 @@
1/*
2 * Hardware descriptions for HP 9000 based hardware, including
3 * system types, SCSI controllers, DMA controllers, HPPB controllers
4 * and lots more.
5 *
6 * Based on the document "PA-RISC 1.1 I/O Firmware Architecture
7 * Reference Specification", March 7, 1999, version 0.96. This
8 * is available at http://parisc-linux.org/documentation/
9 *
10 * Copyright 1999 by Alex deVries <alex@onefishtwo.ca>
11 * and copyright 1999 The Puffin Group Inc.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 */
28
29
30#include <asm/hardware.h>
31#include <linux/stddef.h>
32#include <linux/kernel.h>
33#include <linux/init.h>
34
35/*
36 * HP PARISC Hardware Database
37 * Access to this database is only possible during bootup
38 * so don't reference this table after starting the init process
39 */
40
41static struct hp_hardware hp_hardware_list[] __initdata = {
42 {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
43 {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
44 {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
45 {HPHW_NPROC,0xB,0x4,0x01,"Technical Shogun (845, 645)"},
46 {HPHW_NPROC,0xF,0x4,0x01,"Commercial Shogun (949)"},
47 {HPHW_NPROC,0xC,0x4,0x01,"Cheetah (850, 950)"},
48 {HPHW_NPROC,0x80,0x4,0x01,"Cheetah (950S)"},
49 {HPHW_NPROC,0x81,0x4,0x01,"Jaguar (855, 955)"},
50 {HPHW_NPROC,0x82,0x4,0x01,"Cougar (860, 960)"},
51 {HPHW_NPROC,0x83,0x4,0x13,"Panther (865, 870, 980)"},
52 {HPHW_NPROC,0x100,0x4,0x01,"Burgundy (810)"},
53 {HPHW_NPROC,0x101,0x4,0x01,"SilverFox Low (822, 922)"},
54 {HPHW_NPROC,0x102,0x4,0x01,"SilverFox High (832, 932)"},
55 {HPHW_NPROC,0x103,0x4,0x01,"Lego, SilverLite (815, 808, 920)"},
56 {HPHW_NPROC,0x104,0x4,0x03,"SilverBullet Low (842, 948)"},
57 {HPHW_NPROC,0x105,0x4,0x03,"SilverBullet High (852, 958)"},
58 {HPHW_NPROC,0x106,0x4,0x81,"Oboe"},
59 {HPHW_NPROC,0x180,0x4,0x12,"Dragon"},
60 {HPHW_NPROC,0x181,0x4,0x13,"Chimera (890, 990, 992)"},
61 {HPHW_NPROC,0x182,0x4,0x91,"TNT 100 (891,T500)"},
62 {HPHW_NPROC,0x183,0x4,0x91,"TNT 120 (892,T520)"},
63 {HPHW_NPROC,0x184,0x4,0x91,"Jade 180 U (893,T540)"},
64 {HPHW_NPROC,0x1FF,0x4,0x91,"Hitachi X Processor"},
65 {HPHW_NPROC,0x200,0x4,0x81,"Cobra (720)"},
66 {HPHW_NPROC,0x201,0x4,0x81,"Coral (750)"},
67 {HPHW_NPROC,0x202,0x4,0x81,"King Cobra (730)"},
68 {HPHW_NPROC,0x203,0x4,0x81,"Hardball (735/99)"},
69 {HPHW_NPROC,0x204,0x4,0x81,"Coral II (755/99)"},
70 {HPHW_NPROC,0x205,0x4,0x81,"Coral II (755/125)"},
71 {HPHW_NPROC,0x205,0x4,0x91,"Snake Eagle "},
72 {HPHW_NPROC,0x206,0x4,0x81,"Snake Cheetah (735/130)"},
73 {HPHW_NPROC,0x280,0x4,0x81,"Nova Low (817, 827, 957, 957LX)"},
74 {HPHW_NPROC,0x281,0x4,0x81,"Nova High (837, 847, 857, 967, 967LX)"},
75 {HPHW_NPROC,0x282,0x4,0x81,"Nova8 (807, 917, 917LX, 927,927LX, 937, 937LX, 947,947LX)"},
76 {HPHW_NPROC,0x283,0x4,0x81,"Nova64 (867, 877, 977)"},
77 {HPHW_NPROC,0x284,0x4,0x81,"TNova (887, 897, 987)"},
78 {HPHW_NPROC,0x285,0x4,0x81,"TNova64"},
79 {HPHW_NPROC,0x286,0x4,0x91,"Hydra64 (Nova)"},
80 {HPHW_NPROC,0x287,0x4,0x91,"Hydra96 (Nova)"},
81 {HPHW_NPROC,0x288,0x4,0x81,"TNova96"},
82 {HPHW_NPROC,0x300,0x4,0x81,"Bushmaster (710)"},
83 {HPHW_NPROC,0x302,0x4,0x81,"Flounder (705)"},
84 {HPHW_NPROC,0x310,0x4,0x81,"Scorpio (715/50)"},
85 {HPHW_NPROC,0x311,0x4,0x81,"Scorpio Jr.(715/33)"},
86 {HPHW_NPROC,0x312,0x4,0x81,"Strider-50 (715S/50)"},
87 {HPHW_NPROC,0x313,0x4,0x81,"Strider-33 (715S/33)"},
88 {HPHW_NPROC,0x314,0x4,0x81,"Trailways-50 (715T/50)"},
89 {HPHW_NPROC,0x315,0x4,0x81,"Trailways-33 (715T/33)"},
90 {HPHW_NPROC,0x316,0x4,0x81,"Scorpio Sr.(715/75)"},
91 {HPHW_NPROC,0x317,0x4,0x81,"Scorpio 100 (715/100)"},
92 {HPHW_NPROC,0x318,0x4,0x81,"Spectra (725/50)"},
93 {HPHW_NPROC,0x319,0x4,0x81,"Spectra (725/75)"},
94 {HPHW_NPROC,0x320,0x4,0x81,"Spectra (725/100)"},
95 {HPHW_NPROC,0x401,0x4,0x81,"Pace (745i, 747i)"},
96 {HPHW_NPROC,0x402,0x4,0x81,"Sidewinder (742i)"},
97 {HPHW_NPROC,0x403,0x4,0x81,"Fast Pace"},
98 {HPHW_NPROC,0x480,0x4,0x81,"Orville (E23)"},
99 {HPHW_NPROC,0x481,0x4,0x81,"Wilbur (E25)"},
100 {HPHW_NPROC,0x482,0x4,0x81,"WB-80 (E35)"},
101 {HPHW_NPROC,0x483,0x4,0x81,"WB-96 (E45)"},
102 {HPHW_NPROC,0x484,0x4,0x81,"UL Proc L-100 (811/D210,D310)"},
103 {HPHW_NPROC,0x485,0x4,0x81,"UL Proc L-75 (801/D200)"},
104 {HPHW_NPROC,0x501,0x4,0x81,"Merlin L2 132 (9000/778/B132L)"},
105 {HPHW_NPROC,0x502,0x4,0x81,"Merlin L2 160 (9000/778/B160L)"},
106 {HPHW_NPROC,0x503,0x4,0x81,"Merlin L2+ 132 (9000/778/B132L)"},
107 {HPHW_NPROC,0x504,0x4,0x81,"Merlin L2+ 180 (9000/778/B180L)"},
108 {HPHW_NPROC,0x505,0x4,0x81,"Raven L2 132 (9000/778/C132L)"},
109 {HPHW_NPROC,0x506,0x4,0x81,"Raven L2 160 (9000/779/C160L)"},
110 {HPHW_NPROC,0x507,0x4,0x81,"Raven L2 180 (9000/779/C180L)"},
111 {HPHW_NPROC,0x508,0x4,0x81,"Raven L2 160 (9000/779/C160L)"},
112 {HPHW_NPROC,0x509,0x4,0x81,"712/132 L2 Upgrade"},
113 {HPHW_NPROC,0x50A,0x4,0x81,"712/160 L2 Upgrade"},
114 {HPHW_NPROC,0x50B,0x4,0x81,"715/132 L2 Upgrade"},
115 {HPHW_NPROC,0x50C,0x4,0x81,"715/160 L2 Upgrade"},
116 {HPHW_NPROC,0x50D,0x4,0x81,"Rocky2 L2 120"},
117 {HPHW_NPROC,0x50E,0x4,0x81,"Rocky2 L2 150"},
118 {HPHW_NPROC,0x50F,0x4,0x81,"Anole L2 132 (744)"},
119 {HPHW_NPROC,0x510,0x4,0x81,"Anole L2 165 (744)"},
120 {HPHW_NPROC,0x511,0x4,0x81,"Kiji L2 132"},
121 {HPHW_NPROC,0x512,0x4,0x81,"UL L2 132 (803/D220,D320)"},
122 {HPHW_NPROC,0x513,0x4,0x81,"UL L2 160 (813/D220,D320)"},
123 {HPHW_NPROC,0x514,0x4,0x81,"Merlin Jr L2 132"},
124 {HPHW_NPROC,0x515,0x4,0x81,"Staccato L2 132"},
125 {HPHW_NPROC,0x516,0x4,0x81,"Staccato L2 180 (A Class 180)"},
126 {HPHW_NPROC,0x580,0x4,0x81,"KittyHawk DC2-100 (K100)"},
127 {HPHW_NPROC,0x581,0x4,0x91,"KittyHawk DC3-120 (K210)"},
128 {HPHW_NPROC,0x582,0x4,0x91,"KittyHawk DC3 100 (K400)"},
129 {HPHW_NPROC,0x583,0x4,0x91,"KittyHawk DC3 120 (K410)"},
130 {HPHW_NPROC,0x584,0x4,0x91,"LighteningHawk T120"},
131 {HPHW_NPROC,0x585,0x4,0x91,"SkyHawk 100"},
132 {HPHW_NPROC,0x586,0x4,0x91,"SkyHawk 120"},
133 {HPHW_NPROC,0x587,0x4,0x81,"UL Proc 1-way T'120"},
134 {HPHW_NPROC,0x588,0x4,0x91,"UL Proc 2-way T'120"},
135 {HPHW_NPROC,0x589,0x4,0x81,"UL Proc 1-way T'100 (821/D250,D350)"},
136 {HPHW_NPROC,0x58A,0x4,0x91,"UL Proc 2-way T'100 (831/D250,D350)"},
137 {HPHW_NPROC,0x58B,0x4,0x91,"KittyHawk DC2 100 (K200)"},
138 {HPHW_NPROC,0x58C,0x4,0x91,"ThunderHawk DC3- 120 1M (K220)"},
139 {HPHW_NPROC,0x58D,0x4,0x91,"ThunderHawk DC3 120 1M (K420)"},
140 {HPHW_NPROC,0x58E,0x4,0x81,"Raven 120 T'"},
141 {HPHW_NPROC,0x58F,0x4,0x91,"Mohawk 160 U 1M DC3 (K450)"},
142 {HPHW_NPROC,0x590,0x4,0x91,"Mohawk 180 U 1M DC3 (K460)"},
143 {HPHW_NPROC,0x591,0x4,0x91,"Mohawk 200 U 1M DC3"},
144 {HPHW_NPROC,0x592,0x4,0x81,"Raven 100 T'"},
145 {HPHW_NPROC,0x593,0x4,0x91,"FireHawk 160 U"},
146 {HPHW_NPROC,0x594,0x4,0x91,"FireHawk 180 U"},
147 {HPHW_NPROC,0x595,0x4,0x91,"FireHawk 220 U"},
148 {HPHW_NPROC,0x596,0x4,0x91,"FireHawk 240 U"},
149 {HPHW_NPROC,0x597,0x4,0x91,"SPP2000 processor"},
150 {HPHW_NPROC,0x598,0x4,0x81,"Raven U 230 (9000/780/C230)"},
151 {HPHW_NPROC,0x599,0x4,0x81,"Raven U 240 (9000/780/C240)"},
152 {HPHW_NPROC,0x59A,0x4,0x91,"Unlisted but reserved"},
153 {HPHW_NPROC,0x59A,0x4,0x81,"Unlisted but reserved"},
154 {HPHW_NPROC,0x59B,0x4,0x81,"Raven U 160 (9000/780/C160)"},
155 {HPHW_NPROC,0x59C,0x4,0x81,"Raven U 180 (9000/780/C180)"},
156 {HPHW_NPROC,0x59D,0x4,0x81,"Raven U 200 (9000/780/C200)"},
157 {HPHW_NPROC,0x59E,0x4,0x91,"ThunderHawk T' 120"},
158 {HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780)"},
159 {HPHW_NPROC,0x5A0,0x4,0x81,"UL 1w T120 1MB/1MB (841/D260,D360)"},
160 {HPHW_NPROC,0x5A1,0x4,0x91,"UL 2w T120 1MB/1MB (851/D260,D360)"},
161 {HPHW_NPROC,0x5A2,0x4,0x81,"UL 1w U160 512K/512K (861/D270,D370)"},
162 {HPHW_NPROC,0x5A3,0x4,0x91,"UL 2w U160 512K/512K (871/D270,D370)"},
163 {HPHW_NPROC,0x5A4,0x4,0x91,"Mohawk 160 U 1M DC3- (K250)"},
164 {HPHW_NPROC,0x5A5,0x4,0x91,"Mohawk 180 U 1M DC3- (K260)"},
165 {HPHW_NPROC,0x5A6,0x4,0x91,"Mohawk 200 U 1M DC3-"},
166 {HPHW_NPROC,0x5A7,0x4,0x81,"UL proc 1-way U160 1M/1M"},
167 {HPHW_NPROC,0x5A8,0x4,0x91,"UL proc 2-way U160 1M/1M"},
168 {HPHW_NPROC,0x5A9,0x4,0x81,"UL proc 1-way U180 1M/1M"},
169 {HPHW_NPROC,0x5AA,0x4,0x91,"UL proc 2-way U180 1M/1M"},
170 {HPHW_NPROC,0x5AB,0x4,0x91,"Obsolete"},
171 {HPHW_NPROC,0x5AB,0x4,0x81,"Obsolete"},
172 {HPHW_NPROC,0x5AC,0x4,0x91,"Obsolete"},
173 {HPHW_NPROC,0x5AC,0x4,0x81,"Obsolete"},
174 {HPHW_NPROC,0x5AD,0x4,0x91,"BraveHawk 180MHz DC3-"},
175 {HPHW_NPROC,0x5AE,0x4,0x91,"BraveHawk 200MHz DC3- (898/K370)"},
176 {HPHW_NPROC,0x5AF,0x4,0x91,"BraveHawk 220MHz DC3-"},
177 {HPHW_NPROC,0x5B0,0x4,0x91,"BraveHawk 180MHz DC3"},
178 {HPHW_NPROC,0x5B1,0x4,0x91,"BraveHawk 200MHz DC3 (899/K570)"},
179 {HPHW_NPROC,0x5B2,0x4,0x91,"BraveHawk 220MHz DC3"},
180 {HPHW_NPROC,0x5B3,0x4,0x91,"FireHawk 200"},
181 {HPHW_NPROC,0x5B4,0x4,0x91,"SPP2500"},
182 {HPHW_NPROC,0x5B5,0x4,0x91,"SummitHawk U+"},
183 {HPHW_NPROC,0x5B6,0x4,0x91,"DragonHawk U+ 240 DC3"},
184 {HPHW_NPROC,0x5B7,0x4,0x91,"DragonHawk U+ 240 DC3-"},
185 {HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"},
186 {HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"},
187 {HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"},
188 {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W"},
189 {HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"},
190 {HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"},
191 {HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"},
192 {HPHW_NPROC,0x5BF,0x4,0x91,"Forte W 4-way"},
193 {HPHW_NPROC,0x5C0,0x4,0x91,"M2250"},
194 {HPHW_NPROC,0x5C1,0x4,0x91,"M2500"},
195 {HPHW_NPROC,0x5C2,0x4,0x91,"Sonata 440"},
196 {HPHW_NPROC,0x5C3,0x4,0x91,"Sonata 360"},
197 {HPHW_NPROC,0x5C4,0x4,0x91,"Rhapsody 440"},
198 {HPHW_NPROC,0x5C5,0x4,0x91,"Rhapsody 360"},
199 {HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780)"},
200 {HPHW_NPROC,0x5C7,0x4,0x91,"Halfdome W 440"},
201 {HPHW_NPROC,0x5C8,0x4,0x81,"Lego 360 processor"},
202 {HPHW_NPROC,0x5C9,0x4,0x91,"Rhapsody DC- 440"},
203 {HPHW_NPROC,0x5CA,0x4,0x91,"Rhapsody DC- 360"},
204 {HPHW_NPROC,0x5CB,0x4,0x91,"Crescendo 440"},
205 {HPHW_NPROC,0x5CC,0x4,0x91,"Prelude W 440"},
206 {HPHW_NPROC,0x5CD,0x4,0x91,"SPP2600"},
207 {HPHW_NPROC,0x5CE,0x4,0x91,"M2600"},
208 {HPHW_NPROC,0x5CF,0x4,0x81,"Allegro W+"},
209 {HPHW_NPROC,0x5D0,0x4,0x81,"Kazoo W+"},
210 {HPHW_NPROC,0x5D1,0x4,0x91,"Forte W+ 2w"},
211 {HPHW_NPROC,0x5D2,0x4,0x91,"Forte W+ 4w"},
212 {HPHW_NPROC,0x5D3,0x4,0x91,"Prelude W+ 540"},
213 {HPHW_NPROC,0x5D4,0x4,0x91,"Duet W+"},
214 {HPHW_NPROC,0x5D5,0x4,0x91,"Crescendo 550"},
215 {HPHW_NPROC,0x5D6,0x4,0x81,"Crescendo DC- 440"},
216 {HPHW_NPROC,0x5D7,0x4,0x91,"Keystone W+"},
217 {HPHW_NPROC,0x5D8,0x4,0x91,"Rhapsody wave 2 W+ DC-"},
218 {HPHW_NPROC,0x5D9,0x4,0x91,"Rhapsody wave 2 W+"},
219 {HPHW_NPROC,0x5DA,0x4,0x91,"Marcato W+ DC-"},
220 {HPHW_NPROC,0x5DB,0x4,0x91,"Marcato W+"},
221 {HPHW_NPROC,0x5DC,0x4,0x91,"Allegro W2"},
222 {HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"},
223 {HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"},
224 {HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"},
225 {HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"},
226 {HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"},
227 {HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"},
228 {HPHW_NPROC,0x5E3,0x4,0x91,"Crescendo 750 W2"},
229 {HPHW_NPROC,0x5E4,0x4,0x91,"Keystone/Matterhorn W2 750"},
230 {HPHW_NPROC,0x5E5,0x4,0x91,"PowerBar W+"},
231 {HPHW_NPROC,0x5E6,0x4,0x91,"Keystone/Matterhorn W2 650"},
232 {HPHW_NPROC,0x5E7,0x4,0x91,"Caribe W2 800"},
233 {HPHW_NPROC,0x5E8,0x4,0x91,"Pikes Peak W2"},
234 {HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"},
235 {HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"},
236 {HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"},
237 {HPHW_NPROC,0x602,0x4,0x81,"Gecko 100 (712/100)"},
238 {HPHW_NPROC,0x603,0x4,0x81,"Anole 64 (743/64)"},
239 {HPHW_NPROC,0x604,0x4,0x81,"Anole 100 (743/100)"},
240 {HPHW_NPROC,0x605,0x4,0x81,"Gecko 120 (712/120)"},
241 {HPHW_NPROC,0x606,0x4,0x81,"Gila 80"},
242 {HPHW_NPROC,0x607,0x4,0x81,"Gila 100"},
243 {HPHW_NPROC,0x608,0x4,0x81,"Gila 120"},
244 {HPHW_NPROC,0x609,0x4,0x81,"Scorpio-L 80"},
245 {HPHW_NPROC,0x60A,0x4,0x81,"Mirage Jr (715/64)"},
246 {HPHW_NPROC,0x60B,0x4,0x81,"Mirage 100"},
247 {HPHW_NPROC,0x60C,0x4,0x81,"Mirage 100+"},
248 {HPHW_NPROC,0x60D,0x4,0x81,"Electra 100"},
249 {HPHW_NPROC,0x60E,0x4,0x81,"Electra 120"},
250 {HPHW_NPROC,0x610,0x4,0x81,"Scorpio-L 100"},
251 {HPHW_NPROC,0x611,0x4,0x81,"Scorpio-L 120"},
252 {HPHW_NPROC,0x612,0x4,0x81,"Spectra-L 80"},
253 {HPHW_NPROC,0x613,0x4,0x81,"Spectra-L 100"},
254 {HPHW_NPROC,0x614,0x4,0x81,"Spectra-L 120"},
255 {HPHW_NPROC,0x615,0x4,0x81,"Piranha 100"},
256 {HPHW_NPROC,0x616,0x4,0x81,"Piranha 120"},
257 {HPHW_NPROC,0x617,0x4,0x81,"Jason 50"},
258 {HPHW_NPROC,0x618,0x4,0x81,"Jason 100"},
259 {HPHW_NPROC,0x619,0x4,0x81,"Mirage 80"},
260 {HPHW_NPROC,0x61A,0x4,0x81,"SAIC L-80"},
261 {HPHW_NPROC,0x61B,0x4,0x81,"Rocky1 L-60"},
262 {HPHW_NPROC,0x61C,0x4,0x81,"Anole T (743/T)"},
263 {HPHW_NPROC,0x67E,0x4,0x81,"Hitachi Tiny 80"},
264 {HPHW_NPROC,0x67F,0x4,0x81,"Hitachi Tiny 64"},
265 {HPHW_NPROC,0x700,0x4,0x91,"NEC Aska Processor"},
266 {HPHW_NPROC,0x880,0x4,0x91,"Orca Mako"},
267 {HPHW_NPROC,0x881,0x4,0x91,"Everest Mako"},
268 {HPHW_NPROC,0x882,0x4,0x91,"Rainier/Medel Mako Slow"},
269 {HPHW_NPROC,0x883,0x4,0x91,"Rainier/Medel Mako Fast"},
270 {HPHW_NPROC,0x884,0x4,0x91,"Mt. Hamilton"},
271 {HPHW_NPROC,0x885,0x4,0x91,"Mt. Hamilton DC-"},
272 {HPHW_NPROC,0x886,0x4,0x91,"Storm Peak Slow DC-"},
273 {HPHW_NPROC,0x887,0x4,0x91,"Storm Peak Slow"},
274 {HPHW_NPROC,0x888,0x4,0x91,"Storm Peak Fast DC-"},
275 {HPHW_NPROC,0x889,0x4,0x91,"Storm Peak Fast"},
276 {HPHW_NPROC,0x88A,0x4,0x91,"Crestone Peak"},
277 {HPHW_A_DIRECT, 0x004, 0x0000D, 0x00, "Arrakis MUX"},
278 {HPHW_A_DIRECT, 0x005, 0x0000D, 0x00, "Dyun Kiuh MUX"},
279 {HPHW_A_DIRECT, 0x006, 0x0000D, 0x00, "Baat Kiuh AP/MUX (40299B)"},
280 {HPHW_A_DIRECT, 0x007, 0x0000D, 0x00, "Dino AP"},
281 {HPHW_A_DIRECT, 0x009, 0x0000D, 0x00, "Solaris Direct Connect MUX (J2092A)"},
282 {HPHW_A_DIRECT, 0x00A, 0x0000D, 0x00, "Solaris RS-422/423 MUX (J2093A)"},
283 {HPHW_A_DIRECT, 0x00B, 0x0000D, 0x00, "Solaris RS-422/423 Quadriloops MUX"},
284 {HPHW_A_DIRECT, 0x00C, 0x0000D, 0x00, "Solaris Modem MUX (J2094A)"},
285 {HPHW_A_DIRECT, 0x00D, 0x0000D, 0x00, "Twins Direct Connect MUX"},
286 {HPHW_A_DIRECT, 0x00E, 0x0000D, 0x00, "Twins Modem MUX"},
287 {HPHW_A_DIRECT, 0x00F, 0x0000D, 0x00, "Nautilus RS-485"},
288 {HPHW_A_DIRECT, 0x010, 0x0000D, 0x00, "UltraLight CAP/MUX"},
289 {HPHW_A_DIRECT, 0x015, 0x0000D, 0x00, "Eole CAP/MUX"},
290 {HPHW_A_DIRECT, 0x024, 0x0000D, 0x00, "Sahp Kiuh AP/MUX"},
291 {HPHW_A_DIRECT, 0x034, 0x0000D, 0x00, "Sahp Kiuh Low AP/MUX"},
292 {HPHW_A_DIRECT, 0x044, 0x0000D, 0x00, "Sahp Baat Kiuh AP/MUX"},
293 {HPHW_A_DIRECT, 0x004, 0x0000E, 0x80, "Burgundy RS-232"},
294 {HPHW_A_DIRECT, 0x005, 0x0000E, 0x80, "Silverfox RS-232"},
295 {HPHW_A_DIRECT, 0x006, 0x0000E, 0x80, "Lego RS-232"},
296 {HPHW_A_DIRECT, 0x004, 0x0000F, 0x00, "Peacock Graphics"},
297 {HPHW_A_DIRECT, 0x004, 0x00014, 0x80, "Burgundy HIL"},
298 {HPHW_A_DIRECT, 0x005, 0x00014, 0x80, "Peacock HIL"},
299 {HPHW_A_DIRECT, 0x004, 0x00015, 0x80, "Leonardo"},
300 {HPHW_A_DIRECT, 0x004, 0x00016, 0x80, "HP-PB HRM"},
301 {HPHW_A_DIRECT, 0x004, 0x00017, 0x80, "HP-PB HRC"},
302 {HPHW_A_DIRECT, 0x004, 0x0003A, 0x80, "Skunk Centronics (28655A)"},
303 {HPHW_A_DIRECT, 0x024, 0x0003A, 0x80, "Sahp Kiuh Centronics"},
304 {HPHW_A_DIRECT, 0x044, 0x0003A, 0x80, "Sahp Baat Kiuh Centronics"},
305 {HPHW_A_DIRECT, 0x004, 0x0004E, 0x80, "AT&T DataKit (AMSO)"},
306 {HPHW_A_DIRECT, 0x004, 0x0009B, 0x80, "Test&Meas GSC HPIB"},
307 {HPHW_A_DIRECT, 0x004, 0x000A8, 0x00, "Rocky2-120 Front Keyboard"},
308 {HPHW_A_DIRECT, 0x005, 0x000A8, 0x00, "Rocky2-150 Front Keyboard"},
309 {HPHW_A_DIRECT, 0x004, 0x00101, 0x80, "Hitachi Console Module"},
310 {HPHW_A_DIRECT, 0x004, 0x00102, 0x80, "Hitachi Boot Module"},
311 {HPHW_A_DIRECT, 0x004, 0x00203, 0x80, "MELCO HBMLA MLAIT"},
312 {HPHW_A_DIRECT, 0x004, 0x00208, 0x80, "MELCO HBDPC"},
313 {HPHW_A_DIRECT, 0x004, 0x00300, 0x00, "DCI TWINAX TERM IO MUX"},
314 {HPHW_A_DMA, 0x004, 0x00039, 0x80, "Skunk SCSI (28655A)"},
315 {HPHW_A_DMA, 0x005, 0x00039, 0x80, "KittyHawk CSY Core SCSI"},
316 {HPHW_A_DMA, 0x014, 0x00039, 0x80, "Diablo SCSI"},
317 {HPHW_A_DMA, 0x024, 0x00039, 0x80, "Sahp Kiuh SCSI"},
318 {HPHW_A_DMA, 0x034, 0x00039, 0x80, "Sahp Kiuh Low SCSI"},
319 {HPHW_A_DMA, 0x044, 0x00039, 0x80, "Sahp Baat Kiuh SCSI"},
320 {HPHW_A_DMA, 0x004, 0x0003B, 0x80, "Wizard SCSI"},
321 {HPHW_A_DMA, 0x005, 0x0003B, 0x80, "KittyHawk CSY Core FW-SCSI"},
322 {HPHW_A_DMA, 0x006, 0x0003B, 0x80, "Symbios EPIC FW-SCSI"},
323 {HPHW_A_DMA, 0x004, 0x00040, 0x80, "HP-PB Shazam HPIB (28650A)"},
324 {HPHW_A_DMA, 0x005, 0x00040, 0x80, "Burgundy HPIB"},
325 {HPHW_A_DMA, 0x004, 0x00041, 0x80, "HP-PB HP-FL"},
326 {HPHW_A_DMA, 0x004, 0x00042, 0x80, "HP-PB LoQuix HPIB (28650B)"},
327 {HPHW_A_DMA, 0x004, 0x00043, 0x80, "HP-PB Crypt LoQuix"},
328 {HPHW_A_DMA, 0x004, 0x00044, 0x80, "HP-PB Shazam GPIO (28651A)"},
329 {HPHW_A_DMA, 0x004, 0x00045, 0x80, "HP-PB LoQuix GPIO"},
330 {HPHW_A_DMA, 0x004, 0x00046, 0x80, "2-Port X.25 NIO_ACC (AMSO)"},
331 {HPHW_A_DMA, 0x004, 0x00047, 0x80, "4-Port X.25 NIO_ACC (AMSO)"},
332 {HPHW_A_DMA, 0x004, 0x0004B, 0x80, "LGB Control"},
333 {HPHW_A_DMA, 0x004, 0x0004C, 0x80, "Martian RTI (AMSO)"},
334 {HPHW_A_DMA, 0x004, 0x0004D, 0x80, "ACC Mux (AMSO)"},
335 {HPHW_A_DMA, 0x004, 0x00050, 0x80, "Lanbrusca 802.3 (36967A)"},
336 {HPHW_A_DMA, 0x004, 0x00056, 0x80, "HP-PB LoQuix FDDI"},
337 {HPHW_A_DMA, 0x004, 0x00057, 0x80, "HP-PB LoQuix FDDI (28670A)"},
338 {HPHW_A_DMA, 0x004, 0x0005E, 0x00, "Gecko Add-on Token Ring"},
339 {HPHW_A_DMA, 0x012, 0x00089, 0x80, "Barracuda Add-on FW-SCSI"},
340 {HPHW_A_DMA, 0x013, 0x00089, 0x80, "Bluefish Add-on FW-SCSI"},
341 {HPHW_A_DMA, 0x014, 0x00089, 0x80, "Shrike Add-on FW-SCSI"},
342 {HPHW_A_DMA, 0x015, 0x00089, 0x80, "KittyHawk GSY Core FW-SCSI"},
343 {HPHW_A_DMA, 0x017, 0x00089, 0x80, "Shrike Jade Add-on FW-SCSI (A3644A)"},
344 {HPHW_A_DMA, 0x01F, 0x00089, 0x80, "SkyHawk 100/120 FW-SCSI"},
345 {HPHW_A_DMA, 0x027, 0x00089, 0x80, "Piranha 100 FW-SCSI"},
346 {HPHW_A_DMA, 0x032, 0x00089, 0x80, "Raven T' Core FW-SCSI"},
347 {HPHW_A_DMA, 0x03B, 0x00089, 0x80, "Raven U/L2 Core FW-SCSI"},
348 {HPHW_A_DMA, 0x03C, 0x00089, 0x80, "Merlin 132 Core FW-SCSI"},
349 {HPHW_A_DMA, 0x03D, 0x00089, 0x80, "Merlin 160 Core FW-SCSI"},
350 {HPHW_A_DMA, 0x044, 0x00089, 0x80, "Mohawk Core FW-SCSI"},
351 {HPHW_A_DMA, 0x051, 0x00089, 0x80, "Firehawk FW-SCSI"},
352 {HPHW_A_DMA, 0x058, 0x00089, 0x80, "FireHawk 200 FW-SCSI"},
353 {HPHW_A_DMA, 0x05C, 0x00089, 0x80, "SummitHawk 230 Ultra-SCSI"},
354 {HPHW_A_DMA, 0x014, 0x00091, 0x80, "Baby Hugo Add-on Net FC (A3406A)"},
355 {HPHW_A_DMA, 0x020, 0x00091, 0x80, "Baby Jade Add-on Net FC (A3638A)"},
356 {HPHW_A_DMA, 0x004, 0x00092, 0x80, "GSC+ YLIASTER ATM"},
357 {HPHW_A_DMA, 0x004, 0x00095, 0x80, "Hamlyn GSC+ Network Card"},
358 {HPHW_A_DMA, 0x004, 0x00098, 0x80, "Lo-fat Emulator"},
359 {HPHW_A_DMA, 0x004, 0x0009A, 0x80, "GSC+ Venus ATM"},
360 {HPHW_A_DMA, 0x005, 0x0009A, 0x80, "GSC+ Samorobrive ATM"},
361 {HPHW_A_DMA, 0x004, 0x0009D, 0x80, "HP HSC-PCI Cards"},
362 {HPHW_A_DMA, 0x004, 0x0009E, 0x80, "Alaxis GSC+ 155Mb ATM"},
363 {HPHW_A_DMA, 0x005, 0x0009E, 0x80, "Alaxis GSC+ 622Mb ATM"},
364 {HPHW_A_DMA, 0x05C, 0x0009F, 0x80, "SummitHawk 230 USB"},
365 {HPHW_A_DMA, 0x05C, 0x000A0, 0x80, "SummitHawk 230 100BaseT"},
366 {HPHW_A_DMA, 0x015, 0x000A7, 0x80, "Baby Hugo Add-on mass FC (A3404A)"},
367 {HPHW_A_DMA, 0x018, 0x000A7, 0x80, "Mombasa GS Add-on mass FC (A3591)"},
368 {HPHW_A_DMA, 0x021, 0x000A7, 0x80, "Baby Jade Add-on mass FC (A3636A)"},
369 {HPHW_A_DMA, 0x004, 0x00201, 0x80, "MELCO HCMAP"},
370 {HPHW_A_DMA, 0x004, 0x00202, 0x80, "MELCO HBMLA MLAMA"},
371 {HPHW_A_DMA, 0x004, 0x00205, 0x80, "MELCO HBRFU"},
372 {HPHW_A_DMA, 0x004, 0x00380, 0x80, "Interphase NIO-FC"},
373 {HPHW_A_DMA, 0x004, 0x00381, 0x80, "Interphase NIO-ATM"},
374 {HPHW_A_DMA, 0x004, 0x00382, 0x80, "Interphase NIO-100BaseTX"},
375 {HPHW_BA, 0x004, 0x00070, 0x0, "Cobra Core BA"},
376 {HPHW_BA, 0x005, 0x00070, 0x0, "Coral Core BA"},
377 {HPHW_BA, 0x006, 0x00070, 0x0, "Bushmaster Core BA"},
378 {HPHW_BA, 0x007, 0x00070, 0x0, "Scorpio Core BA"},
379 {HPHW_BA, 0x008, 0x00070, 0x0, "Flounder Core BA"},
380 {HPHW_BA, 0x009, 0x00070, 0x0, "Outfield Core BA"},
381 {HPHW_BA, 0x00A, 0x00070, 0x0, "CoralII Core BA"},
382 {HPHW_BA, 0x00B, 0x00070, 0x0, "Scorpio Jr. Core BA"},
383 {HPHW_BA, 0x00C, 0x00070, 0x0, "Strider-50 Core BA"},
384 {HPHW_BA, 0x00D, 0x00070, 0x0, "Strider-33 Core BA"},
385 {HPHW_BA, 0x00E, 0x00070, 0x0, "Trailways-50 Core BA"},
386 {HPHW_BA, 0x00F, 0x00070, 0x0, "Trailways-33 Core BA"},
387 {HPHW_BA, 0x010, 0x00070, 0x0, "Pace Core BA"},
388 {HPHW_BA, 0x011, 0x00070, 0x0, "Sidewinder Core BA"},
389 {HPHW_BA, 0x019, 0x00070, 0x0, "Scorpio Sr. Core BA"},
390 {HPHW_BA, 0x020, 0x00070, 0x0, "Scorpio 100 Core BA"},
391 {HPHW_BA, 0x021, 0x00070, 0x0, "Spectra 50 Core BA"},
392 {HPHW_BA, 0x022, 0x00070, 0x0, "Spectra 75 Core BA"},
393 {HPHW_BA, 0x023, 0x00070, 0x0, "Spectra 100 Core BA"},
394 {HPHW_BA, 0x024, 0x00070, 0x0, "Fast Pace Core BA"},
395 {HPHW_BA, 0x026, 0x00070, 0x0, "CoralII Jaguar Core BA"},
396 {HPHW_BA, 0x004, 0x00076, 0x0, "Cobra EISA BA"},
397 {HPHW_BA, 0x005, 0x00076, 0x0, "Coral EISA BA"},
398 {HPHW_BA, 0x007, 0x00076, 0x0, "Scorpio EISA BA"},
399 {HPHW_BA, 0x00A, 0x00076, 0x0, "CoralII EISA BA"},
400 {HPHW_BA, 0x00B, 0x00076, 0x0, "Scorpio Jr. EISA BA"},
401 {HPHW_BA, 0x00C, 0x00076, 0x0, "Strider-50 Core EISA"},
402 {HPHW_BA, 0x00D, 0x00076, 0x0, "Strider-33 Core EISA"},
403 {HPHW_BA, 0x00E, 0x00076, 0x0, "Trailways-50 Core EISA"},
404 {HPHW_BA, 0x00F, 0x00076, 0x0, "Trailways-33 Core EISA"},
405 {HPHW_BA, 0x010, 0x00076, 0x0, "Pace Core EISA"},
406 {HPHW_BA, 0x019, 0x00076, 0x0, "Scorpio Sr. EISA BA"},
407 {HPHW_BA, 0x020, 0x00076, 0x0, "Scorpio 100 EISA BA"},
408 {HPHW_BA, 0x021, 0x00076, 0x0, "Spectra 50 EISA BA"},
409 {HPHW_BA, 0x022, 0x00076, 0x0, "Spectra 75 EISA BA"},
410 {HPHW_BA, 0x023, 0x00076, 0x0, "Spectra 100 EISA BA"},
411 {HPHW_BA, 0x026, 0x00076, 0x0, "CoralII Jaguar EISA BA"},
412 {HPHW_BA, 0x010, 0x00078, 0x0, "Pace VME BA"},
413 {HPHW_BA, 0x011, 0x00078, 0x0, "Sidewinder VME BA"},
414 {HPHW_BA, 0x01A, 0x00078, 0x0, "Anole 64 VME BA"},
415 {HPHW_BA, 0x01B, 0x00078, 0x0, "Anole 100 VME BA"},
416 {HPHW_BA, 0x024, 0x00078, 0x0, "Fast Pace VME BA"},
417 {HPHW_BA, 0x034, 0x00078, 0x0, "Anole T VME BA"},
418 {HPHW_BA, 0x04A, 0x00078, 0x0, "Anole L2 132 VME BA"},
419 {HPHW_BA, 0x04C, 0x00078, 0x0, "Anole L2 165 VME BA"},
420 {HPHW_BA, 0x011, 0x00081, 0x0, "WB-96 Core BA"},
421 {HPHW_BA, 0x012, 0x00081, 0x0, "Orville UX Core BA"},
422 {HPHW_BA, 0x013, 0x00081, 0x0, "Wilbur UX Core BA"},
423 {HPHW_BA, 0x014, 0x00081, 0x0, "WB-80 Core BA"},
424 {HPHW_BA, 0x015, 0x00081, 0x0, "KittyHawk GSY Core BA"},
425 {HPHW_BA, 0x016, 0x00081, 0x0, "Gecko Core BA"},
426 {HPHW_BA, 0x018, 0x00081, 0x0, "Gecko Optional BA"},
427 {HPHW_BA, 0x01A, 0x00081, 0x0, "Anole 64 Core BA"},
428 {HPHW_BA, 0x01B, 0x00081, 0x0, "Anole 100 Core BA"},
429 {HPHW_BA, 0x01C, 0x00081, 0x0, "Gecko 80 Core BA"},
430 {HPHW_BA, 0x01D, 0x00081, 0x0, "Gecko 100 Core BA"},
431 {HPHW_BA, 0x01F, 0x00081, 0x0, "SkyHawk 100/120 Core BA"},
432 {HPHW_BA, 0x027, 0x00081, 0x0, "Piranha 100 Core BA"},
433 {HPHW_BA, 0x028, 0x00081, 0x0, "Mirage Jr Core BA"},
434 {HPHW_BA, 0x029, 0x00081, 0x0, "Mirage Core BA"},
435 {HPHW_BA, 0x02A, 0x00081, 0x0, "Electra Core BA"},
436 {HPHW_BA, 0x02B, 0x00081, 0x0, "Mirage 80 Core BA"},
437 {HPHW_BA, 0x02C, 0x00081, 0x0, "Mirage 100+ Core BA"},
438 {HPHW_BA, 0x02E, 0x00081, 0x0, "UL 350 Lasi Core BA"},
439 {HPHW_BA, 0x02F, 0x00081, 0x0, "UL 550 Lasi Core BA"},
440 {HPHW_BA, 0x032, 0x00081, 0x0, "Raven T' Core BA"},
441 {HPHW_BA, 0x033, 0x00081, 0x0, "Anole T Core BA"},
442 {HPHW_BA, 0x034, 0x00081, 0x0, "SAIC L-80 Core BA"},
443 {HPHW_BA, 0x035, 0x00081, 0x0, "PCX-L2 712/132 Core BA"},
444 {HPHW_BA, 0x036, 0x00081, 0x0, "PCX-L2 712/160 Core BA"},
445 {HPHW_BA, 0x03B, 0x00081, 0x0, "Raven U/L2 Core BA"},
446 {HPHW_BA, 0x03C, 0x00081, 0x0, "Merlin 132 Core BA"},
447 {HPHW_BA, 0x03D, 0x00081, 0x0, "Merlin 160 Core BA"},
448 {HPHW_BA, 0x03E, 0x00081, 0x0, "Merlin+ 132 Core BA"},
449 {HPHW_BA, 0x03F, 0x00081, 0x0, "Merlin+ 180 Core BA"},
450 {HPHW_BA, 0x044, 0x00081, 0x0, "Mohawk Core BA"},
451 {HPHW_BA, 0x045, 0x00081, 0x0, "Rocky1 Core BA"},
452 {HPHW_BA, 0x046, 0x00081, 0x0, "Rocky2 120 Core BA"},
453 {HPHW_BA, 0x047, 0x00081, 0x0, "Rocky2 150 Core BA"},
454 {HPHW_BA, 0x04B, 0x00081, 0x0, "Anole L2 132 Core BA"},
455 {HPHW_BA, 0x04D, 0x00081, 0x0, "Anole L2 165 Core BA"},
456 {HPHW_BA, 0x04E, 0x00081, 0x0, "Kiji L2 132 Core BA"},
457 {HPHW_BA, 0x050, 0x00081, 0x0, "Merlin Jr 132 Core BA"},
458 {HPHW_BA, 0x051, 0x00081, 0x0, "Firehawk Core BA"},
459 {HPHW_BA, 0x056, 0x00081, 0x0, "Raven+ w SE FWSCSI Core BA"},
460 {HPHW_BA, 0x057, 0x00081, 0x0, "Raven+ w Diff FWSCSI Core BA"},
461 {HPHW_BA, 0x058, 0x00081, 0x0, "FireHawk 200 Core BA"},
462 {HPHW_BA, 0x05C, 0x00081, 0x0, "SummitHawk 230 Core BA"},
463 {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 132 Core BA"},
464 {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 180 Core BA"},
465 {HPHW_BA, 0x05F, 0x00081, 0x0, "Staccato 180 Lasi"},
466 {HPHW_BA, 0x800, 0x00081, 0x0, "Hitachi Tiny 64 Core BA"},
467 {HPHW_BA, 0x801, 0x00081, 0x0, "Hitachi Tiny 80 Core BA"},
468 {HPHW_BA, 0x004, 0x0008B, 0x0, "Anole Optional PCMCIA BA"},
469 {HPHW_BA, 0x004, 0x0008E, 0x0, "GSC ITR Wax BA"},
470 {HPHW_BA, 0x00C, 0x0008E, 0x0, "Gecko Optional Wax BA"},
471 {HPHW_BA, 0x010, 0x0008E, 0x0, "Pace Wax BA"},
472 {HPHW_BA, 0x011, 0x0008E, 0x0, "SuperPace Wax BA"},
473 {HPHW_BA, 0x012, 0x0008E, 0x0, "Mirage Jr Wax BA"},
474 {HPHW_BA, 0x013, 0x0008E, 0x0, "Mirage Wax BA"},
475 {HPHW_BA, 0x014, 0x0008E, 0x0, "Electra Wax BA"},
476 {HPHW_BA, 0x017, 0x0008E, 0x0, "Raven Backplane Wax BA"},
477 {HPHW_BA, 0x01E, 0x0008E, 0x0, "Raven T' Wax BA"},
478 {HPHW_BA, 0x01F, 0x0008E, 0x0, "SkyHawk Wax BA"},
479 {HPHW_BA, 0x023, 0x0008E, 0x0, "Rocky1 Wax BA"},
480 {HPHW_BA, 0x02B, 0x0008E, 0x0, "Mirage 80 Wax BA"},
481 {HPHW_BA, 0x02C, 0x0008E, 0x0, "Mirage 100+ Wax BA"},
482 {HPHW_BA, 0x030, 0x0008E, 0x0, "UL 350 Core Wax BA"},
483 {HPHW_BA, 0x031, 0x0008E, 0x0, "UL 550 Core Wax BA"},
484 {HPHW_BA, 0x034, 0x0008E, 0x0, "SAIC L-80 Wax BA"},
485 {HPHW_BA, 0x03A, 0x0008E, 0x0, "Merlin+ Wax BA"},
486 {HPHW_BA, 0x040, 0x0008E, 0x0, "Merlin 132 Wax BA"},
487 {HPHW_BA, 0x041, 0x0008E, 0x0, "Merlin 160 Wax BA"},
488 {HPHW_BA, 0x043, 0x0008E, 0x0, "Merlin 132/160 Wax BA"},
489 {HPHW_BA, 0x052, 0x0008E, 0x0, "Raven+ Hi Power Backplane w/EISA Wax BA"},
490 {HPHW_BA, 0x054, 0x0008E, 0x0, "Raven+ Lo Power Backplane w/EISA Wax BA"},
491 {HPHW_BA, 0x059, 0x0008E, 0x0, "FireHawk 200 Wax BA"},
492 {HPHW_BA, 0x05A, 0x0008E, 0x0, "Raven+ L2 Backplane w/EISA Wax BA"},
493 {HPHW_BA, 0x05D, 0x0008E, 0x0, "SummitHawk Wax BA"},
494 {HPHW_BA, 0x800, 0x0008E, 0x0, "Hitachi Tiny 64 Wax BA"},
495 {HPHW_BA, 0x801, 0x0008E, 0x0, "Hitachi Tiny 80 Wax BA"},
496 {HPHW_BA, 0x011, 0x00090, 0x0, "SuperPace Wax EISA BA"},
497 {HPHW_BA, 0x017, 0x00090, 0x0, "Raven Backplane Wax EISA BA"},
498 {HPHW_BA, 0x01E, 0x00090, 0x0, "Raven T' Wax EISA BA"},
499 {HPHW_BA, 0x01F, 0x00090, 0x0, "SkyHawk 100/120 Wax EISA BA"},
500 {HPHW_BA, 0x027, 0x00090, 0x0, "Piranha 100 Wax EISA BA"},
501 {HPHW_BA, 0x028, 0x00090, 0x0, "Mirage Jr Wax EISA BA"},
502 {HPHW_BA, 0x029, 0x00090, 0x0, "Mirage Wax EISA BA"},
503 {HPHW_BA, 0x02A, 0x00090, 0x0, "Electra Wax EISA BA"},
504 {HPHW_BA, 0x02B, 0x00090, 0x0, "Mirage 80 Wax EISA BA"},
505 {HPHW_BA, 0x02C, 0x00090, 0x0, "Mirage 100+ Wax EISA BA"},
506 {HPHW_BA, 0x030, 0x00090, 0x0, "UL 350 Wax EISA BA"},
507 {HPHW_BA, 0x031, 0x00090, 0x0, "UL 550 Wax EISA BA"},
508 {HPHW_BA, 0x034, 0x00090, 0x0, "SAIC L-80 Wax EISA BA"},
509 {HPHW_BA, 0x03A, 0x00090, 0x0, "Merlin+ Wax EISA BA"},
510 {HPHW_BA, 0x040, 0x00090, 0x0, "Merlin 132 Wax EISA BA"},
511 {HPHW_BA, 0x041, 0x00090, 0x0, "Merlin 160 Wax EISA BA"},
512 {HPHW_BA, 0x043, 0x00090, 0x0, "Merlin 132/160 Wax EISA BA"},
513 {HPHW_BA, 0x052, 0x00090, 0x0, "Raven Hi Power Backplane Wax EISA BA"},
514 {HPHW_BA, 0x054, 0x00090, 0x0, "Raven Lo Power Backplane Wax EISA BA"},
515 {HPHW_BA, 0x059, 0x00090, 0x0, "FireHawk 200 Wax EISA BA"},
516 {HPHW_BA, 0x05A, 0x00090, 0x0, "Raven L2 Backplane Wax EISA BA"},
517 {HPHW_BA, 0x05D, 0x00090, 0x0, "SummitHawk Wax EISA BA"},
518 {HPHW_BA, 0x800, 0x00090, 0x0, "Hitachi Tiny 64 Wax EISA BA"},
519 {HPHW_BA, 0x801, 0x00090, 0x0, "Hitachi Tiny 80 Wax EISA BA"},
520 {HPHW_BA, 0x01A, 0x00093, 0x0, "Anole 64 TIMI BA"},
521 {HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 100 TIMI BA"},
522 {HPHW_BA, 0x034, 0x00093, 0x0, "Anole T TIMI BA"},
523 {HPHW_BA, 0x04A, 0x00093, 0x0, "Anole L2 132 TIMI BA"},
524 {HPHW_BA, 0x04C, 0x00093, 0x0, "Anole L2 165 TIMI BA"},
525 {HPHW_BA, 0x582, 0x000A5, 0x00, "Epic PCI Bridge"},
526 {HPHW_BCPORT, 0x504, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"},
527 {HPHW_BCPORT, 0x505, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"},
528 {HPHW_BCPORT, 0x503, 0x0000C, 0x00, "Java BC GSC+ Port"},
529 {HPHW_BCPORT, 0x57F, 0x0000C, 0x00, "Hitachi Ghostview GSC+ Port"},
530 {HPHW_BCPORT, 0x501, 0x0000C, 0x00, "U2-IOA BC GSC+ Port"},
531 {HPHW_BCPORT, 0x502, 0x0000C, 0x00, "Uturn-IOA BC GSC+ Port"},
532 {HPHW_BCPORT, 0x780, 0x0000C, 0x00, "Astro BC Ropes Port"},
533 {HPHW_BCPORT, 0x506, 0x0000C, 0x00, "NEC-IOS BC HSC Port"},
534 {HPHW_BCPORT, 0x004, 0x0000C, 0x00, "Cheetah BC SMB Port"},
535 {HPHW_BCPORT, 0x006, 0x0000C, 0x00, "Cheetah BC MID_BUS Port"},
536 {HPHW_BCPORT, 0x005, 0x0000C, 0x00, "Condor BC MID_BUS Port"},
537 {HPHW_BCPORT, 0x100, 0x0000C, 0x00, "Condor BC HP-PB Port"},
538 {HPHW_BCPORT, 0x184, 0x0000C, 0x00, "Summit BC Port"},
539 {HPHW_BCPORT, 0x101, 0x0000C, 0x00, "Summit BC HP-PB Port"},
540 {HPHW_BCPORT, 0x102, 0x0000C, 0x00, "HP-PB Port (prefetch)"},
541 {HPHW_BCPORT, 0x500, 0x0000C, 0x00, "Gecko BOA BC GSC+ Port"},
542 {HPHW_BCPORT, 0x103, 0x0000C, 0x00, "Gecko BOA BC HP-PB Port"},
543 {HPHW_BCPORT, 0x507, 0x0000C, 0x00, "Keyaki BC GSC+ Port"},
544 {HPHW_BCPORT, 0x508, 0x0000C, 0x00, "Keyaki-DX BC GSC+ Port"},
545 {HPHW_BCPORT, 0x584, 0x0000C, 0x10, "DEW BC Runway Port"},
546 {HPHW_BCPORT, 0x800, 0x0000C, 0x10, "DEW BC Merced Port"},
547 {HPHW_BCPORT, 0x801, 0x0000C, 0x10, "SMC Bus Interface Merced Bus0"},
548 {HPHW_BCPORT, 0x802, 0x0000C, 0x10, "SMC Bus INterface Merced Bus1"},
549 {HPHW_BCPORT, 0x803, 0x0000C, 0x10, "IKE I/O BC Merced Port"},
550 {HPHW_BCPORT, 0x781, 0x0000C, 0x00, "IKE I/O BC Ropes Port"},
551 {HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O BC Merced Port"},
552 {HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O BC Ropes Port"},
553 {HPHW_BCPORT, 0x784, 0x0000C, 0x00, "Pluto I/O BC Ropes Port"},
554 {HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"},
555 {HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"},
556 {HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"},
557 {HPHW_BRIDGE, 0x583, 0x000A5, 0x00, "Saga PCI Bridge"},
558 {HPHW_BRIDGE, 0x783, 0x0000A, 0x00, "Mercury PCI Bridge"},
559 {HPHW_BRIDGE, 0x784, 0x0000A, 0x00, "Quicksilver AGP Bridge"},
560 {HPHW_B_DMA, 0x004, 0x00018, 0x00, "Parallel I/O"},
561 {HPHW_B_DMA, 0x004, 0x00019, 0x00, "Parallel RDB"},
562 {HPHW_B_DMA, 0x004, 0x00020, 0x80, "MID_BUS PSI"},
563 {HPHW_B_DMA, 0x004, 0x0002F, 0x80, "HP-PB Transit PSI (36960A)"},
564 {HPHW_B_DMA, 0x008, 0x00051, 0x80, "HP-PB Transit 802.3"},
565 {HPHW_B_DMA, 0x004, 0x00052, 0x80, "Miura LAN/Console (J2146A)"},
566 {HPHW_B_DMA, 0x008, 0x00058, 0x80, "HP-PB Transit 802.4"},
567 {HPHW_B_DMA, 0x005, 0x00060, 0x80, "KittyHawk CSY Core LAN/Console"},
568 {HPHW_B_DMA, 0x014, 0x00060, 0x80, "Diablo LAN/Console"},
569 {HPHW_B_DMA, 0x054, 0x00060, 0x80, "Countach LAN/Console"},
570 {HPHW_B_DMA, 0x004, 0x00094, 0x80, "KittyHawk GSC+ Exerciser"},
571 {HPHW_B_DMA, 0x004, 0x00100, 0x80, "HP-PB HF Interface"},
572 {HPHW_B_DMA, 0x000, 0x00206, 0x80, "MELCO HMPHA"},
573 {HPHW_B_DMA, 0x005, 0x00206, 0x80, "MELCO HMPHA_10"},
574 {HPHW_B_DMA, 0x006, 0x00206, 0x80, "MELCO HMQHA"},
575 {HPHW_B_DMA, 0x007, 0x00206, 0x80, "MELCO HMQHA_10"},
576 {HPHW_B_DMA, 0x004, 0x207, 0x80, "MELCO HNDWA MDWS-70"},
577 {HPHW_CIO, 0x004, 0x00010, 0x00, "VLSI CIO"},
578 {HPHW_CIO, 0x005, 0x00010, 0x00, "Silverfox CIO"},
579 {HPHW_CIO, 0x006, 0x00010, 0x00, "Emerald CIO"},
580 {HPHW_CIO, 0x008, 0x00010, 0x00, "Discrete CIO"},
581 {HPHW_CONSOLE, 0x004, 0x0001C, 0x00, "Cheetah console"},
582 {HPHW_CONSOLE, 0x005, 0x0001C, 0x00, "Emerald console"},
583 {HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"},
584 {HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"},
585 {HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"},
586 {HPHW_FABRIC, 0x007, 0x000AA, 0x80, "Caribe DNA Central Agent"},
587 {HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"},
588 {HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"},
589 {HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"},
590 {HPHW_FIO, 0x004, 0x0004F, 0x0, "8-Port X.25 EISA-ACC (AMSO)"},
591 {HPHW_FIO, 0x004, 0x00071, 0x0, "Cobra Core SCSI"},
592 {HPHW_FIO, 0x005, 0x00071, 0x0, "Coral Core SCSI"},
593 {HPHW_FIO, 0x006, 0x00071, 0x0, "Bushmaster Core SCSI"},
594 {HPHW_FIO, 0x007, 0x00071, 0x0, "Scorpio Core SCSI"},
595 {HPHW_FIO, 0x008, 0x00071, 0x0, "Flounder Core SCSI"},
596 {HPHW_FIO, 0x009, 0x00071, 0x0, "Outfield Core SCSI"},
597 {HPHW_FIO, 0x00A, 0x00071, 0x0, "CoralII Core SCSI"},
598 {HPHW_FIO, 0x00B, 0x00071, 0x0, "Scorpio Jr. Core SCSI"},
599 {HPHW_FIO, 0x00C, 0x00071, 0x0, "Strider-50 Core SCSI"},
600 {HPHW_FIO, 0x00D, 0x00071, 0x0, "Strider-33 Core SCSI"},
601 {HPHW_FIO, 0x00E, 0x00071, 0x0, "Trailways-50 Core SCSI"},
602 {HPHW_FIO, 0x00F, 0x00071, 0x0, "Trailways-33 Core SCSI"},
603 {HPHW_FIO, 0x010, 0x00071, 0x0, "Pace Core SCSI"},
604 {HPHW_FIO, 0x011, 0x00071, 0x0, "Sidewinder Core SCSI"},
605 {HPHW_FIO, 0x019, 0x00071, 0x0, "Scorpio Sr. Core SCSI"},
606 {HPHW_FIO, 0x020, 0x00071, 0x0, "Scorpio 100 Core SCSI"},
607 {HPHW_FIO, 0x021, 0x00071, 0x0, "Spectra 50 Core SCSI"},
608 {HPHW_FIO, 0x022, 0x00071, 0x0, "Spectra 75 Core SCSI"},
609 {HPHW_FIO, 0x023, 0x00071, 0x0, "Spectra 100 Core SCSI"},
610 {HPHW_FIO, 0x024, 0x00071, 0x0, "Fast Pace Core SCSI"},
611 {HPHW_FIO, 0x026, 0x00071, 0x0, "CoralII Jaguar Core SCSI"},
612 {HPHW_FIO, 0x004, 0x00072, 0x0, "Cobra Core LAN (802.3)"},
613 {HPHW_FIO, 0x005, 0x00072, 0x0, "Coral Core LAN (802.3)"},
614 {HPHW_FIO, 0x006, 0x00072, 0x0, "Bushmaster Core LAN (802.3)"},
615 {HPHW_FIO, 0x007, 0x00072, 0x0, "Scorpio Core LAN (802.3)"},
616 {HPHW_FIO, 0x008, 0x00072, 0x0, "Flounder Core LAN (802.3)"},
617 {HPHW_FIO, 0x009, 0x00072, 0x0, "Outfield Core LAN (802.3)"},
618 {HPHW_FIO, 0x00A, 0x00072, 0x0, "CoralII Core LAN (802.3)"},
619 {HPHW_FIO, 0x00B, 0x00072, 0x0, "Scorpio Jr. Core LAN (802.3)"},
620 {HPHW_FIO, 0x00C, 0x00072, 0x0, "Strider-50 Core LAN (802.3)"},
621 {HPHW_FIO, 0x00D, 0x00072, 0x0, "Strider-33 Core LAN (802.3)"},
622 {HPHW_FIO, 0x00E, 0x00072, 0x0, "Trailways-50 Core LAN (802.3)"},
623 {HPHW_FIO, 0x00F, 0x00072, 0x0, "Trailways-33 Core LAN (802.3)"},
624 {HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core LAN (802.3)"},
625 {HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core LAN (802.3)"},
626 {HPHW_FIO, 0x019, 0x00072, 0x0, "Scorpio Sr. Core LAN (802.3)"},
627 {HPHW_FIO, 0x020, 0x00072, 0x0, "Scorpio 100 Core LAN (802.3)"},
628 {HPHW_FIO, 0x021, 0x00072, 0x0, "Spectra 50 Core LAN (802.3)"},
629 {HPHW_FIO, 0x022, 0x00072, 0x0, "Spectra 75 Core LAN (802.3)"},
630 {HPHW_FIO, 0x023, 0x00072, 0x0, "Spectra 100 Core LAN (802.3)"},
631 {HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core LAN (802.3)"},
632 {HPHW_FIO, 0x026, 0x00072, 0x0, "CoralII Jaguar Core LAN (802.3)"},
633 {HPHW_FIO, 0x004, 0x00073, 0x0, "Cobra Core HIL"},
634 {HPHW_FIO, 0x005, 0x00073, 0x0, "Coral Core HIL"},
635 {HPHW_FIO, 0x006, 0x00073, 0x0, "Bushmaster Core HIL"},
636 {HPHW_FIO, 0x007, 0x00073, 0x0, "Scorpio Core HIL"},
637 {HPHW_FIO, 0x008, 0x00073, 0x0, "Flounder Core HIL"},
638 {HPHW_FIO, 0x009, 0x00073, 0x0, "Outfield Core HIL"},
639 {HPHW_FIO, 0x00A, 0x00073, 0x0, "CoralII Core HIL"},
640 {HPHW_FIO, 0x00B, 0x00073, 0x0, "Scorpio Jr. Core HIL"},
641 {HPHW_FIO, 0x00C, 0x00073, 0x0, "Strider-50 Core HIL"},
642 {HPHW_FIO, 0x00D, 0x00073, 0x0, "Strider-33 Core HIL"},
643 {HPHW_FIO, 0x00E, 0x00073, 0x0, "Trailways-50 Core HIL"},
644 {HPHW_FIO, 0x00F, 0x00073, 0x0, "Trailways-33 Core HIL"},
645 {HPHW_FIO, 0x010, 0x00073, 0x0, "Pace Core HIL"},
646 {HPHW_FIO, 0x011, 0x00073, 0xcc, "SuperPace Wax HIL"},
647 {HPHW_FIO, 0x012, 0x00073, 0x0, "Mirage Jr Wax HIL"},
648 {HPHW_FIO, 0x013, 0x00073, 0x0, "Mirage 100 Wax HIL"},
649 {HPHW_FIO, 0x014, 0x00073, 0x0, "Electra Wax HIL"},
650 {HPHW_FIO, 0x017, 0x00073, 0x0, "Raven Backplane Wax HIL"},
651 {HPHW_FIO, 0x019, 0x00073, 0x0, "Scorpio Sr. Core HIL"},
652 {HPHW_FIO, 0x01E, 0x00073, 0x0, "Raven T' Wax HIL"},
653 {HPHW_FIO, 0x01F, 0x00073, 0x0, "SkyHawk 100/120 Wax HIL"},
654 {HPHW_FIO, 0x020, 0x00073, 0x0, "Scorpio 100 Core HIL"},
655 {HPHW_FIO, 0x021, 0x00073, 0x0, "Spectra 50 Core HIL"},
656 {HPHW_FIO, 0x022, 0x00073, 0x0, "Spectra 75 Core HIL"},
657 {HPHW_FIO, 0x023, 0x00073, 0x0, "Spectra 100 Core HIL"},
658 {HPHW_FIO, 0x024, 0x00073, 0x0, "Fast Pace Core HIL"},
659 {HPHW_FIO, 0x026, 0x00073, 0x0, "CoralII Jaguar Core HIL"},
660 {HPHW_FIO, 0x02B, 0x00073, 0x0, "Mirage 80 Wax HIL"},
661 {HPHW_FIO, 0x02C, 0x00073, 0x0, "Mirage 100+ Wax HIL"},
662 {HPHW_FIO, 0x03A, 0x00073, 0x0, "Merlin+ Wax HIL"},
663 {HPHW_FIO, 0x040, 0x00073, 0x0, "Merlin 132 Wax HIL"},
664 {HPHW_FIO, 0x041, 0x00073, 0x0, "Merlin 160 Wax HIL"},
665 {HPHW_FIO, 0x043, 0x00073, 0x0, "Merlin 132/160 Wax HIL"},
666 {HPHW_FIO, 0x052, 0x00073, 0x0, "Raven+ Hi Power Backplane w/EISA Wax HIL"},
667 {HPHW_FIO, 0x053, 0x00073, 0x0, "Raven+ Hi Power Backplane wo/EISA Wax HIL"},
668 {HPHW_FIO, 0x054, 0x00073, 0x0, "Raven+ Lo Power Backplane w/EISA Wax HIL"},
669 {HPHW_FIO, 0x055, 0x00073, 0x0, "Raven+ Lo Power Backplane wo/EISA Wax HIL"},
670 {HPHW_FIO, 0x059, 0x00073, 0x0, "FireHawk 200 Wax HIL"},
671 {HPHW_FIO, 0x05A, 0x00073, 0x0, "Raven+ L2 Backplane w/EISA Wax HIL"},
672 {HPHW_FIO, 0x05B, 0x00073, 0x0, "Raven+ L2 Backplane wo/EISA Wax HIL"},
673 {HPHW_FIO, 0x05D, 0x00073, 0x0, "SummitHawk Wax HIL"},
674 {HPHW_FIO, 0x800, 0x00073, 0x0, "Hitachi Tiny 64 Wax HIL"},
675 {HPHW_FIO, 0x801, 0x00073, 0x0, "Hitachi Tiny 80 Wax HIL"},
676 {HPHW_FIO, 0x004, 0x00074, 0x0, "Cobra Core Centronics"},
677 {HPHW_FIO, 0x005, 0x00074, 0x0, "Coral Core Centronics"},
678 {HPHW_FIO, 0x006, 0x00074, 0x0, "Bushmaster Core Centronics"},
679 {HPHW_FIO, 0x007, 0x00074, 0x0, "Scorpio Core Centronics"},
680 {HPHW_FIO, 0x008, 0x00074, 0x0, "Flounder Core Centronics"},
681 {HPHW_FIO, 0x009, 0x00074, 0x0, "Outfield Core Centronics"},
682 {HPHW_FIO, 0x00A, 0x00074, 0x0, "CoralII Core Centronics"},
683 {HPHW_FIO, 0x00B, 0x00074, 0x0, "Scorpio Jr. Core Centronics"},
684 {HPHW_FIO, 0x00C, 0x00074, 0x0, "Strider-50 Core Centronics"},
685 {HPHW_FIO, 0x00D, 0x00074, 0x0, "Strider-33 Core Centronics"},
686 {HPHW_FIO, 0x00E, 0x00074, 0x0, "Trailways-50 Core Centronics"},
687 {HPHW_FIO, 0x00F, 0x00074, 0x0, "Trailways-33 Core Centronics"},
688 {HPHW_FIO, 0x010, 0x00074, 0x0, "Pace Core Centronics"},
689 {HPHW_FIO, 0x011, 0x00074, 0x0, "Sidewinder Core Centronics"},
690 {HPHW_FIO, 0x015, 0x00074, 0x0, "KittyHawk GSY Core Centronics"},
691 {HPHW_FIO, 0x016, 0x00074, 0x0, "Gecko Core Centronics"},
692 {HPHW_FIO, 0x019, 0x00074, 0x0, "Scorpio Sr. Core Centronics"},
693 {HPHW_FIO, 0x01A, 0x00074, 0x0, "Anole 64 Core Centronics"},
694 {HPHW_FIO, 0x01B, 0x00074, 0x0, "Anole 100 Core Centronics"},
695 {HPHW_FIO, 0x01C, 0x00074, 0x0, "Gecko 80 Core Centronics"},
696 {HPHW_FIO, 0x01D, 0x00074, 0x0, "Gecko 100 Core Centronics"},
697 {HPHW_FIO, 0x01F, 0x00074, 0x0, "SkyHawk 100/120 Core Centronics"},
698 {HPHW_FIO, 0x020, 0x00074, 0x0, "Scorpio 100 Core Centronics"},
699 {HPHW_FIO, 0x021, 0x00074, 0x0, "Spectra 50 Core Centronics"},
700 {HPHW_FIO, 0x022, 0x00074, 0x0, "Spectra 75 Core Centronics"},
701 {HPHW_FIO, 0x023, 0x00074, 0x0, "Spectra 100 Core Centronics"},
702 {HPHW_FIO, 0x024, 0x00074, 0x0, "Fast Pace Core Centronics"},
703 {HPHW_FIO, 0x026, 0x00074, 0x0, "CoralII Jaguar Core Centronics"},
704 {HPHW_FIO, 0x027, 0x00074, 0x0, "Piranha 100 Core Centronics"},
705 {HPHW_FIO, 0x028, 0x00074, 0x0, "Mirage Jr Core Centronics"},
706 {HPHW_FIO, 0x029, 0x00074, 0x0, "Mirage Core Centronics"},
707 {HPHW_FIO, 0x02A, 0x00074, 0x0, "Electra Core Centronics"},
708 {HPHW_FIO, 0x02B, 0x00074, 0x0, "Mirage 80 Core Centronics"},
709 {HPHW_FIO, 0x02C, 0x00074, 0x0, "Mirage 100+ Core Centronics"},
710 {HPHW_FIO, 0x02E, 0x00074, 0x0, "UL 350 Core Centronics"},
711 {HPHW_FIO, 0x02F, 0x00074, 0x0, "UL 550 Core Centronics"},
712 {HPHW_FIO, 0x032, 0x00074, 0x0, "Raven T' Core Centronics"},
713 {HPHW_FIO, 0x033, 0x00074, 0x0, "Anole T Core Centronics"},
714 {HPHW_FIO, 0x034, 0x00074, 0x0, "SAIC L-80 Core Centronics"},
715 {HPHW_FIO, 0x035, 0x00074, 0x0, "PCX-L2 712/132 Core Centronics"},
716 {HPHW_FIO, 0x036, 0x00074, 0x0, "PCX-L2 712/160 Core Centronics"},
717 {HPHW_FIO, 0x03B, 0x00074, 0x0, "Raven U/L2 Core Centronics"},
718 {HPHW_FIO, 0x03C, 0x00074, 0x0, "Merlin 132 Core Centronics"},
719 {HPHW_FIO, 0x03D, 0x00074, 0x0, "Merlin 160 Core Centronics"},
720 {HPHW_FIO, 0x03E, 0x00074, 0x0, "Merlin+ 132 Core Centronics"},
721 {HPHW_FIO, 0x03F, 0x00074, 0x0, "Merlin+ 180 Core Centronics"},
722 {HPHW_FIO, 0x044, 0x00074, 0x0, "Mohawk Core Centronics"},
723 {HPHW_FIO, 0x045, 0x00074, 0x0, "Rocky1 Core Centronics"},
724 {HPHW_FIO, 0x046, 0x00074, 0x0, "Rocky2 120 Core Centronics"},
725 {HPHW_FIO, 0x047, 0x00074, 0x0, "Rocky2 150 Core Centronics"},
726 {HPHW_FIO, 0x04B, 0x00074, 0x0, "Anole L2 132 Core Centronics"},
727 {HPHW_FIO, 0x04D, 0x00074, 0x0, "Anole L2 165 Core Centronics"},
728 {HPHW_FIO, 0x050, 0x00074, 0x0, "Merlin Jr 132 Core Centronics"},
729 {HPHW_FIO, 0x051, 0x00074, 0x0, "Firehawk Core Centronics"},
730 {HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ w SE FWSCSI Core Centronics"},
731 {HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ w Diff FWSCSI Core Centronics"},
732 {HPHW_FIO, 0x058, 0x00074, 0x0, "FireHawk 200 Core Centronics"},
733 {HPHW_FIO, 0x05C, 0x00074, 0x0, "SummitHawk 230 Core Centronics"},
734 {HPHW_FIO, 0x800, 0x00074, 0x0, "Hitachi Tiny 64 Core Centronics"},
735 {HPHW_FIO, 0x801, 0x00074, 0x0, "Hitachi Tiny 80 Core Centronics"},
736 {HPHW_FIO, 0x004, 0x00075, 0x0, "Cobra Core RS-232"},
737 {HPHW_FIO, 0x005, 0x00075, 0x0, "Coral Core RS-232"},
738 {HPHW_FIO, 0x006, 0x00075, 0x0, "Bushmaster Core RS-232"},
739 {HPHW_FIO, 0x007, 0x00075, 0x0, "Scorpio Core RS-232"},
740 {HPHW_FIO, 0x008, 0x00075, 0x0, "Flounder Core RS-232"},
741 {HPHW_FIO, 0x009, 0x00075, 0x0, "Outfield Core RS-232"},
742 {HPHW_FIO, 0x00A, 0x00075, 0x0, "CoralII Core RS-232"},
743 {HPHW_FIO, 0x00B, 0x00075, 0x0, "Scorpio Jr. Core RS-232"},
744 {HPHW_FIO, 0x00C, 0x00075, 0x0, "Strider-50 Core RS-232"},
745 {HPHW_FIO, 0x00D, 0x00075, 0x0, "Strider-33 Core RS-232"},
746 {HPHW_FIO, 0x00E, 0x00075, 0x0, "Trailways-50 Core RS-232"},
747 {HPHW_FIO, 0x00F, 0x00075, 0x0, "Trailways-33 Core RS-232"},
748 {HPHW_FIO, 0x010, 0x00075, 0x0, "Pace Core RS-232"},
749 {HPHW_FIO, 0x011, 0x00075, 0x0, "Sidewinder Core RS-232"},
750 {HPHW_FIO, 0x019, 0x00075, 0x0, "Scorpio Sr. Core RS-232"},
751 {HPHW_FIO, 0x020, 0x00075, 0x0, "Scorpio 100 Core RS-232"},
752 {HPHW_FIO, 0x021, 0x00075, 0x0, "Spectra 50 Core RS-232"},
753 {HPHW_FIO, 0x022, 0x00075, 0x0, "Spectra 75 Core RS-232"},
754 {HPHW_FIO, 0x023, 0x00075, 0x0, "Spectra 100 Core RS-232"},
755 {HPHW_FIO, 0x024, 0x00075, 0x0, "Fast Pace Core RS-232"},
756 {HPHW_FIO, 0x026, 0x00075, 0x0, "CoralII Jaguar Core RS-232"},
757 {HPHW_FIO, 0x004, 0x00077, 0x0, "Coral SGC Graphics"},
758 {HPHW_FIO, 0x005, 0x00077, 0x0, "Hyperdrive Optional Graphics"},
759 {HPHW_FIO, 0x006, 0x00077, 0x0, "Stinger Optional Graphics"},
760 {HPHW_FIO, 0x007, 0x00077, 0x0, "Scorpio Builtin Graphics"},
761 {HPHW_FIO, 0x008, 0x00077, 0x0, "Anole Hyperdrive Optional Graphics"},
762 {HPHW_FIO, 0x009, 0x00077, 0x0, "Thunder II graphics EISA form"},
763 {HPHW_FIO, 0x00A, 0x00077, 0x0, "Thunder II graphics GSA form"},
764 {HPHW_FIO, 0x00B, 0x00077, 0x0, "Scorpio Jr Builtin Graphics"},
765 {HPHW_FIO, 0x00C, 0x00077, 0x0, "Strider-50 SSC Graphics"},
766 {HPHW_FIO, 0x00D, 0x00077, 0x0, "Strider-33 SSC Graphics"},
767 {HPHW_FIO, 0x00E, 0x00077, 0x0, "Trailways-50 SSC Graphics"},
768 {HPHW_FIO, 0x00F, 0x00077, 0x0, "Trailways-33 SSC Graphics"},
769 {HPHW_FIO, 0x010, 0x00077, 0x0, "Pace SGC Graphics"},
770 {HPHW_FIO, 0x011, 0x00077, 0x0, "Mohawk Opt. 2D Graphics (Kid)"},
771 {HPHW_FIO, 0x012, 0x00077, 0x0, "Raven Opt. 2D Graphics (Goat)"},
772 {HPHW_FIO, 0x016, 0x00077, 0x0, "Lego 24 SCG Graphics"},
773 {HPHW_FIO, 0x017, 0x00077, 0x0, "Lego 24Z SCG Graphics"},
774 {HPHW_FIO, 0x018, 0x00077, 0x0, "Lego 48Z SCG Graphics"},
775 {HPHW_FIO, 0x019, 0x00077, 0x0, "Scorpio Sr Builtin Graphics"},
776 {HPHW_FIO, 0x020, 0x00077, 0x0, "Scorpio 100 Builtin Graphics"},
777 {HPHW_FIO, 0x021, 0x00077, 0x0, "Spectra 50 Builtin Graphics"},
778 {HPHW_FIO, 0x022, 0x00077, 0x0, "Spectra 75 Builtin Graphics"},
779 {HPHW_FIO, 0x023, 0x00077, 0x0, "Spectra 100 Builtin Graphics"},
780 {HPHW_FIO, 0x024, 0x00077, 0x0, "Fast Pace SGC Graphics"},
781 {HPHW_FIO, 0x006, 0x0007A, 0x0, "Bushmaster Audio"},
782 {HPHW_FIO, 0x008, 0x0007A, 0x0, "Flounder Audio"},
783 {HPHW_FIO, 0x004, 0x0007B, 0x0, "UL Optional Audio"},
784 {HPHW_FIO, 0x007, 0x0007B, 0x0, "Scorpio Audio"},
785 {HPHW_FIO, 0x00B, 0x0007B, 0x0, "Scorpio Jr. Audio"},
786 {HPHW_FIO, 0x00C, 0x0007B, 0x0, "Strider-50 Audio"},
787 {HPHW_FIO, 0x00D, 0x0007B, 0x0, "Strider-33 Audio"},
788 {HPHW_FIO, 0x00E, 0x0007B, 0x0, "Trailways-50 Audio"},
789 {HPHW_FIO, 0x00F, 0x0007B, 0x0, "Trailways-33 Audio"},
790 {HPHW_FIO, 0x015, 0x0007B, 0x0, "KittyHawk GSY Core Audio"},
791 {HPHW_FIO, 0x016, 0x0007B, 0x0, "Gecko Audio"},
792 {HPHW_FIO, 0x019, 0x0007B, 0x0, "Scorpio Sr. Audio"},
793 {HPHW_FIO, 0x01A, 0x0007B, 0x0, "Anole 64 Audio"},
794 {HPHW_FIO, 0x01B, 0x0007B, 0x0, "Anole 100 Audio"},
795 {HPHW_FIO, 0x01C, 0x0007B, 0x0, "Gecko 80 Audio"},
796 {HPHW_FIO, 0x01D, 0x0007B, 0x0, "Gecko 100 Audio"},
797 {HPHW_FIO, 0x01F, 0x0007B, 0x0, "SkyHawk 100/120 Audio"},
798 {HPHW_FIO, 0x020, 0x0007B, 0x0, "Scorpio 100 Audio"},
799 {HPHW_FIO, 0x021, 0x0007B, 0x0, "Spectra 50 Audio"},
800 {HPHW_FIO, 0x022, 0x0007B, 0x0, "Spectra 75 Audio"},
801 {HPHW_FIO, 0x023, 0x0007B, 0x0, "Spectra 100 Audio"},
802 {HPHW_FIO, 0x028, 0x0007B, 0x0, "Mirage Jr Audio"},
803 {HPHW_FIO, 0x029, 0x0007B, 0x0, "Mirage Audio"},
804 {HPHW_FIO, 0x02A, 0x0007B, 0x0, "Electra Audio"},
805 {HPHW_FIO, 0x02B, 0x0007B, 0x0, "Mirage 80 Audio"},
806 {HPHW_FIO, 0x02C, 0x0007B, 0x0, "Mirage 100+ Audio"},
807 {HPHW_FIO, 0x032, 0x0007B, 0x0, "Raven T' Audio"},
808 {HPHW_FIO, 0x034, 0x0007B, 0x0, "SAIC L-80 Audio"},
809 {HPHW_FIO, 0x035, 0x0007B, 0x0, "PCX-L2 712/132 Core Audio"},
810 {HPHW_FIO, 0x036, 0x0007B, 0x0, "PCX-L2 712/160 Core Audio"},
811 {HPHW_FIO, 0x03B, 0x0007B, 0x0, "Raven U/L2 Core Audio"},
812 {HPHW_FIO, 0x03C, 0x0007B, 0x0, "Merlin 132 Core Audio"},
813 {HPHW_FIO, 0x03D, 0x0007B, 0x0, "Merlin 160 Core Audio"},
814 {HPHW_FIO, 0x03E, 0x0007B, 0x0, "Merlin+ 132 Core Audio"},
815 {HPHW_FIO, 0x03F, 0x0007B, 0x0, "Merlin+ 180 Core Audio"},
816 {HPHW_FIO, 0x044, 0x0007B, 0x0, "Mohawk Core Audio"},
817 {HPHW_FIO, 0x046, 0x0007B, 0x0, "Rocky2 120 Core Audio"},
818 {HPHW_FIO, 0x047, 0x0007B, 0x0, "Rocky2 150 Core Audio"},
819 {HPHW_FIO, 0x04B, 0x0007B, 0x0, "Anole L2 132 Core Audio"},
820 {HPHW_FIO, 0x04D, 0x0007B, 0x0, "Anole L2 165 Core Audio"},
821 {HPHW_FIO, 0x04E, 0x0007B, 0x0, "Kiji L2 132 Core Audio"},
822 {HPHW_FIO, 0x050, 0x0007B, 0x0, "Merlin Jr 132 Core Audio"},
823 {HPHW_FIO, 0x051, 0x0007B, 0x0, "Firehawk Audio"},
824 {HPHW_FIO, 0x056, 0x0007B, 0x0, "Raven+ w SE FWSCSI Core Audio"},
825 {HPHW_FIO, 0x057, 0x0007B, 0x0, "Raven+ w Diff FWSCSI Core Audio"},
826 {HPHW_FIO, 0x058, 0x0007B, 0x0, "FireHawk 200 Audio"},
827 {HPHW_FIO, 0x05C, 0x0007B, 0x0, "SummitHawk 230 Core Audio"},
828 {HPHW_FIO, 0x800, 0x0007B, 0x0, "Hitachi Tiny 64 Audio"},
829 {HPHW_FIO, 0x801, 0x0007B, 0x0, "Hitachi Tiny 80 Audio"},
830 {HPHW_FIO, 0x009, 0x0007C, 0x0, "Outfield FW SCSI"},
831 {HPHW_FIO, 0x00A, 0x0007C, 0x0, "CoralII FW SCSI"},
832 {HPHW_FIO, 0x026, 0x0007C, 0x0, "CoralII Jaguar FW SCSI"},
833 {HPHW_FIO, 0x009, 0x0007D, 0x0, "Outfield FDDI"},
834 {HPHW_FIO, 0x00A, 0x0007D, 0x0, "CoralII FDDI"},
835 {HPHW_FIO, 0x026, 0x0007D, 0x0, "CoralII Jaguar FDDI"},
836 {HPHW_FIO, 0x010, 0x0007E, 0x0, "Pace Audio"},
837 {HPHW_FIO, 0x024, 0x0007E, 0x0, "Fast Pace Audio"},
838 {HPHW_FIO, 0x009, 0x0007F, 0x0, "Outfield Audio"},
839 {HPHW_FIO, 0x00A, 0x0007F, 0x0, "CoralII Audio"},
840 {HPHW_FIO, 0x026, 0x0007F, 0x0, "CoralII Jaguar Audio"},
841 {HPHW_FIO, 0x010, 0x00080, 0x0, "Pace Core HPIB"},
842 {HPHW_FIO, 0x024, 0x00080, 0x0, "Fast Pace Core HPIB"},
843 {HPHW_FIO, 0x015, 0x00082, 0x0, "KittyHawk GSY Core SCSI"},
844 {HPHW_FIO, 0x016, 0x00082, 0x0, "Gecko Core SCSI"},
845 {HPHW_FIO, 0x01A, 0x00082, 0x0, "Anole 64 Core SCSI"},
846 {HPHW_FIO, 0x01B, 0x00082, 0x0, "Anole 100 Core SCSI"},
847 {HPHW_FIO, 0x01C, 0x00082, 0x0, "Gecko 80 Core SCSI"},
848 {HPHW_FIO, 0x01D, 0x00082, 0x0, "Gecko 100 Core SCSI"},
849 {HPHW_FIO, 0x01F, 0x00082, 0x0, "SkyHawk 100/120 Core SCSI"},
850 {HPHW_FIO, 0x027, 0x00082, 0x0, "Piranha 100 Core SCSI"},
851 {HPHW_FIO, 0x028, 0x00082, 0x0, "Mirage Jr Core SCSI"},
852 {HPHW_FIO, 0x029, 0x00082, 0x0, "Mirage Core SCSI"},
853 {HPHW_FIO, 0x02A, 0x00082, 0x0, "Electra Core SCSI"},
854 {HPHW_FIO, 0x02B, 0x00082, 0x0, "Mirage 80 Core SCSI"},
855 {HPHW_FIO, 0x02C, 0x00082, 0x0, "Mirage 100+ Core SCSI"},
856 {HPHW_FIO, 0x02E, 0x00082, 0x0, "UL 350 Core SCSI"},
857 {HPHW_FIO, 0x02F, 0x00082, 0x0, "UL 550 Core SCSI"},
858 {HPHW_FIO, 0x032, 0x00082, 0x0, "Raven T' Core SCSI"},
859 {HPHW_FIO, 0x033, 0x00082, 0x0, "Anole T Core SCSI"},
860 {HPHW_FIO, 0x034, 0x00082, 0x0, "SAIC L-80 Core SCSI"},
861 {HPHW_FIO, 0x035, 0x00082, 0x0, "PCX-L2 712/132 Core SCSI"},
862 {HPHW_FIO, 0x036, 0x00082, 0x0, "PCX-L2 712/160 Core SCSI"},
863 {HPHW_FIO, 0x03B, 0x00082, 0x0, "Raven U/L2 Core SCSI"},
864 {HPHW_FIO, 0x03C, 0x00082, 0x0, "Merlin 132 Core SCSI"},
865 {HPHW_FIO, 0x03D, 0x00082, 0x0, "Merlin 160 Core SCSI"},
866 {HPHW_FIO, 0x03E, 0x00082, 0x0, "Merlin+ 132 Core SCSI"},
867 {HPHW_FIO, 0x03F, 0x00082, 0x0, "Merlin+ 180 Core SCSI"},
868 {HPHW_FIO, 0x044, 0x00082, 0x0, "Mohawk Core SCSI"},
869 {HPHW_FIO, 0x045, 0x00082, 0x0, "Rocky1 Core SCSI"},
870 {HPHW_FIO, 0x046, 0x00082, 0x0, "Rocky2 120 Core SCSI"},
871 {HPHW_FIO, 0x047, 0x00082, 0x0, "Rocky2 150 Core SCSI"},
872 {HPHW_FIO, 0x04B, 0x00082, 0x0, "Anole L2 132 Core SCSI"},
873 {HPHW_FIO, 0x04D, 0x00082, 0x0, "Anole L2 165 Core SCSI"},
874 {HPHW_FIO, 0x04E, 0x00082, 0x0, "Kiji L2 132 Core SCSI"},
875 {HPHW_FIO, 0x050, 0x00082, 0x0, "Merlin Jr 132 Core SCSI"},
876 {HPHW_FIO, 0x051, 0x00082, 0x0, "Firehawk Core SCSI"},
877 {HPHW_FIO, 0x056, 0x00082, 0x0, "Raven+ w SE FWSCSI Core SCSI"},
878 {HPHW_FIO, 0x057, 0x00082, 0x0, "Raven+ w Diff FWSCSI Core SCSI"},
879 {HPHW_FIO, 0x058, 0x00082, 0x0, "FireHawk 200 Core SCSI"},
880 {HPHW_FIO, 0x05C, 0x00082, 0x0, "SummitHawk 230 Core SCSI"},
881 {HPHW_FIO, 0x05E, 0x00082, 0x0, "Staccato 132 Core SCSI"},
882 {HPHW_FIO, 0x05F, 0x00082, 0x0, "Staccato 180 Core SCSI"},
883 {HPHW_FIO, 0x800, 0x00082, 0x0, "Hitachi Tiny 64 Core SCSI"},
884 {HPHW_FIO, 0x801, 0x00082, 0x0, "Hitachi Tiny 80 Core SCSI"},
885 {HPHW_FIO, 0x016, 0x00083, 0x0, "Gecko Core PC Floppy"},
886 {HPHW_FIO, 0x01C, 0x00083, 0x0, "Gecko 80 Core PC Floppy"},
887 {HPHW_FIO, 0x01D, 0x00083, 0x0, "Gecko 100 Core PC Floppy"},
888 {HPHW_FIO, 0x051, 0x00083, 0x0, "Firehawk Core PC Floppy"},
889 {HPHW_FIO, 0x058, 0x00083, 0x0, "FireHawk 200 Core PC Floppy"},
890 {HPHW_FIO, 0x027, 0x00083, 0x0, "Piranha 100 Core PC Floppy"},
891 {HPHW_FIO, 0x028, 0x00083, 0x0, "Mirage Jr Core PC Floppy"},
892 {HPHW_FIO, 0x029, 0x00083, 0x0, "Mirage Core PC Floppy"},
893 {HPHW_FIO, 0x02A, 0x00083, 0x0, "Electra Core PC Floppy"},
894 {HPHW_FIO, 0x02B, 0x00083, 0x0, "Mirage 80 Core PC Floppy"},
895 {HPHW_FIO, 0x02C, 0x00083, 0x0, "Mirage 100+ Core PC Floppy"},
896 {HPHW_FIO, 0x02E, 0x00083, 0x0, "UL 350 Core PC Floppy"},
897 {HPHW_FIO, 0x02F, 0x00083, 0x0, "UL 550 Core PC Floppy"},
898 {HPHW_FIO, 0x032, 0x00083, 0x0, "Raven T' Core PC Floppy"},
899 {HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floppy"},
900 {HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floppy"},
901 {HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floppy"},
902 {HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floppy"},
903 {HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floppy"},
904 {HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floppy"},
905 {HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floppy"},
906 {HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floppy"},
907 {HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floppy"},
908 {HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floppy"},
909 {HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floppy"},
910 {HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floppy"},
911 {HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floppy"},
912 {HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floppy"},
913 {HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floppy"},
914 {HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floppy"},
915 {HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floppy"},
916 {HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PS/2 Port"},
917 {HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PS/2 Port"},
918 {HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PS/2 Port"},
919 {HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PS/2 Port"},
920 {HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PS/2 Port"},
921 {HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PS/2 Port"},
922 {HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PS/2 Port"},
923 {HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PS/2 Port"},
924 {HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PS/2 Port"},
925 {HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PS/2 Port"},
926 {HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PS/2 Port"},
927 {HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PS/2 Port"},
928 {HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PS/2 Port"},
929 {HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PS/2 Port"},
930 {HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PS/2 Port"},
931 {HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PS/2 Port"},
932 {HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PS/2 Port"},
933 {HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PS/2 Port"},
934 {HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PS/2 Port"},
935 {HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core PS/2 Port"},
936 {HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core PS/2 Port"},
937 {HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PS/2 Port"},
938 {HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PS/2 Port"},
939 {HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PS/2 Port"},
940 {HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PS/2 Port"},
941 {HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PS/2 Port"},
942 {HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PS/2 Port"},
943 {HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PS/2 Port"},
944 {HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PS/2 Port"},
945 {HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PS/2 Port"},
946 {HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PS/2 Port"},
947 {HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PS/2 Port"},
948 {HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PS/2 Port"},
949 {HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PS/2 Port"},
950 {HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PS/2 Port"},
951 {HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PS/2 Port"},
952 {HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PS/2 Port"},
953 {HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PS/2 Port"},
954 {HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PS/2 Port"},
955 {HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PS/2 Port"},
956 {HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PS/2 Port"},
957 {HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PS/2 Port"},
958 {HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PS/2 Port"},
959 {HPHW_FIO, 0x004, 0x00085, 0x0, "Solo GSC Optional Graphics"},
960 {HPHW_FIO, 0x005, 0x00085, 0x0, "Duet GSC Optional Graphics"},
961 {HPHW_FIO, 0x008, 0x00085, 0x0, "Anole Artist Optional Graphics"},
962 {HPHW_FIO, 0x010, 0x00085, 0x0, "Mirage 80 GSC Builtin Graphics"},
963 {HPHW_FIO, 0x011, 0x00085, 0x0, "Mirage 100+ GSC Builtin Graphics"},
964 {HPHW_FIO, 0x012, 0x00085, 0x0, "Mirage Jr GSC Builtin Graphics"},
965 {HPHW_FIO, 0x013, 0x00085, 0x0, "Mirage GSC Builtin Graphics"},
966 {HPHW_FIO, 0x014, 0x00085, 0x0, "Electra GSC Builtin Graphics"},
967 {HPHW_FIO, 0x016, 0x00085, 0x0, "Gecko GSC Core Graphics"},
968 {HPHW_FIO, 0x017, 0x00085, 0x0, "Gecko GSC Optional Graphics"},
969 {HPHW_FIO, 0x01A, 0x00085, 0x0, "Anole 64 Artist Builtin Graphics"},
970 {HPHW_FIO, 0x01B, 0x00085, 0x0, "Anole 100 Artist Builtin Graphics"},
971 {HPHW_FIO, 0x01C, 0x00085, 0x0, "Gecko 80 GSC Core Graphics"},
972 {HPHW_FIO, 0x01D, 0x00085, 0x0, "Gecko 100 GSC Core Graphics"},
973 {HPHW_FIO, 0x032, 0x00085, 0x0, "Raven T' GSC Core Graphics"},
974 {HPHW_FIO, 0x033, 0x00085, 0x0, "Anole T Artist Builtin Graphics"},
975 {HPHW_FIO, 0x034, 0x00085, 0x0, "SAIC L-80 GSC Core Graphics"},
976 {HPHW_FIO, 0x035, 0x00085, 0x0, "PCX-L2 712/132 Core Graphics"},
977 {HPHW_FIO, 0x036, 0x00085, 0x0, "PCX-L2 712/160 Core Graphics"},
978 {HPHW_FIO, 0x03B, 0x00085, 0x0, "Raven U/L2 Core Graphics"},
979 {HPHW_FIO, 0x03C, 0x00085, 0x0, "Merlin 132 Core Graphics"},
980 {HPHW_FIO, 0x03D, 0x00085, 0x0, "Merlin 160 Core Graphics"},
981 {HPHW_FIO, 0x03E, 0x00085, 0x0, "Merlin+ 132 Core Graphics"},
982 {HPHW_FIO, 0x03F, 0x00085, 0x0, "Merlin+ 180 Core Graphics"},
983 {HPHW_FIO, 0x045, 0x00085, 0x0, "Rocky1 Core Graphics"},
984 {HPHW_FIO, 0x046, 0x00085, 0x0, "Rocky2 120 Core Graphics"},
985 {HPHW_FIO, 0x047, 0x00085, 0x0, "Rocky2 150 Core Graphics"},
986 {HPHW_FIO, 0x04B, 0x00085, 0x0, "Anole L2 132 Core Graphics"},
987 {HPHW_FIO, 0x04D, 0x00085, 0x0, "Anole L2 165 Core Graphics"},
988 {HPHW_FIO, 0x04E, 0x00085, 0x0, "Kiji L2 132 Core Graphics"},
989 {HPHW_FIO, 0x050, 0x00085, 0x0, "Merlin Jr 132 Core Graphics"},
990 {HPHW_FIO, 0x056, 0x00085, 0x0, "Raven+ w SE FWSCSI Core Graphics"},
991 {HPHW_FIO, 0x057, 0x00085, 0x0, "Raven+ w Diff FWSCSI Core Graphics"},
992 {HPHW_FIO, 0x800, 0x00085, 0x0, "Hitachi Tiny 64 Core Graphics"},
993 {HPHW_FIO, 0x801, 0x00085, 0x0, "Hitachi Tiny 80 Core Graphics"},
994 {HPHW_FIO, 0x004, 0x00086, 0x0, "GSC IBM Token Ring"},
995 {HPHW_FIO, 0x015, 0x00087, 0x0, "Gecko Optional ISDN"},
996 {HPHW_FIO, 0x016, 0x00087, 0x0, "Gecko Core ISDN"},
997 {HPHW_FIO, 0x01C, 0x00087, 0x0, "Gecko 80 Core ISDN"},
998 {HPHW_FIO, 0x01D, 0x00087, 0x0, "Gecko 100 Core ISDN"},
999 {HPHW_FIO, 0x010, 0x00088, 0x0, "Pace VME Networking"},
1000 {HPHW_FIO, 0x011, 0x00088, 0x0, "Sidewinder VME Networking"},
1001 {HPHW_FIO, 0x01A, 0x00088, 0x0, "Anole 64 VME Networking"},
1002 {HPHW_FIO, 0x01B, 0x00088, 0x0, "Anole 100 VME Networking"},
1003 {HPHW_FIO, 0x024, 0x00088, 0x0, "Fast Pace VME Networking"},
1004 {HPHW_FIO, 0x034, 0x00088, 0x0, "Anole T VME Networking"},
1005 {HPHW_FIO, 0x04A, 0x00088, 0x0, "Anole L2 132 VME Networking"},
1006 {HPHW_FIO, 0x04C, 0x00088, 0x0, "Anole L2 165 VME Networking"},
1007 {HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core LAN (802.3)"},
1008 {HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core LAN (802.3)"},
1009 {HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core LAN (802.3)"},
1010 {HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core LAN (802.3)"},
1011 {HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core LAN (802.3)"},
1012 {HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core LAN (802.3)"},
1013 {HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional LAN (802.3)"},
1014 {HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core LAN (802.3)"},
1015 {HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core LAN (802.3)"},
1016 {HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core LAN (802.3)"},
1017 {HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core LAN (802.3)"},
1018 {HPHW_FIO, 0x01F, 0x0008A, 0x0, "SkyHawk 100/120 Core LAN (802.3)"},
1019 {HPHW_FIO, 0x027, 0x0008A, 0x0, "Piranha 100 Core LAN (802.3)"},
1020 {HPHW_FIO, 0x028, 0x0008A, 0x0, "Mirage Jr Core LAN (802.3)"},
1021 {HPHW_FIO, 0x029, 0x0008A, 0x0, "Mirage Core LAN (802.3)"},
1022 {HPHW_FIO, 0x02A, 0x0008A, 0x0, "Electra Core LAN (802.3)"},
1023 {HPHW_FIO, 0x02B, 0x0008A, 0x0, "Mirage 80 Core LAN (802.3)"},
1024 {HPHW_FIO, 0x02C, 0x0008A, 0x0, "Mirage 100+ Core LAN (802.3)"},
1025 {HPHW_FIO, 0x02E, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"},
1026 {HPHW_FIO, 0x02F, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"},
1027 {HPHW_FIO, 0x032, 0x0008A, 0x0, "Raven T' Core LAN (802.3)"},
1028 {HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core LAN (802.3)"},
1029 {HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core LAN (802.3)"},
1030 {HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core LAN (802.3)"},
1031 {HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core LAN (802.3)"},
1032 {HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core LAN (802.3)"},
1033 {HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core LAN (802.3)"},
1034 {HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core LAN (802.3)"},
1035 {HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core LAN (802.3)"},
1036 {HPHW_FIO, 0x045, 0x0008A, 0x0, "Rocky1 Core LAN (802.3)"},
1037 {HPHW_FIO, 0x046, 0x0008A, 0x0, "Rocky2 120 Core LAN (802.3)"},
1038 {HPHW_FIO, 0x047, 0x0008A, 0x0, "Rocky2 150 Core LAN (802.3)"},
1039 {HPHW_FIO, 0x04B, 0x0008A, 0x0, "Anole L2 132 Core LAN (802.3)"},
1040 {HPHW_FIO, 0x04D, 0x0008A, 0x0, "Anole L2 165 Core LAN (802.3)"},
1041 {HPHW_FIO, 0x04E, 0x0008A, 0x0, "Kiji L2 132 Core LAN (802.3)"},
1042 {HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core LAN (802.3)"},
1043 {HPHW_FIO, 0x058, 0x0008A, 0x0, "FireHawk 200 Core LAN (802.3)"},
1044 {HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core LAN (802.3)"},
1045 {HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core LAN (802.3)"},
1046 {HPHW_FIO, 0x004, 0x0008C, 0x0, "SkyHawk 100/120 Wax RS-232"},
1047 {HPHW_FIO, 0x005, 0x0008C, 0x0, "SAIC L-80 Wax RS-232"},
1048 {HPHW_FIO, 0x006, 0x0008C, 0x0, "Raven U/L2 Dino RS-232"},
1049 {HPHW_FIO, 0x007, 0x0008C, 0x0, "Dino RS-232"},
1050 {HPHW_FIO, 0x008, 0x0008C, 0x0, "Merlin 132 Dino RS-232"},
1051 {HPHW_FIO, 0x009, 0x0008C, 0x0, "Merlin 160 Dino RS-232"},
1052 {HPHW_FIO, 0x00A, 0x0008C, 0x0, "Merlin Jr 132 Dino RS-232"},
1053 {HPHW_FIO, 0x010, 0x0008C, 0x0, "Mirage 80 Wax RS-232"},
1054 {HPHW_FIO, 0x011, 0x0008C, 0x0, "Mirage 100+ Wax RS-232"},
1055 {HPHW_FIO, 0x012, 0x0008C, 0x0, "Mirage Jr Wax RS-232"},
1056 {HPHW_FIO, 0x013, 0x0008C, 0x0, "Mirage Wax RS-232"},
1057 {HPHW_FIO, 0x014, 0x0008C, 0x0, "Electra Wax RS-232"},
1058 {HPHW_FIO, 0x015, 0x0008C, 0x0, "KittyHawk GSY Core RS-232"},
1059 {HPHW_FIO, 0x016, 0x0008C, 0x0, "Gecko Core RS-232"},
1060 {HPHW_FIO, 0x017, 0x0008C, 0x0, "Raven Backplane RS-232"},
1061 {HPHW_FIO, 0x018, 0x0008C, 0x0, "Gecko Optional RS-232"},
1062 {HPHW_FIO, 0x019, 0x0008C, 0x0, "Merlin+ 180 Dino RS-232"},
1063 {HPHW_FIO, 0x01A, 0x0008C, 0x0, "Anole 64 Core RS-232"},
1064 {HPHW_FIO, 0x01B, 0x0008C, 0x0, "Anole 100 Core RS-232"},
1065 {HPHW_FIO, 0x01C, 0x0008C, 0x0, "Gecko 80 Core RS-232"},
1066 {HPHW_FIO, 0x01D, 0x0008C, 0x0, "Gecko 100 Core RS-232"},
1067 {HPHW_FIO, 0x01E, 0x0008C, 0x0, "Raven T' Wax RS-232"},
1068 {HPHW_FIO, 0x01F, 0x0008C, 0x0, "SkyHawk 100/120 Core RS-232"},
1069 {HPHW_FIO, 0x020, 0x0008C, 0x0, "Anole 64 Timi RS-232"},
1070 {HPHW_FIO, 0x021, 0x0008C, 0x0, "Anole 100 Timi RS-232"},
1071 {HPHW_FIO, 0x022, 0x0008C, 0x0, "Merlin+ 132 Dino RS-232"},
1072 {HPHW_FIO, 0x023, 0x0008C, 0x0, "Rocky1 Wax RS-232"},
1073 {HPHW_FIO, 0x025, 0x0008C, 0x0, "Armyknife Optional RS-232"},
1074 {HPHW_FIO, 0x026, 0x0008C, 0x0, "Piranha 100 Wax RS-232"},
1075 {HPHW_FIO, 0x027, 0x0008C, 0x0, "Piranha 100 Core RS-232"},
1076 {HPHW_FIO, 0x028, 0x0008C, 0x0, "Mirage Jr Core RS-232"},
1077 {HPHW_FIO, 0x029, 0x0008C, 0x0, "Mirage Core RS-232"},
1078 {HPHW_FIO, 0x02A, 0x0008C, 0x0, "Electra Core RS-232"},
1079 {HPHW_FIO, 0x02B, 0x0008C, 0x0, "Mirage 80 Core RS-232"},
1080 {HPHW_FIO, 0x02C, 0x0008C, 0x0, "Mirage 100+ Core RS-232"},
1081 {HPHW_FIO, 0x02E, 0x0008C, 0x0, "UL 350 Lasi Core RS-232"},
1082 {HPHW_FIO, 0x02F, 0x0008C, 0x0, "UL 550 Lasi Core RS-232"},
1083 {HPHW_FIO, 0x030, 0x0008C, 0x0, "UL 350 Wax Core RS-232"},
1084 {HPHW_FIO, 0x031, 0x0008C, 0x0, "UL 550 Wax Core RS-232"},
1085 {HPHW_FIO, 0x032, 0x0008C, 0x0, "Raven T' Lasi Core RS-232"},
1086 {HPHW_FIO, 0x033, 0x0008C, 0x0, "Anole T Core RS-232"},
1087 {HPHW_FIO, 0x034, 0x0008C, 0x0, "SAIC L-80 Core RS-232"},
1088 {HPHW_FIO, 0x035, 0x0008C, 0x0, "PCX-L2 712/132 Core RS-232"},
1089 {HPHW_FIO, 0x036, 0x0008C, 0x0, "PCX-L2 712/160 Core RS-232"},
1090 {HPHW_FIO, 0x03A, 0x0008C, 0x0, "Merlin+ Wax RS-232"},
1091 {HPHW_FIO, 0x03B, 0x0008C, 0x0, "Raven U/L2 Core RS-232"},
1092 {HPHW_FIO, 0x03C, 0x0008C, 0x0, "Merlin 132 Core RS-232"},
1093 {HPHW_FIO, 0x03D, 0x0008C, 0x0, "Merlin 160 Core RS-232"},
1094 {HPHW_FIO, 0x03E, 0x0008C, 0x0, "Merlin+ 132 Core RS-232"},
1095 {HPHW_FIO, 0x03F, 0x0008C, 0x0, "Merlin+ 180 Core RS-232"},
1096 {HPHW_FIO, 0x040, 0x0008C, 0x0, "Merlin 132 Wax RS-232"},
1097 {HPHW_FIO, 0x041, 0x0008C, 0x0, "Merlin 160 Wax RS-232"},
1098 {HPHW_FIO, 0x043, 0x0008C, 0x0, "Merlin 132/160 Wax RS-232"},
1099 {HPHW_FIO, 0x044, 0x0008C, 0x0, "Mohawk Core RS-232"},
1100 {HPHW_FIO, 0x045, 0x0008C, 0x0, "Rocky1 Core RS-232"},
1101 {HPHW_FIO, 0x046, 0x0008C, 0x0, "Rocky2 120 Core RS-232"},
1102 {HPHW_FIO, 0x047, 0x0008C, 0x0, "Rocky2 150 Core RS-232"},
1103 {HPHW_FIO, 0x048, 0x0008C, 0x0, "Rocky2 120 Dino RS-232"},
1104 {HPHW_FIO, 0x049, 0x0008C, 0x0, "Rocky2 150 Dino RS-232"},
1105 {HPHW_FIO, 0x04A, 0x0008C, 0x0, "Anole L2 132 TIMI RS-232"},
1106 {HPHW_FIO, 0x04B, 0x0008C, 0x0, "Anole L2 l32 Core RS-232"},
1107 {HPHW_FIO, 0x04C, 0x0008D, 0x0, "Anole L2 165 TIMI RS-232"},
1108 {HPHW_FIO, 0x04D, 0x0008C, 0x0, "Anole L2 165 Core RS-232"},
1109 {HPHW_FIO, 0x04E, 0x0008C, 0x0, "Kiji L2 132 Core RS-232"},
1110 {HPHW_FIO, 0x04F, 0x0008C, 0x0, "Kiji L2 132 Dino RS-232"},
1111 {HPHW_FIO, 0x050, 0x0008C, 0x0, "Merlin Jr 132 Core RS-232"},
1112 {HPHW_FIO, 0x051, 0x0008C, 0x0, "Firehawk Core RS-232"},
1113 {HPHW_FIO, 0x052, 0x0008C, 0x0, "Raven+ Hi Power Backplane w EISA RS-232"},
1114 {HPHW_FIO, 0x053, 0x0008C, 0x0, "Raven+ Hi Power Backplane w/o EISA RS-232"},
1115 {HPHW_FIO, 0x054, 0x0008C, 0x0, "Raven+ Lo Power Backplane w EISA RS-232"},
1116 {HPHW_FIO, 0x055, 0x0008C, 0x0, "Raven+ Lo Power Backplane w/o EISA RS-232"},
1117 {HPHW_FIO, 0x056, 0x0008C, 0x0, "Raven+ w SE FWSCSI Core RS-232"},
1118 {HPHW_FIO, 0x057, 0x0008C, 0x0, "Raven+ w Diff FWSCSI Core RS-232"},
1119 {HPHW_FIO, 0x058, 0x0008C, 0x0, "FireHawk 200 Core RS-232"},
1120 {HPHW_FIO, 0x059, 0x0008C, 0x0, "FireHawk 200 Wax RS-232"},
1121 {HPHW_FIO, 0x05A, 0x0008C, 0x0, "Raven+ L2 Backplane w EISA RS-232"},
1122 {HPHW_FIO, 0x05B, 0x0008C, 0x0, "Raven+ L2 Backplane w/o EISA RS-232"},
1123 {HPHW_FIO, 0x05D, 0x0008C, 0x0, "SummitHawk Dino RS-232"},
1124 {HPHW_FIO, 0x05E, 0x0008C, 0x0, "Staccato 132 Core LAN RS-232"},
1125 {HPHW_FIO, 0x05F, 0x0008C, 0x0, "Staccato 180 Core LAN RS-232"},
1126 {HPHW_FIO, 0x800, 0x0008C, 0x0, "Hitachi Tiny 64 Core RS-232"},
1127 {HPHW_FIO, 0x801, 0x0008C, 0x0, "Hitachi Tiny 80 Core RS-232"},
1128 {HPHW_FIO, 0x015, 0x0008D, 0x0, "Gecko Optional RJ-16"},
1129 {HPHW_FIO, 0x016, 0x0008D, 0x0, "Gecko Core RJ-16"},
1130 {HPHW_FIO, 0x01C, 0x0008D, 0x0, "Gecko 80 Core RJ-16"},
1131 {HPHW_FIO, 0x01D, 0x0008D, 0x0, "Gecko 100 Core RJ-16"},
1132 {HPHW_FIO, 0x004, 0x0008F, 0x0, "Anole Boot Rom"},
1133 {HPHW_FIO, 0x005, 0x0008F, 0x0, "Rocky1 Boot Rom"},
1134 {HPHW_FIO, 0x006, 0x0008F, 0x0, "Rocky2 120 Boot Rom"},
1135 {HPHW_FIO, 0x007, 0x0008F, 0x0, "Rocky2 150 Boot Rom"},
1136 {HPHW_FIO, 0x01B, 0x0008F, 0x0, "Anole 100 Boot Rom"},
1137 {HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS/2 Port"},
1138 {HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS/2 Port"},
1139 {HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS/2 Port"},
1140 {HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS/2 Port"},
1141 {HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS/2 Port"},
1142 {HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS/2 Port"},
1143 {HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS/2 Port"},
1144 {HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG LAN"},
1145 {HPHW_FIO, 0x023, 0x00099, 0x0, "Rocky1 Wax HPIB"},
1146 {HPHW_FIO, 0x048, 0x00099, 0x0, "Rocky2 120 Clark/Dino HPIB"},
1147 {HPHW_FIO, 0x049, 0x00099, 0x0, "Rocky2 150 Clark/Dino HPIB"},
1148 {HPHW_FIO, 0x004, 0x000A1, 0x0, "SPP2000 Console TTY"},
1149 {HPHW_FIO, 0x004, 0x000A2, 0x0, "Forte Core PCI 10/100BT LAN"},
1150 {HPHW_FIO, 0x005, 0x000A2, 0x0, "AllegroLow PCI 10/100BT LAN"},
1151 {HPHW_FIO, 0x006, 0x000A2, 0x0, "AllegroHIgh Core PCI 10/100BT LAN"},
1152 {HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in LAN"},
1153 {HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT LAN"},
1154 {HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI LAN"},
1155 {HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI LAN"},
1156 {HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI LAN"},
1157 {HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI LAN"},
1158 {HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI LAN"},
1159 {HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI LAN"},
1160 {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI LVD Ultra2 SCSI"},
1161 {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI SE UltraSCSI"},
1162 {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI IDE/ATAPI CD-ROM"},
1163 {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI LVD Ultra2 SCSI"},
1164 {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI IDE/ATAPI CD-ROM"},
1165 {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI LVD Ultra2 SCSI"},
1166 {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI IDE/ATAPI CD-ROM"},
1167 {HPHW_FIO, 0x007, 0x000A3, 0x0, "PCI Plug-in Disk"},
1168 {HPHW_FIO, 0x008, 0x000A3, 0x0, "A5158A S FC Tachlite HBA"},
1169 {HPHW_FIO, 0x009, 0x000A3, 0x0, "A5157A D FC HBA"},
1170 {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI LVD Ultra2 SCSI"},
1171 {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI NSE UltraSCSI"},
1172 {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI WSE UltraSCSI"},
1173 {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI IDE/ATAPI CD-ROM"},
1174 {HPHW_FIO, 0x03E, 0x000A3, 0x0, "Merlin+ 132 Core SE FWSCSI PCI Disk"},
1175 {HPHW_FIO, 0x03F, 0x000A3, 0x0, "Merlin+ 180 Core SE FWSCSI PCI Disk"},
1176 {HPHW_FIO, 0x056, 0x000A3, 0x0, "Raven+ w SE FWSCSI Core PCI Disk"},
1177 {HPHW_FIO, 0x057, 0x000A3, 0x0, "Raven+ w Diff FWSCSI Core PCI Disk"},
1178 {HPHW_FIO, 0x004, 0x000A4, 0x0, "SPP2000 Core BA"},
1179 {HPHW_FIO, 0x004, 0x000A6, 0x0, "Sonic Ethernet 802.3 Card"},
1180 {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI SuperIO RS-232"},
1181 {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI USB KB"},
1182 {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI SuperIO RS-232"},
1183 {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI USB KB"},
1184 {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI SuperIO RS-232"},
1185 {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI USB KB"},
1186 {HPHW_FIO, 0x007, 0x000A9, 0x0, "Miscelaneous PCI Plug-in"},
1187 {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI SuperIO RS-232"},
1188 {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI USB KB"},
1189 {HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"},
1190 {HPHW_FIO, 0x004, 0x00340, 0x0, "BARCO CX4500 VME Grphx Cnsl"},
1191 {HPHW_FIO, 0x004, 0x00360, 0x0, "Hughes TOG VME FDDI"},
1192 {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"},
1193 {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"},
1194 {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"},
1195 {HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"},
1196 {HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"},
1197 {HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"},
1198 {HPHW_IOA, 0x880, 0x0000C, 0x10, "Pluto BC McKinley Port"},
1199 {HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"},
1200 {HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"},
1201 {HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"},
1202 {HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"},
1203 {HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"},
1204 {HPHW_MEMORY, 0x0AF, 0x00009, 0x00, "Everest Mako Memory"},
1205 {HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"},
1206 {HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"},
1207 {HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"},
1208 {HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"},
1209 {HPHW_MC, 0x004, 0x000C0, 0x00, "BMC IPMI Mgmt Ctlr"},
1210 {HPHW_FAULTY, 0, } /* Special Marker for last entry */
1211};
1212
1213
1214static struct hp_cpu_type_mask {
1215 unsigned short model;
1216 unsigned short mask;
1217 enum cpu_type cpu;
1218} hp_cpu_type_mask_list[] __initdata = {
1219
1220 { 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */
1221 { 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */
1222 { 0x0080, 0x0ff0, pcx }, /* 0x0080 - 0x008f */
1223 { 0x0100, 0x0ff0, pcx }, /* 0x0100 - 0x010f */
1224 { 0x0182, 0x0ffe, pcx }, /* 0x0182 - 0x0183 */
1225 { 0x0182, 0x0ffe, pcxt }, /* 0x0182 - 0x0183 */
1226 { 0x0184, 0x0fff, pcxu }, /* 0x0184 - 0x0184 */
1227 { 0x0200, 0x0ffe, pcxs }, /* 0x0200 - 0x0201 */
1228 { 0x0202, 0x0fff, pcxs }, /* 0x0202 - 0x0202 */
1229 { 0x0203, 0x0fff, pcxt }, /* 0x0203 - 0x0203 */
1230 { 0x0204, 0x0ffc, pcxt }, /* 0x0204 - 0x0207 */
1231 { 0x0280, 0x0ffc, pcxs }, /* 0x0280 - 0x0283 */
1232 { 0x0284, 0x0ffc, pcxt }, /* 0x0284 - 0x0287 */
1233 { 0x0288, 0x0fff, pcxt }, /* 0x0288 - 0x0288 */
1234 { 0x0300, 0x0ffc, pcxs }, /* 0x0300 - 0x0303 */
1235 { 0x0310, 0x0ff0, pcxt }, /* 0x0310 - 0x031f */
1236 { 0x0320, 0x0ff0, pcxt }, /* 0x0320 - 0x032f */
1237 { 0x0400, 0x0ff0, pcxt }, /* 0x0400 - 0x040f */
1238 { 0x0480, 0x0ff0, pcxl }, /* 0x0480 - 0x048f */
1239 { 0x0500, 0x0ff0, pcxl2 }, /* 0x0500 - 0x050f */
1240 { 0x0510, 0x0ff0, pcxl2 }, /* 0x0510 - 0x051f */
1241 { 0x0580, 0x0ff8, pcxt_ }, /* 0x0580 - 0x0587 */
1242 { 0x0588, 0x0ffc, pcxt_ }, /* 0x0588 - 0x058b */
1243 { 0x058c, 0x0ffe, pcxt_ }, /* 0x058c - 0x058d */
1244 { 0x058e, 0x0fff, pcxt_ }, /* 0x058e - 0x058e */
1245 { 0x058f, 0x0fff, pcxu }, /* 0x058f - 0x058f */
1246 { 0x0590, 0x0ffe, pcxu }, /* 0x0590 - 0x0591 */
1247 { 0x0592, 0x0fff, pcxt_ }, /* 0x0592 - 0x0592 */
1248 { 0x0593, 0x0fff, pcxu }, /* 0x0593 - 0x0593 */
1249 { 0x0594, 0x0ffc, pcxu }, /* 0x0594 - 0x0597 */
1250 { 0x0598, 0x0ffe, pcxu_ }, /* 0x0598 - 0x0599 */
1251 { 0x059a, 0x0ffe, pcxu }, /* 0x059a - 0x059b */
1252 { 0x059c, 0x0fff, pcxu }, /* 0x059c - 0x059c */
1253 { 0x059d, 0x0fff, pcxu_ }, /* 0x059d - 0x059d */
1254 { 0x059e, 0x0fff, pcxt_ }, /* 0x059e - 0x059e */
1255 { 0x059f, 0x0fff, pcxu }, /* 0x059f - 0x059f */
1256 { 0x05a0, 0x0ffe, pcxt_ }, /* 0x05a0 - 0x05a1 */
1257 { 0x05a2, 0x0ffe, pcxu }, /* 0x05a2 - 0x05a3 */
1258 { 0x05a4, 0x0ffc, pcxu }, /* 0x05a4 - 0x05a7 */
1259 { 0x05a8, 0x0ffc, pcxu }, /* 0x05a8 - 0x05ab */
1260 { 0x05ad, 0x0fff, pcxu_ }, /* 0x05ad - 0x05ad */
1261 { 0x05ae, 0x0ffe, pcxu_ }, /* 0x05ae - 0x05af */
1262 { 0x05b0, 0x0ffe, pcxu_ }, /* 0x05b0 - 0x05b1 */
1263 { 0x05b2, 0x0fff, pcxu_ }, /* 0x05b2 - 0x05b2 */
1264 { 0x05b3, 0x0fff, pcxu }, /* 0x05b3 - 0x05b3 */
1265 { 0x05b4, 0x0fff, pcxw }, /* 0x05b4 - 0x05b4 */
1266 { 0x05b5, 0x0fff, pcxu_ }, /* 0x05b5 - 0x05b5 */
1267 { 0x05b6, 0x0ffe, pcxu_ }, /* 0x05b6 - 0x05b7 */
1268 { 0x05b8, 0x0ffe, pcxu_ }, /* 0x05b8 - 0x05b9 */
1269 { 0x05ba, 0x0fff, pcxu_ }, /* 0x05ba - 0x05ba */
1270 { 0x05bb, 0x0fff, pcxw }, /* 0x05bb - 0x05bb */
1271 { 0x05bc, 0x0ffc, pcxw }, /* 0x05bc - 0x05bf */
1272 { 0x05c0, 0x0ffc, pcxw }, /* 0x05c0 - 0x05c3 */
1273 { 0x05c4, 0x0ffe, pcxw }, /* 0x05c4 - 0x05c5 */
1274 { 0x05c6, 0x0fff, pcxw }, /* 0x05c6 - 0x05c6 */
1275 { 0x05c7, 0x0fff, pcxw_ }, /* 0x05c7 - 0x05c7 */
1276 { 0x05c8, 0x0ffc, pcxw }, /* 0x05c8 - 0x05cb */
1277 { 0x05cc, 0x0ffe, pcxw }, /* 0x05cc - 0x05cd */
1278 { 0x05ce, 0x0ffe, pcxw_ }, /* 0x05ce - 0x05cf */
1279 { 0x05d0, 0x0ffc, pcxw_ }, /* 0x05d0 - 0x05d3 */
1280 { 0x05d4, 0x0ffe, pcxw_ }, /* 0x05d4 - 0x05d5 */
1281 { 0x05d6, 0x0fff, pcxw }, /* 0x05d6 - 0x05d6 */
1282 { 0x05d7, 0x0fff, pcxw_ }, /* 0x05d7 - 0x05d7 */
1283 { 0x05d8, 0x0ffc, pcxw_ }, /* 0x05d8 - 0x05db */
1284 { 0x05dc, 0x0ffe, pcxw2 }, /* 0x05dc - 0x05dd */
1285 { 0x05de, 0x0fff, pcxw_ }, /* 0x05de - 0x05de */
1286 { 0x05df, 0x0fff, pcxw2 }, /* 0x05df - 0x05df */
1287 { 0x05e0, 0x0ffc, pcxw2 }, /* 0x05e0 - 0x05e3 */
1288 { 0x05e4, 0x0fff, pcxw2 }, /* 0x05e4 - 0x05e4 */
1289 { 0x05e5, 0x0fff, pcxw_ }, /* 0x05e5 - 0x05e5 */
1290 { 0x05e6, 0x0ffe, pcxw2 }, /* 0x05e6 - 0x05e7 */
1291 { 0x05e8, 0x0ff8, pcxw2 }, /* 0x05e8 - 0x05ef */
1292 { 0x05f0, 0x0ff0, pcxw2 }, /* 0x05f0 - 0x05ff */
1293 { 0x0600, 0x0fe0, pcxl }, /* 0x0600 - 0x061f */
1294 { 0x0880, 0x0ff0, mako }, /* 0x0880 - 0x088f */
1295 { 0x0000, 0x0000, pcx } /* terminate table */
1296};
1297
1298char *cpu_name_version[][2] = {
1299 [pcx] = { "PA7000 (PCX)", "1.0" },
1300 [pcxs] = { "PA7000 (PCX-S)", "1.1a" },
1301 [pcxt] = { "PA7100 (PCX-T)", "1.1b" },
1302 [pcxt_] = { "PA7200 (PCX-T')", "1.1c" },
1303 [pcxl] = { "PA7100LC (PCX-L)", "1.1d" },
1304 [pcxl2] = { "PA7300LC (PCX-L2)", "1.1e" },
1305 [pcxu] = { "PA8000 (PCX-U)", "2.0" },
1306 [pcxu_] = { "PA8200 (PCX-U+)", "2.0" },
1307 [pcxw] = { "PA8500 (PCX-W)", "2.0" },
1308 [pcxw_] = { "PA8600 (PCX-W+)", "2.0" },
1309 [pcxw2] = { "PA8700 (PCX-W2)", "2.0" },
1310 [mako] = { "PA8800 (Mako)", "2.0" }
1311};
1312
1313const char * __init
1314parisc_hardware_description(struct parisc_device_id *id)
1315{
1316 struct hp_hardware *listptr;
1317
1318 for (listptr = hp_hardware_list; listptr->hw_type != HPHW_FAULTY; listptr++) {
1319 if ((listptr->hw_type == id->hw_type) &&
1320 (listptr->hversion == id->hversion) &&
1321 (listptr->sversion == id->sversion)){
1322 return listptr->name;
1323 }
1324 }
1325
1326 /*
1327 * ok, the above hardware table isn't complete, and we haven't found
1328 * our device in this table. So let's now try to find a generic name
1329 * to describe the given hardware...
1330 */
1331 switch (id->hw_type) {
1332 case HPHW_NPROC:
1333 return "Unknown machine";
1334
1335 case HPHW_A_DIRECT:
1336 switch (id->sversion) {
1337 case 0x0D: return "MUX port";
1338 case 0x0E: return "RS-232 port";
1339 }
1340 break;
1341
1342 case HPHW_MEMORY:
1343 return "Memory";
1344
1345 }
1346
1347 return "unknown device";
1348}
1349
1350
1351/* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */
1352enum cpu_type __init
1353parisc_get_cpu_type(unsigned long hversion)
1354{
1355 struct hp_cpu_type_mask *ptr;
1356 unsigned short model = ((unsigned short) (hversion)) >> 4;
1357
1358 for (ptr = hp_cpu_type_mask_list; 0 != ptr->mask; ptr++) {
1359 if (ptr->model == (model & ptr->mask))
1360 return ptr->cpu;
1361 }
1362 panic("could not identify CPU type\n");
1363
1364 return pcx; /* not reached: */
1365}
1366
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 @@
1/* This file is subject to the terms and conditions of the GNU General Public
2 * License. See the file "COPYING" in the main directory of this archive
3 * for more details.
4 *
5 * Copyright (C) 1999 by Helge Deller
6 * Copyright 1999 SuSE GmbH (Philipp Rumpf)
7 * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
8 * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com)
9 * Copyright (C) 2001 Grant Grundler (Hewlett Packard)
10 * Copyright (C) 2004 Kyle McMartin <kyle@debian.org>
11 *
12 * Initial Version 04-23-1999 by Helge Deller <deller@gmx.de>
13 */
14
15#include <linux/autoconf.h> /* for CONFIG_SMP */
16
17#include <asm/offsets.h>
18#include <asm/psw.h>
19#include <asm/pdc.h>
20
21#include <asm/assembly.h>
22#include <asm/pgtable.h>
23
24 .level LEVEL
25
26 .data
27
28 .export boot_args
29boot_args:
30 .word 0 /* arg0 */
31 .word 0 /* arg1 */
32 .word 0 /* arg2 */
33 .word 0 /* arg3 */
34
35 .text
36 .align 4
37 .import init_thread_union,data
38 .import fault_vector_20,code /* IVA parisc 2.0 32 bit */
39#ifndef __LP64__
40 .import fault_vector_11,code /* IVA parisc 1.1 32 bit */
41 .import $global$ /* forward declaration */
42#endif /*!LP64*/
43 .export stext
44 .export _stext,data /* Kernel want it this way! */
45_stext:
46stext:
47 .proc
48 .callinfo
49
50 /* Make sure sr4-sr7 are set to zero for the kernel address space */
51 mtsp %r0,%sr4
52 mtsp %r0,%sr5
53 mtsp %r0,%sr6
54 mtsp %r0,%sr7
55
56 /* Clear BSS (shouldn't the boot loader do this?) */
57
58 .import __bss_start,data
59 .import __bss_stop,data
60
61 load32 PA(__bss_start),%r3
62 load32 PA(__bss_stop),%r4
63$bss_loop:
64 cmpb,<<,n %r3,%r4,$bss_loop
65 stw,ma %r0,4(%r3)
66
67 /* Save away the arguments the boot loader passed in (32 bit args) */
68 load32 PA(boot_args),%r1
69 stw,ma %arg0,4(%r1)
70 stw,ma %arg1,4(%r1)
71 stw,ma %arg2,4(%r1)
72 stw,ma %arg3,4(%r1)
73
74 /* Initialize startup VM. Just map first 8/16 MB of memory */
75 load32 PA(swapper_pg_dir),%r4
76 mtctl %r4,%cr24 /* Initialize kernel root pointer */
77 mtctl %r4,%cr25 /* Initialize user root pointer */
78
79#ifdef __LP64__
80 /* Set pmd in pgd */
81 load32 PA(pmd0),%r5
82 shrd %r5,PxD_VALUE_SHIFT,%r3
83 ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
84 stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
85 ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
86#else
87 /* 2-level page table, so pmd == pgd */
88 ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
89#endif
90
91 /* Fill in pmd with enough pte directories */
92 load32 PA(pg0),%r1
93 SHRREG %r1,PxD_VALUE_SHIFT,%r3
94 ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
95
96 ldi ASM_PT_INITIAL,%r1
97
981:
99 stw %r3,0(%r4)
100 ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
101 addib,> -1,%r1,1b
102#ifdef __LP64__
103 ldo ASM_PMD_ENTRY_SIZE(%r4),%r4
104#else
105 ldo ASM_PGD_ENTRY_SIZE(%r4),%r4
106#endif
107
108
109 /* Now initialize the PTEs themselves */
110 ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
111 load32 PA(pg0),%r1
112
113$pgt_fill_loop:
114 STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1)
115 ldo ASM_PAGE_SIZE(%r3),%r3
116 bb,>= %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop
117 nop
118
119 /* Load the return address...er...crash 'n burn */
120 copy %r0,%r2
121
122 /* And the RFI Target address too */
123 load32 start_kernel,%r11
124
125 /* And the initial task pointer */
126 load32 init_thread_union,%r6
127 mtctl %r6,%cr30
128
129 /* And the stack pointer too */
130 ldo THREAD_SZ_ALGN(%r6),%sp
131
132 /* And the interrupt stack */
133 load32 interrupt_stack,%r6
134 mtctl %r6,%cr31
135
136#ifdef CONFIG_SMP
137 /* Set the smp rendevous address into page zero.
138 ** It would be safer to do this in init_smp_config() but
139 ** it's just way easier to deal with here because
140 ** of 64-bit function ptrs and the address is local to this file.
141 */
142 load32 PA(smp_slave_stext),%r10
143 stw %r10,0x10(%r0) /* MEM_RENDEZ */
144 stw %r0,0x28(%r0) /* MEM_RENDEZ_HI - assume addr < 4GB */
145
146 /* FALLTHROUGH */
147 .procend
148
149 /*
150 ** Code Common to both Monarch and Slave processors.
151 ** Entry:
152 **
153 ** 1.1:
154 ** %r11 must contain RFI target address.
155 ** %r25/%r26 args to pass to target function
156 ** %r2 in case rfi target decides it didn't like something
157 **
158 ** 2.0w:
159 ** %r3 PDCE_PROC address
160 ** %r11 RFI target address
161 **
162 ** Caller must init: SR4-7, %sp, %r10, %cr24/25,
163 */
164common_stext:
165 .proc
166 .callinfo
167#else
168 /* Clear PDC entry point - we won't use it */
169 stw %r0,0x10(%r0) /* MEM_RENDEZ */
170 stw %r0,0x28(%r0) /* MEM_RENDEZ_HI */
171#endif /*CONFIG_SMP*/
172
173#ifdef __LP64__
174 tophys_r1 %sp
175
176 /* Save the rfi target address */
177 ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10
178 tophys_r1 %r10
179 std %r11, TASK_PT_GR11(%r10)
180 /* Switch to wide mode Superdome doesn't support narrow PDC
181 ** calls.
182 */
1831: mfia %rp /* clear upper part of pcoq */
184 ldo 2f-1b(%rp),%rp
185 depdi 0,31,32,%rp
186 bv (%rp)
187 ssm PSW_SM_W,%r0
188
189 /* Set Wide mode as the "Default" (eg for traps)
190 ** First trap occurs *right* after (or part of) rfi for slave CPUs.
191 ** Someday, palo might not do this for the Monarch either.
192 */
1932:
194#define MEM_PDC_LO 0x388
195#define MEM_PDC_HI 0x35C
196 ldw MEM_PDC_LO(%r0),%r3
197 ldw MEM_PDC_HI(%r0),%r6
198 depd %r6, 31, 32, %r3 /* move to upper word */
199
200 ldo PDC_PSW(%r0),%arg0 /* 21 */
201 ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */
202 ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */
203 load32 PA(stext_pdc_ret), %rp
204 bv (%r3)
205 copy %r0,%arg3
206
207stext_pdc_ret:
208 /* restore rfi target address*/
209 ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10
210 tophys_r1 %r10
211 ldd TASK_PT_GR11(%r10), %r11
212 tovirt_r1 %sp
213#endif
214
215 /* PARANOID: clear user scratch/user space SR's */
216 mtsp %r0,%sr0
217 mtsp %r0,%sr1
218 mtsp %r0,%sr2
219 mtsp %r0,%sr3
220
221 /* Initialize Protection Registers */
222 mtctl %r0,%cr8
223 mtctl %r0,%cr9
224 mtctl %r0,%cr12
225 mtctl %r0,%cr13
226
227 /* Prepare to RFI! Man all the cannons! */
228
229 /* Initialize the global data pointer */
230 loadgp
231
232 /* Set up our interrupt table. HPMCs might not work after this!
233 *
234 * We need to install the correct iva for PA1.1 or PA2.0. The
235 * following short sequence of instructions can determine this
236 * (without being illegal on a PA1.1 machine).
237 */
238#ifndef __LP64__
239 ldi 32,%r10
240 mtctl %r10,%cr11
241 .level 2.0
242 mfctl,w %cr11,%r10
243 .level 1.1
244 comib,<>,n 0,%r10,$is_pa20
245 ldil L%PA(fault_vector_11),%r10
246 b $install_iva
247 ldo R%PA(fault_vector_11)(%r10),%r10
248
249$is_pa20:
250 .level LEVEL /* restore 1.1 || 2.0w */
251#endif /*!LP64*/
252 load32 PA(fault_vector_20),%r10
253
254$install_iva:
255 mtctl %r10,%cr14
256
257#ifdef __LP64__
258 b aligned_rfi
259 nop
260
261 .align 256
262aligned_rfi:
263 ssm 0,0
264 nop /* 1 */
265 nop /* 2 */
266 nop /* 3 */
267 nop /* 4 */
268 nop /* 5 */
269 nop /* 6 */
270 nop /* 7 */
271 nop /* 8 */
272#endif
273
274#ifdef __LP64__ /* move to psw.h? */
275#define PSW_BITS PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R
276#else
277#define PSW_BITS PSW_SM_Q
278#endif
279
280$rfi:
281 /* turn off troublesome PSW bits */
282 rsm PSW_BITS,%r0
283
284 /* kernel PSW:
285 * - no interruptions except HPMC and TOC (which are handled by PDC)
286 * - Q bit set (IODC / PDC interruptions)
287 * - big-endian
288 * - virtually mapped
289 */
290 load32 KERNEL_PSW,%r10
291 mtctl %r10,%ipsw
292
293 /* Set the space pointers for the post-RFI world
294 ** Clear the two-level IIA Space Queue, effectively setting
295 ** Kernel space.
296 */
297 mtctl %r0,%cr17 /* Clear IIASQ tail */
298 mtctl %r0,%cr17 /* Clear IIASQ head */
299
300 /* Load RFI target into PC queue */
301 mtctl %r11,%cr18 /* IIAOQ head */
302 ldo 4(%r11),%r11
303 mtctl %r11,%cr18 /* IIAOQ tail */
304
305 /* Jump to hyperspace */
306 rfi
307 nop
308
309 .procend
310
311#ifdef CONFIG_SMP
312
313 .import smp_init_current_idle_task,data
314 .import smp_callin,code
315
316#ifndef __LP64__
317smp_callin_rtn:
318 .proc
319 .callinfo
320 break 1,1 /* Break if returned from start_secondary */
321 nop
322 nop
323 .procend
324#endif /*!LP64*/
325
326/***************************************************************************
327* smp_slave_stext is executed by all non-monarch Processors when the Monarch
328* pokes the slave CPUs in smp.c:smp_boot_cpus().
329*
330* Once here, registers values are initialized in order to branch to virtual
331* mode. Once all available/eligible CPUs are in virtual mode, all are
332* released and start out by executing their own idle task.
333*****************************************************************************/
334smp_slave_stext:
335 .proc
336 .callinfo
337
338 /*
339 ** Initialize Space registers
340 */
341 mtsp %r0,%sr4
342 mtsp %r0,%sr5
343 mtsp %r0,%sr6
344 mtsp %r0,%sr7
345
346 /* Initialize the SP - monarch sets up smp_init_current_idle_task */
347 load32 PA(smp_init_current_idle_task),%sp
348 LDREG 0(%sp),%sp /* load task address */
349 tophys_r1 %sp
350 LDREG TASK_THREAD_INFO(%sp),%sp
351 mtctl %sp,%cr30 /* store in cr30 */
352 ldo THREAD_SZ_ALGN(%sp),%sp
353
354 /* point CPU to kernel page tables */
355 load32 PA(swapper_pg_dir),%r4
356 mtctl %r4,%cr24 /* Initialize kernel root pointer */
357 mtctl %r4,%cr25 /* Initialize user root pointer */
358
359#ifdef __LP64__
360 /* Setup PDCE_PROC entry */
361 copy %arg0,%r3
362#else
363 /* Load RFI *return* address in case smp_callin bails */
364 load32 smp_callin_rtn,%r2
365#endif
366
367 /* Load RFI target address. */
368 load32 smp_callin,%r11
369
370 /* ok...common code can handle the rest */
371 b common_stext
372 nop
373
374 .procend
375#endif /* CONFIG_SMP */
376#ifndef __LP64__
377 .data
378
379 .align 4
380 .export $global$,data
381
382 .type $global$,@object
383 .size $global$,4
384$global$:
385 .word 0
386#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 @@
1/*
2 * HPMC (High Priority Machine Check) handler.
3 *
4 * Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org>
5 * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
6 * Copyright (C) 2000 Hewlett-Packard (John Marvin)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23
24/*
25 * This HPMC handler retrieves the HPMC pim data, resets IO and
26 * returns to the default trap handler with code set to 1 (HPMC).
27 * The default trap handler calls handle interruption, which
28 * does a stack and register dump. This at least allows kernel
29 * developers to get back to C code in virtual mode, where they
30 * have the option to examine and print values from memory that
31 * would help in debugging an HPMC caused by a software bug.
32 *
33 * There is more to do here:
34 *
35 * 1) On MP systems we need to synchronize processors
36 * before calling pdc/iodc.
37 * 2) We should be checking the system state and not
38 * returning to the fault handler if things are really
39 * bad.
40 *
41 */
42
43 .level 1.1
44 .data
45
46#include <asm/assembly.h>
47#include <asm/pdc.h>
48
49 /*
50 * stack for os_hpmc, the HPMC handler.
51 * buffer for IODC procedures (for the HPMC handler).
52 *
53 * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc.
54 */
55
56 .align 4096
57hpmc_stack:
58 .block 16384
59
60#define HPMC_IODC_BUF_SIZE 0x8000
61
62 .align 4096
63hpmc_iodc_buf:
64 .block HPMC_IODC_BUF_SIZE
65
66 .align 8
67hpmc_raddr:
68 .block 128
69
70#define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */
71
72 .export hpmc_pim_data, data
73 .align 8
74hpmc_pim_data:
75 .block HPMC_PIM_DATA_SIZE
76
77 .text
78
79 .export os_hpmc, code
80 .import intr_save, code
81
82os_hpmc:
83
84 /*
85 * registers modified:
86 *
87 * Using callee saves registers without saving them. The
88 * original values are in the pim dump if we need them.
89 *
90 * r2 (rp) return pointer
91 * r3 address of PDCE_PROC
92 * r4 scratch
93 * r5 scratch
94 * r23 (arg3) procedure arg
95 * r24 (arg2) procedure arg
96 * r25 (arg1) procedure arg
97 * r26 (arg0) procedure arg
98 * r30 (sp) stack pointer
99 *
100 * registers read:
101 *
102 * r26 contains address of PDCE_PROC on entry
103 * r28 (ret0) return value from procedure
104 */
105
106 copy arg0, %r3 /* save address of PDCE_PROC */
107
108 /*
109 * disable nested HPMCs
110 *
111 * Increment os_hpmc checksum to invalidate it.
112 * Do this before turning the PSW M bit off.
113 */
114
115 mfctl %cr14, %r4
116 ldw 52(%r4),%r5
117 addi 1,%r5,%r5
118 stw %r5,52(%r4)
119
120 /* MP_FIXME: synchronize all processors. */
121
122 /* Setup stack pointer. */
123
124 load32 PA(hpmc_stack),sp
125
126 ldo 128(sp),sp /* leave room for arguments */
127
128 /*
129 * Most PDC routines require that the M bit be off.
130 * So turn on the Q bit and turn off the M bit.
131 */
132
133 ldo 8(%r0),%r4 /* PSW Q on, PSW M off */
134 mtctl %r4,ipsw
135 mtctl %r0,pcsq
136 mtctl %r0,pcsq
137 load32 PA(os_hpmc_1),%r4
138 mtctl %r4,pcoq
139 ldo 4(%r4),%r4
140 mtctl %r4,pcoq
141 rfi
142 nop
143
144os_hpmc_1:
145
146 /* Call PDC_PIM to get HPMC pim info */
147
148 /*
149 * Note that on some newer boxes, PDC_PIM must be called
150 * before PDC_IO if you want IO to be reset. PDC_PIM sets
151 * a flag that PDC_IO examines.
152 */
153
154 ldo PDC_PIM(%r0), arg0
155 ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */
156 load32 PA(hpmc_raddr),arg2
157 load32 PA(hpmc_pim_data),arg3
158 load32 HPMC_PIM_DATA_SIZE,%r4
159 stw %r4,-52(sp)
160
161 ldil L%PA(os_hpmc_2), rp
162 bv (r3) /* call pdce_proc */
163 ldo R%PA(os_hpmc_2)(rp), rp
164
165os_hpmc_2:
166 comib,<> 0,ret0, os_hpmc_fail
167
168 /* Reset IO by calling the hversion dependent PDC_IO routine */
169
170 ldo PDC_IO(%r0),arg0
171 ldo 0(%r0),arg1 /* log IO errors */
172 ldo 0(%r0),arg2 /* reserved */
173 ldo 0(%r0),arg3 /* reserved */
174 stw %r0,-52(sp) /* reserved */
175
176 ldil L%PA(os_hpmc_3),rp
177 bv (%r3) /* call pdce_proc */
178 ldo R%PA(os_hpmc_3)(rp),rp
179
180os_hpmc_3:
181
182 /* FIXME? Check for errors from PDC_IO (-1 might be OK) */
183
184 /*
185 * Initialize the IODC console device (HPA,SPA, path etc.
186 * are stored on page 0.
187 */
188
189 /*
190 * Load IODC into hpmc_iodc_buf by calling PDC_IODC.
191 * Note that PDC_IODC handles flushing the appropriate
192 * data and instruction cache lines.
193 */
194
195 ldo PDC_IODC(%r0),arg0
196 ldo PDC_IODC_READ(%r0),arg1
197 load32 PA(hpmc_raddr),arg2
198 ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */
199 ldo PDC_IODC_RI_INIT(%r0),%r4
200 stw %r4,-52(sp)
201 load32 PA(hpmc_iodc_buf),%r4
202 stw %r4,-56(sp)
203 load32 HPMC_IODC_BUF_SIZE,%r4
204 stw %r4,-60(sp)
205
206 ldil L%PA(os_hpmc_4),rp
207 bv (%r3) /* call pdce_proc */
208 ldo R%PA(os_hpmc_4)(rp),rp
209
210os_hpmc_4:
211 comib,<> 0,ret0,os_hpmc_fail
212
213 /* Call the entry init (just loaded by PDC_IODC) */
214
215 ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg0 /* console hpa */
216 ldo ENTRY_INIT_MOD_DEV(%r0), arg1
217 ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */
218 depi 0,31,11,arg2 /* clear bits 21-31 */
219 ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */
220 load32 PA(hpmc_raddr),%r4
221 stw %r4, -52(sp)
222 stw %r0, -56(sp) /* HV */
223 stw %r0, -60(sp) /* HV */
224 stw %r0, -64(sp) /* HV */
225 stw %r0, -68(sp) /* lang, must be zero */
226
227 load32 PA(hpmc_iodc_buf),%r5
228 ldil L%PA(os_hpmc_5),rp
229 bv (%r5)
230 ldo R%PA(os_hpmc_5)(rp),rp
231
232os_hpmc_5:
233 comib,<> 0,ret0,os_hpmc_fail
234
235 /* Prepare to call intr_save */
236
237 /*
238 * Load kernel page directory (load into user also, since
239 * we don't intend to ever return to user land anyway)
240 */
241
242 load32 PA(swapper_pg_dir),%r4
243 mtctl %r4,%cr24 /* Initialize kernel root pointer */
244 mtctl %r4,%cr25 /* Initialize user root pointer */
245
246 /* Clear sr4-sr7 */
247
248 mtsp %r0, %sr4
249 mtsp %r0, %sr5
250 mtsp %r0, %sr6
251 mtsp %r0, %sr7
252
253 tovirt_r1 %r30 /* make sp virtual */
254
255 rsm 8,%r0 /* Clear Q bit */
256 ldi 1,%r8 /* Set trap code to "1" for HPMC */
257 load32 PA(intr_save),%r1
258 be 0(%sr7,%r1)
259 nop
260
261os_hpmc_fail:
262
263 /*
264 * Reset the system
265 *
266 * Some systems may lockup from a broadcast reset, so try the
267 * hversion PDC_BROADCAST_RESET() first.
268 * MP_FIXME: reset all processors if more than one central bus.
269 */
270
271 /* PDC_BROADCAST_RESET() */
272
273 ldo PDC_BROADCAST_RESET(%r0),arg0
274 ldo 0(%r0),arg1 /* do reset */
275
276 ldil L%PA(os_hpmc_6),rp
277 bv (%r3) /* call pdce_proc */
278 ldo R%PA(os_hpmc_6)(rp),rp
279
280os_hpmc_6:
281
282 /*
283 * possible return values:
284 * -1 non-existent procedure
285 * -2 non-existent option
286 * -16 unaligned stack
287 *
288 * If call returned, do a broadcast reset.
289 */
290
291 ldil L%0xfffc0000,%r4 /* IO_BROADCAST */
292 ldo 5(%r0),%r5
293 stw %r5,48(%r4) /* CMD_RESET to IO_COMMAND offset */
294
295 b .
296 nop
297
298 /* this label used to compute os_hpmc checksum */
299
300 .export os_hpmc_end, code
301
302os_hpmc_end:
303
304 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 @@
1/*
2 * Static declaration of "init" task data structure.
3 *
4 * Copyright (C) 2000 Paul Bame <bame at parisc-linux.org>
5 * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org>
6 * Copyright (C) 2001 Helge Deller <deller @ parisc-linux.org>
7 * Copyright (C) 2002 Matthew Wilcox <willy with parisc-linux.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <linux/mm.h>
26#include <linux/module.h>
27#include <linux/sched.h>
28#include <linux/init.h>
29#include <linux/init_task.h>
30#include <linux/mqueue.h>
31
32#include <asm/uaccess.h>
33#include <asm/pgtable.h>
34#include <asm/pgalloc.h>
35
36static struct fs_struct init_fs = INIT_FS;
37static struct files_struct init_files = INIT_FILES;
38static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
39static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
40struct mm_struct init_mm = INIT_MM(init_mm);
41
42EXPORT_SYMBOL(init_mm);
43
44/*
45 * Initial task structure.
46 *
47 * We need to make sure that this is 16384-byte aligned due to the
48 * way process stacks are handled. This is done by having a special
49 * "init_task" linker map entry..
50 */
51unsigned char interrupt_stack[ISTACK_SIZE] __attribute__ ((section("init_istack"), aligned(4096)));
52union thread_union init_thread_union
53 __attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) =
54 { INIT_THREAD_INFO(init_task) };
55
56#ifdef __LP64__
57/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
58 * with the first pmd adjacent to the pgd and below it. gcc doesn't actually
59 * guarantee that global objects will be laid out in memory in the same order
60 * as the order of declaration, so put these in different sections and use
61 * the linker script to order them. */
62pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pmd"))) = { {0}, };
63
64#endif
65pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pgd"))) = { {0}, };
66pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pte"))) = { {0}, };
67
68/*
69 * Initial task structure.
70 *
71 * All other task structs will be allocated on slabs in fork.c
72 */
73EXPORT_SYMBOL(init_task);
74
75__asm__(".data");
76struct 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 @@
1/*
2 * inventory.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Copyright (c) 1999 The Puffin Group (David Kennedy and Alex deVries)
10 * Copyright (c) 2001 Matthew Wilcox for Hewlett-Packard
11 *
12 * These are the routines to discover what hardware exists in this box.
13 * This task is complicated by there being 3 different ways of
14 * performing an inventory, depending largely on the age of the box.
15 * The recommended way to do this is to check to see whether the machine
16 * is a `Snake' first, then try System Map, then try PAT. We try System
17 * Map before checking for a Snake -- this probably doesn't cause any
18 * problems, but...
19 */
20
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/slab.h>
25#include <linux/mm.h>
26#include <asm/hardware.h>
27#include <asm/io.h>
28#include <asm/mmzone.h>
29#include <asm/pdc.h>
30#include <asm/pdcpat.h>
31#include <asm/processor.h>
32#include <asm/page.h>
33#include <asm/parisc-device.h>
34
35/*
36** Debug options
37** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices.
38*/
39#undef DEBUG_PAT
40
41int pdc_type = PDC_TYPE_ILLEGAL;
42
43void __init setup_pdc(void)
44{
45 long status;
46 unsigned int bus_id;
47 struct pdc_system_map_mod_info module_result;
48 struct pdc_module_path module_path;
49 struct pdc_model model;
50#ifdef __LP64__
51 struct pdc_pat_cell_num cell_info;
52#endif
53
54 /* Determine the pdc "type" used on this machine */
55
56 printk(KERN_INFO "Determining PDC firmware type: ");
57
58 status = pdc_system_map_find_mods(&module_result, &module_path, 0);
59 if (status == PDC_OK) {
60 pdc_type = PDC_TYPE_SYSTEM_MAP;
61 printk("System Map.\n");
62 return;
63 }
64
65 /*
66 * If the machine doesn't support PDC_SYSTEM_MAP then either it
67 * is a pdc pat box, or it is an older box. All 64 bit capable
68 * machines are either pdc pat boxes or they support PDC_SYSTEM_MAP.
69 */
70
71 /*
72 * TODO: We should test for 64 bit capability and give a
73 * clearer message.
74 */
75
76#ifdef __LP64__
77 status = pdc_pat_cell_get_number(&cell_info);
78 if (status == PDC_OK) {
79 pdc_type = PDC_TYPE_PAT;
80 printk("64 bit PAT.\n");
81 return;
82 }
83#endif
84
85 /* Check the CPU's bus ID. There's probably a better test. */
86
87 status = pdc_model_info(&model);
88
89 bus_id = (model.hversion >> (4 + 7)) & 0x1f;
90
91 switch (bus_id) {
92 case 0x4: /* 720, 730, 750, 735, 755 */
93 case 0x6: /* 705, 710 */
94 case 0x7: /* 715, 725 */
95 case 0x8: /* 745, 747, 742 */
96 case 0xA: /* 712 and similiar */
97 case 0xC: /* 715/64, at least */
98
99 pdc_type = PDC_TYPE_SNAKE;
100 printk("Snake.\n");
101 return;
102
103 default: /* Everything else */
104
105 printk("Unsupported.\n");
106 panic("If this is a 64-bit machine, please try a 64-bit kernel.\n");
107 }
108}
109
110#define PDC_PAGE_ADJ_SHIFT (PAGE_SHIFT - 12) /* pdc pages are always 4k */
111
112static void __init
113set_pmem_entry(physmem_range_t *pmem_ptr, unsigned long start,
114 unsigned long pages4k)
115{
116 /* Rather than aligning and potentially throwing away
117 * memory, we'll assume that any ranges are already
118 * nicely aligned with any reasonable page size, and
119 * panic if they are not (it's more likely that the
120 * pdc info is bad in this case).
121 */
122
123 if ( ((start & (PAGE_SIZE - 1)) != 0)
124 || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) ) {
125
126 panic("Memory range doesn't align with page size!\n");
127 }
128
129 pmem_ptr->start_pfn = (start >> PAGE_SHIFT);
130 pmem_ptr->pages = (pages4k >> PDC_PAGE_ADJ_SHIFT);
131}
132
133static void __init pagezero_memconfig(void)
134{
135 unsigned long npages;
136
137 /* Use the 32 bit information from page zero to create a single
138 * entry in the pmem_ranges[] table.
139 *
140 * We currently don't support machines with contiguous memory
141 * >= 4 Gb, who report that memory using 64 bit only fields
142 * on page zero. It's not worth doing until it can be tested,
143 * and it is not clear we can support those machines for other
144 * reasons.
145 *
146 * If that support is done in the future, this is where it
147 * should be done.
148 */
149
150 npages = (PAGE_ALIGN(PAGE0->imm_max_mem) >> PAGE_SHIFT);
151 set_pmem_entry(pmem_ranges,0UL,npages);
152 npmem_ranges = 1;
153}
154
155#ifdef __LP64__
156
157/* All of the PDC PAT specific code is 64-bit only */
158
159/*
160** The module object is filled via PDC_PAT_CELL[Return Cell Module].
161** If a module is found, register module will get the IODC bytes via
162** pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter.
163**
164** The IO view can be used by PDC_PAT_CELL[Return Cell Module]
165** only for SBAs and LBAs. This view will cause an invalid
166** argument error for all other cell module types.
167**
168*/
169
170static int __init
171pat_query_module(ulong pcell_loc, ulong mod_index)
172{
173 pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
174 unsigned long bytecnt;
175 unsigned long temp; /* 64-bit scratch value */
176 long status; /* PDC return value status */
177 struct parisc_device *dev;
178
179 /* return cell module (PA or Processor view) */
180 status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
181 PA_VIEW, &pa_pdc_cell);
182
183 if (status != PDC_OK) {
184 /* no more cell modules or error */
185 return status;
186 }
187
188 temp = pa_pdc_cell.cba;
189 dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path);
190 if (!dev) {
191 return PDC_NE_MOD;
192 }
193
194 /* alloc_pa_dev sets dev->hpa */
195
196 /*
197 ** save parameters in the parisc_device
198 ** (The idea being the device driver will call pdc_pat_cell_module()
199 ** and store the results in its own data structure.)
200 */
201 dev->pcell_loc = pcell_loc;
202 dev->mod_index = mod_index;
203
204 /* save generic info returned from the call */
205 /* REVISIT: who is the consumer of this? not sure yet... */
206 dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */
207 dev->pmod_loc = pa_pdc_cell.mod_location;
208
209 register_parisc_device(dev); /* advertise device */
210
211#ifdef DEBUG_PAT
212 pdc_pat_cell_mod_maddr_block_t io_pdc_cell;
213 /* dump what we see so far... */
214 switch (PAT_GET_ENTITY(dev->mod_info)) {
215 unsigned long i;
216
217 case PAT_ENTITY_PROC:
218 printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n",
219 pa_pdc_cell.mod[0]);
220 break;
221
222 case PAT_ENTITY_MEM:
223 printk(KERN_DEBUG
224 "PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",
225 pa_pdc_cell.mod[0], pa_pdc_cell.mod[1],
226 pa_pdc_cell.mod[2]);
227 break;
228 case PAT_ENTITY_CA:
229 printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc);
230 break;
231
232 case PAT_ENTITY_PBC:
233 printk(KERN_DEBUG "PAT_ENTITY_PBC: ");
234 goto print_ranges;
235
236 case PAT_ENTITY_SBA:
237 printk(KERN_DEBUG "PAT_ENTITY_SBA: ");
238 goto print_ranges;
239
240 case PAT_ENTITY_LBA:
241 printk(KERN_DEBUG "PAT_ENTITY_LBA: ");
242
243 print_ranges:
244 pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
245 IO_VIEW, &io_pdc_cell);
246 printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]);
247 for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
248 printk(KERN_DEBUG
249 " PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n",
250 i, pa_pdc_cell.mod[2 + i * 3], /* type */
251 pa_pdc_cell.mod[3 + i * 3], /* start */
252 pa_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */
253 printk(KERN_DEBUG
254 " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n",
255 i, io_pdc_cell.mod[2 + i * 3], /* type */
256 io_pdc_cell.mod[3 + i * 3], /* start */
257 io_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */
258 }
259 printk(KERN_DEBUG "\n");
260 break;
261 }
262#endif /* DEBUG_PAT */
263 return PDC_OK;
264}
265
266
267/* pat pdc can return information about a variety of different
268 * types of memory (e.g. firmware,i/o, etc) but we only care about
269 * the usable physical ram right now. Since the firmware specific
270 * information is allocated on the stack, we'll be generous, in
271 * case there is a lot of other information we don't care about.
272 */
273
274#define PAT_MAX_RANGES (4 * MAX_PHYSMEM_RANGES)
275
276static void __init pat_memconfig(void)
277{
278 unsigned long actual_len;
279 struct pdc_pat_pd_addr_map_entry mem_table[PAT_MAX_RANGES+1];
280 struct pdc_pat_pd_addr_map_entry *mtbl_ptr;
281 physmem_range_t *pmem_ptr;
282 long status;
283 int entries;
284 unsigned long length;
285 int i;
286
287 length = (PAT_MAX_RANGES + 1) * sizeof(struct pdc_pat_pd_addr_map_entry);
288
289 status = pdc_pat_pd_get_addr_map(&actual_len, mem_table, length, 0L);
290
291 if ((status != PDC_OK)
292 || ((actual_len % sizeof(struct pdc_pat_pd_addr_map_entry)) != 0)) {
293
294 /* The above pdc call shouldn't fail, but, just in
295 * case, just use the PAGE0 info.
296 */
297
298 printk("\n\n\n");
299 printk(KERN_WARNING "WARNING! Could not get full memory configuration. "
300 "All memory may not be used!\n\n\n");
301 pagezero_memconfig();
302 return;
303 }
304
305 entries = actual_len / sizeof(struct pdc_pat_pd_addr_map_entry);
306
307 if (entries > PAT_MAX_RANGES) {
308 printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
309 printk(KERN_WARNING "Some memory may not be used!\n");
310 }
311
312 /* Copy information into the firmware independent pmem_ranges
313 * array, skipping types we don't care about. Notice we said
314 * "may" above. We'll use all the entries that were returned.
315 */
316
317 npmem_ranges = 0;
318 mtbl_ptr = mem_table;
319 pmem_ptr = pmem_ranges; /* Global firmware independent table */
320 for (i = 0; i < entries; i++,mtbl_ptr++) {
321 if ( (mtbl_ptr->entry_type != PAT_MEMORY_DESCRIPTOR)
322 || (mtbl_ptr->memory_type != PAT_MEMTYPE_MEMORY)
323 || (mtbl_ptr->pages == 0)
324 || ( (mtbl_ptr->memory_usage != PAT_MEMUSE_GENERAL)
325 && (mtbl_ptr->memory_usage != PAT_MEMUSE_GI)
326 && (mtbl_ptr->memory_usage != PAT_MEMUSE_GNI) ) ) {
327
328 continue;
329 }
330
331 if (npmem_ranges == MAX_PHYSMEM_RANGES) {
332 printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
333 printk(KERN_WARNING "Some memory will not be used!\n");
334 break;
335 }
336
337 set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages);
338 npmem_ranges++;
339 }
340}
341
342static int __init pat_inventory(void)
343{
344 int status;
345 ulong mod_index = 0;
346 struct pdc_pat_cell_num cell_info;
347
348 /*
349 ** Note: Prelude (and it's successors: Lclass, A400/500) only
350 ** implement PDC_PAT_CELL sub-options 0 and 2.
351 */
352 status = pdc_pat_cell_get_number(&cell_info);
353 if (status != PDC_OK) {
354 return 0;
355 }
356
357#ifdef DEBUG_PAT
358 printk(KERN_DEBUG "CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_info.cell_num,
359 cell_info.cell_loc);
360#endif
361
362 while (PDC_OK == pat_query_module(cell_info.cell_loc, mod_index)) {
363 mod_index++;
364 }
365
366 return mod_index;
367}
368
369/* We only look for extended memory ranges on a 64 bit capable box */
370static void __init sprockets_memconfig(void)
371{
372 struct pdc_memory_table_raddr r_addr;
373 struct pdc_memory_table mem_table[MAX_PHYSMEM_RANGES];
374 struct pdc_memory_table *mtbl_ptr;
375 physmem_range_t *pmem_ptr;
376 long status;
377 int entries;
378 int i;
379
380 status = pdc_mem_mem_table(&r_addr,mem_table,
381 (unsigned long)MAX_PHYSMEM_RANGES);
382
383 if (status != PDC_OK) {
384
385 /* The above pdc call only works on boxes with sprockets
386 * firmware (newer B,C,J class). Other non PAT PDC machines
387 * do support more than 3.75 Gb of memory, but we don't
388 * support them yet.
389 */
390
391 pagezero_memconfig();
392 return;
393 }
394
395 if (r_addr.entries_total > MAX_PHYSMEM_RANGES) {
396 printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
397 printk(KERN_WARNING "Some memory will not be used!\n");
398 }
399
400 entries = (int)r_addr.entries_returned;
401
402 npmem_ranges = 0;
403 mtbl_ptr = mem_table;
404 pmem_ptr = pmem_ranges; /* Global firmware independent table */
405 for (i = 0; i < entries; i++,mtbl_ptr++) {
406 set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages);
407 npmem_ranges++;
408 }
409}
410
411#else /* !__LP64__ */
412
413#define pat_inventory() do { } while (0)
414#define pat_memconfig() do { } while (0)
415#define sprockets_memconfig() pagezero_memconfig()
416
417#endif /* !__LP64__ */
418
419
420#ifndef CONFIG_PA20
421
422/* Code to support Snake machines (7[2350], 7[235]5, 715/Scorpio) */
423
424static struct parisc_device * __init
425legacy_create_device(struct pdc_memory_map *r_addr,
426 struct pdc_module_path *module_path)
427{
428 struct parisc_device *dev;
429 int status = pdc_mem_map_hpa(r_addr, module_path);
430 if (status != PDC_OK)
431 return NULL;
432
433 dev = alloc_pa_dev(r_addr->hpa, &module_path->path);
434 if (dev == NULL)
435 return NULL;
436
437 register_parisc_device(dev);
438 return dev;
439}
440
441/**
442 * snake_inventory
443 *
444 * Before PDC_SYSTEM_MAP was invented, the PDC_MEM_MAP call was used.
445 * To use it, we initialise the mod_path.bc to 0xff and try all values of
446 * mod to get the HPA for the top-level devices. Bus adapters may have
447 * sub-devices which are discovered by setting bc[5] to 0 and bc[4] to the
448 * module, then trying all possible functions.
449 */
450static void __init snake_inventory(void)
451{
452 int mod;
453 for (mod = 0; mod < 16; mod++) {
454 struct parisc_device *dev;
455 struct pdc_module_path module_path;
456 struct pdc_memory_map r_addr;
457 unsigned int func;
458
459 memset(module_path.path.bc, 0xff, 6);
460 module_path.path.mod = mod;
461 dev = legacy_create_device(&r_addr, &module_path);
462 if ((!dev) || (dev->id.hw_type != HPHW_BA))
463 continue;
464
465 memset(module_path.path.bc, 0xff, 4);
466 module_path.path.bc[4] = mod;
467
468 for (func = 0; func < 16; func++) {
469 module_path.path.bc[5] = 0;
470 module_path.path.mod = func;
471 legacy_create_device(&r_addr, &module_path);
472 }
473 }
474}
475
476#else /* CONFIG_PA20 */
477#define snake_inventory() do { } while (0)
478#endif /* CONFIG_PA20 */
479
480/* Common 32/64 bit based code goes here */
481
482/**
483 * add_system_map_addresses - Add additional addresses to the parisc device.
484 * @dev: The parisc device.
485 * @num_addrs: Then number of addresses to add;
486 * @module_instance: The system_map module instance.
487 *
488 * This function adds any additional addresses reported by the system_map
489 * firmware to the parisc device.
490 */
491static void __init
492add_system_map_addresses(struct parisc_device *dev, int num_addrs,
493 int module_instance)
494{
495 int i;
496 long status;
497 struct pdc_system_map_addr_info addr_result;
498
499 dev->addr = kmalloc(num_addrs * sizeof(unsigned long), GFP_KERNEL);
500 if(!dev->addr) {
501 printk(KERN_ERR "%s %s(): memory allocation failure\n",
502 __FILE__, __FUNCTION__);
503 return;
504 }
505
506 for(i = 1; i <= num_addrs; ++i) {
507 status = pdc_system_map_find_addrs(&addr_result,
508 module_instance, i);
509 if(PDC_OK == status) {
510 dev->addr[dev->num_addrs] = (unsigned long)addr_result.mod_addr;
511 dev->num_addrs++;
512 } else {
513 printk(KERN_WARNING
514 "Bad PDC_FIND_ADDRESS status return (%ld) for index %d\n",
515 status, i);
516 }
517 }
518}
519
520/**
521 * system_map_inventory - Retrieve firmware devices via SYSTEM_MAP.
522 *
523 * This function attempts to retrieve and register all the devices firmware
524 * knows about via the SYSTEM_MAP PDC call.
525 */
526static void __init system_map_inventory(void)
527{
528 int i;
529 long status = PDC_OK;
530
531 for (i = 0; i < 256; i++) {
532 struct parisc_device *dev;
533 struct pdc_system_map_mod_info module_result;
534 struct pdc_module_path module_path;
535
536 status = pdc_system_map_find_mods(&module_result,
537 &module_path, i);
538 if ((status == PDC_BAD_PROC) || (status == PDC_NE_MOD))
539 break;
540 if (status != PDC_OK)
541 continue;
542
543 dev = alloc_pa_dev(module_result.mod_addr, &module_path.path);
544 if (!dev)
545 continue;
546
547 register_parisc_device(dev);
548
549 /* if available, get the additional addresses for a module */
550 if (!module_result.add_addrs)
551 continue;
552
553 add_system_map_addresses(dev, module_result.add_addrs, i);
554 }
555
556 walk_central_bus();
557 return;
558}
559
560void __init do_memory_inventory(void)
561{
562 switch (pdc_type) {
563
564 case PDC_TYPE_PAT:
565 pat_memconfig();
566 break;
567
568 case PDC_TYPE_SYSTEM_MAP:
569 sprockets_memconfig();
570 break;
571
572 case PDC_TYPE_SNAKE:
573 pagezero_memconfig();
574 return;
575
576 default:
577 panic("Unknown PDC type!\n");
578 }
579
580 if (npmem_ranges == 0 || pmem_ranges[0].start_pfn != 0) {
581 printk(KERN_WARNING "Bad memory configuration returned!\n");
582 printk(KERN_WARNING "Some memory may not be used!\n");
583 pagezero_memconfig();
584 }
585}
586
587void __init do_device_inventory(void)
588{
589 printk(KERN_INFO "Searching for devices...\n");
590
591 init_parisc_bus();
592
593 switch (pdc_type) {
594
595 case PDC_TYPE_PAT:
596 pat_inventory();
597 break;
598
599 case PDC_TYPE_SYSTEM_MAP:
600 system_map_inventory();
601 break;
602
603 case PDC_TYPE_SNAKE:
604 snake_inventory();
605 break;
606
607 default:
608 panic("Unknown PDC type!\n");
609 }
610 printk(KERN_INFO "Found devices:\n");
611 print_parisc_devices();
612}
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 @@
1/* $Id: ioctl32.c,v 1.5 2002/10/18 00:21:43 varenet Exp $
2 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
3 *
4 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
5 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
6 *
7 * These routines maintain argument size conversion between 32bit and 64bit
8 * ioctls.
9 */
10
11#include <linux/syscalls.h>
12
13#define INCLUDES
14#include "compat_ioctl.c"
15
16#include <asm/perf.h>
17#include <asm/ioctls.h>
18
19#define CODE
20#include "compat_ioctl.c"
21
22/* Use this to get at 32-bit user passed pointers.
23 See sys_sparc32.c for description about these. */
24#define A(__x) ((unsigned long)(__x))
25/* The same for use with copy_from_user() and copy_to_user(). */
26#define B(__x) ((void *)(unsigned long)(__x))
27
28#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
29/* This really belongs in include/linux/drm.h -DaveM */
30#include "../../../drivers/char/drm/drm.h"
31
32typedef struct drm32_version {
33 int version_major; /* Major version */
34 int version_minor; /* Minor version */
35 int version_patchlevel;/* Patch level */
36 int name_len; /* Length of name buffer */
37 u32 name; /* Name of driver */
38 int date_len; /* Length of date buffer */
39 u32 date; /* User-space buffer to hold date */
40 int desc_len; /* Length of desc buffer */
41 u32 desc; /* User-space buffer to hold desc */
42} drm32_version_t;
43#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t)
44
45static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg)
46{
47 drm32_version_t *uversion = (drm32_version_t *)arg;
48 char *name_ptr, *date_ptr, *desc_ptr;
49 u32 tmp1, tmp2, tmp3;
50 drm_version_t kversion;
51 mm_segment_t old_fs;
52 int ret;
53
54 memset(&kversion, 0, sizeof(kversion));
55 if (get_user(kversion.name_len, &uversion->name_len) ||
56 get_user(kversion.date_len, &uversion->date_len) ||
57 get_user(kversion.desc_len, &uversion->desc_len) ||
58 get_user(tmp1, &uversion->name) ||
59 get_user(tmp2, &uversion->date) ||
60 get_user(tmp3, &uversion->desc))
61 return -EFAULT;
62
63 name_ptr = (char *) A(tmp1);
64 date_ptr = (char *) A(tmp2);
65 desc_ptr = (char *) A(tmp3);
66
67 ret = -ENOMEM;
68 if (kversion.name_len && name_ptr) {
69 kversion.name = kmalloc(kversion.name_len, GFP_KERNEL);
70 if (!kversion.name)
71 goto out;
72 }
73 if (kversion.date_len && date_ptr) {
74 kversion.date = kmalloc(kversion.date_len, GFP_KERNEL);
75 if (!kversion.date)
76 goto out;
77 }
78 if (kversion.desc_len && desc_ptr) {
79 kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL);
80 if (!kversion.desc)
81 goto out;
82 }
83
84 old_fs = get_fs();
85 set_fs(KERNEL_DS);
86 ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion);
87 set_fs(old_fs);
88
89 if (!ret) {
90 if ((kversion.name &&
91 copy_to_user(name_ptr, kversion.name, kversion.name_len)) ||
92 (kversion.date &&
93 copy_to_user(date_ptr, kversion.date, kversion.date_len)) ||
94 (kversion.desc &&
95 copy_to_user(desc_ptr, kversion.desc, kversion.desc_len)))
96 ret = -EFAULT;
97 if (put_user(kversion.version_major, &uversion->version_major) ||
98 put_user(kversion.version_minor, &uversion->version_minor) ||
99 put_user(kversion.version_patchlevel, &uversion->version_patchlevel) ||
100 put_user(kversion.name_len, &uversion->name_len) ||
101 put_user(kversion.date_len, &uversion->date_len) ||
102 put_user(kversion.desc_len, &uversion->desc_len))
103 ret = -EFAULT;
104 }
105
106out:
107 if (kversion.name)
108 kfree(kversion.name);
109 if (kversion.date)
110 kfree(kversion.date);
111 if (kversion.desc)
112 kfree(kversion.desc);
113 return ret;
114}
115
116typedef struct drm32_unique {
117 int unique_len; /* Length of unique */
118 u32 unique; /* Unique name for driver instantiation */
119} drm32_unique_t;
120#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t)
121#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t)
122
123static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg)
124{
125 drm32_unique_t *uarg = (drm32_unique_t *)arg;
126 drm_unique_t karg;
127 mm_segment_t old_fs;
128 char *uptr;
129 u32 tmp;
130 int ret;
131
132 if (get_user(karg.unique_len, &uarg->unique_len))
133 return -EFAULT;
134 karg.unique = NULL;
135
136 if (get_user(tmp, &uarg->unique))
137 return -EFAULT;
138
139 uptr = (char *) A(tmp);
140
141 if (uptr) {
142 karg.unique = kmalloc(karg.unique_len, GFP_KERNEL);
143 if (!karg.unique)
144 return -ENOMEM;
145 if (cmd == DRM32_IOCTL_SET_UNIQUE &&
146 copy_from_user(karg.unique, uptr, karg.unique_len)) {
147 kfree(karg.unique);
148 return -EFAULT;
149 }
150 }
151
152 old_fs = get_fs();
153 set_fs(KERNEL_DS);
154 if (cmd == DRM32_IOCTL_GET_UNIQUE)
155 ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg);
156 else
157 ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg);
158 set_fs(old_fs);
159
160 if (!ret) {
161 if (cmd == DRM32_IOCTL_GET_UNIQUE &&
162 uptr != NULL &&
163 copy_to_user(uptr, karg.unique, karg.unique_len))
164 ret = -EFAULT;
165 if (put_user(karg.unique_len, &uarg->unique_len))
166 ret = -EFAULT;
167 }
168
169 if (karg.unique != NULL)
170 kfree(karg.unique);
171
172 return ret;
173}
174
175typedef struct drm32_map {
176 u32 offset; /* Requested physical address (0 for SAREA)*/
177 u32 size; /* Requested physical size (bytes) */
178 drm_map_type_t type; /* Type of memory to map */
179 drm_map_flags_t flags; /* Flags */
180 u32 handle; /* User-space: "Handle" to pass to mmap */
181 /* Kernel-space: kernel-virtual address */
182 int mtrr; /* MTRR slot used */
183 /* Private data */
184} drm32_map_t;
185#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t)
186
187static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg)
188{
189 drm32_map_t *uarg = (drm32_map_t *) arg;
190 drm_map_t karg;
191 mm_segment_t old_fs;
192 u32 tmp;
193 int ret;
194
195 ret = get_user(karg.offset, &uarg->offset);
196 ret |= get_user(karg.size, &uarg->size);
197 ret |= get_user(karg.type, &uarg->type);
198 ret |= get_user(karg.flags, &uarg->flags);
199 ret |= get_user(tmp, &uarg->handle);
200 ret |= get_user(karg.mtrr, &uarg->mtrr);
201 if (ret)
202 return -EFAULT;
203
204 karg.handle = (void *) A(tmp);
205
206 old_fs = get_fs();
207 set_fs(KERNEL_DS);
208 ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg);
209 set_fs(old_fs);
210
211 if (!ret) {
212 ret = put_user(karg.offset, &uarg->offset);
213 ret |= put_user(karg.size, &uarg->size);
214 ret |= put_user(karg.type, &uarg->type);
215 ret |= put_user(karg.flags, &uarg->flags);
216 tmp = (u32) (long)karg.handle;
217 ret |= put_user(tmp, &uarg->handle);
218 ret |= put_user(karg.mtrr, &uarg->mtrr);
219 if (ret)
220 ret = -EFAULT;
221 }
222
223 return ret;
224}
225
226typedef struct drm32_buf_info {
227 int count; /* Entries in list */
228 u32 list; /* (drm_buf_desc_t *) */
229} drm32_buf_info_t;
230#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t)
231
232static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
233{
234 drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg;
235 drm_buf_desc_t *ulist;
236 drm_buf_info_t karg;
237 mm_segment_t old_fs;
238 int orig_count, ret;
239 u32 tmp;
240
241 if (get_user(karg.count, &uarg->count) ||
242 get_user(tmp, &uarg->list))
243 return -EFAULT;
244
245 ulist = (drm_buf_desc_t *) A(tmp);
246
247 orig_count = karg.count;
248
249 karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL);
250 if (!karg.list)
251 return -EFAULT;
252
253 old_fs = get_fs();
254 set_fs(KERNEL_DS);
255 ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg);
256 set_fs(old_fs);
257
258 if (!ret) {
259 if (karg.count <= orig_count &&
260 (copy_to_user(ulist, karg.list,
261 karg.count * sizeof(drm_buf_desc_t))))
262 ret = -EFAULT;
263 if (put_user(karg.count, &uarg->count))
264 ret = -EFAULT;
265 }
266
267 kfree(karg.list);
268
269 return ret;
270}
271
272typedef struct drm32_buf_free {
273 int count;
274 u32 list; /* (int *) */
275} drm32_buf_free_t;
276#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t)
277
278static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
279{
280 drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg;
281 drm_buf_free_t karg;
282 mm_segment_t old_fs;
283 int *ulist;
284 int ret;
285 u32 tmp;
286
287 if (get_user(karg.count, &uarg->count) ||
288 get_user(tmp, &uarg->list))
289 return -EFAULT;
290
291 ulist = (int *) A(tmp);
292
293 karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL);
294 if (!karg.list)
295 return -ENOMEM;
296
297 ret = -EFAULT;
298 if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int))))
299 goto out;
300
301 old_fs = get_fs();
302 set_fs(KERNEL_DS);
303 ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg);
304 set_fs(old_fs);
305
306out:
307 kfree(karg.list);
308
309 return ret;
310}
311
312typedef struct drm32_buf_pub {
313 int idx; /* Index into master buflist */
314 int total; /* Buffer size */
315 int used; /* Amount of buffer in use (for DMA) */
316 u32 address; /* Address of buffer (void *) */
317} drm32_buf_pub_t;
318
319typedef struct drm32_buf_map {
320 int count; /* Length of buflist */
321 u32 virtual; /* Mmaped area in user-virtual (void *) */
322 u32 list; /* Buffer information (drm_buf_pub_t *) */
323} drm32_buf_map_t;
324#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t)
325
326static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
327{
328 drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg;
329 drm32_buf_pub_t *ulist;
330 drm_buf_map_t karg;
331 mm_segment_t old_fs;
332 int orig_count, ret, i;
333 u32 tmp1, tmp2;
334
335 if (get_user(karg.count, &uarg->count) ||
336 get_user(tmp1, &uarg->virtual) ||
337 get_user(tmp2, &uarg->list))
338 return -EFAULT;
339
340 karg.virtual = (void *) A(tmp1);
341 ulist = (drm32_buf_pub_t *) A(tmp2);
342
343 orig_count = karg.count;
344
345 karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL);
346 if (!karg.list)
347 return -ENOMEM;
348
349 ret = -EFAULT;
350 for (i = 0; i < karg.count; i++) {
351 if (get_user(karg.list[i].idx, &ulist[i].idx) ||
352 get_user(karg.list[i].total, &ulist[i].total) ||
353 get_user(karg.list[i].used, &ulist[i].used) ||
354 get_user(tmp1, &ulist[i].address))
355 goto out;
356
357 karg.list[i].address = (void *) A(tmp1);
358 }
359
360 old_fs = get_fs();
361 set_fs(KERNEL_DS);
362 ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg);
363 set_fs(old_fs);
364
365 if (!ret) {
366 for (i = 0; i < orig_count; i++) {
367 tmp1 = (u32) (long) karg.list[i].address;
368 if (put_user(karg.list[i].idx, &ulist[i].idx) ||
369 put_user(karg.list[i].total, &ulist[i].total) ||
370 put_user(karg.list[i].used, &ulist[i].used) ||
371 put_user(tmp1, &ulist[i].address)) {
372 ret = -EFAULT;
373 goto out;
374 }
375 }
376 if (put_user(karg.count, &uarg->count))
377 ret = -EFAULT;
378 }
379
380out:
381 kfree(karg.list);
382 return ret;
383}
384
385typedef struct drm32_dma {
386 /* Indices here refer to the offset into
387 buflist in drm_buf_get_t. */
388 int context; /* Context handle */
389 int send_count; /* Number of buffers to send */
390 u32 send_indices; /* List of handles to buffers (int *) */
391 u32 send_sizes; /* Lengths of data to send (int *) */
392 drm_dma_flags_t flags; /* Flags */
393 int request_count; /* Number of buffers requested */
394 int request_size; /* Desired size for buffers */
395 u32 request_indices; /* Buffer information (int *) */
396 u32 request_sizes; /* (int *) */
397 int granted_count; /* Number of buffers granted */
398} drm32_dma_t;
399#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t)
400
401/* RED PEN The DRM layer blindly dereferences the send/request
402 * indice/size arrays even though they are userland
403 * pointers. -DaveM
404 */
405static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg)
406{
407 drm32_dma_t *uarg = (drm32_dma_t *) arg;
408 int *u_si, *u_ss, *u_ri, *u_rs;
409 drm_dma_t karg;
410 mm_segment_t old_fs;
411 int ret;
412 u32 tmp1, tmp2, tmp3, tmp4;
413
414 karg.send_indices = karg.send_sizes = NULL;
415 karg.request_indices = karg.request_sizes = NULL;
416
417 if (get_user(karg.context, &uarg->context) ||
418 get_user(karg.send_count, &uarg->send_count) ||
419 get_user(tmp1, &uarg->send_indices) ||
420 get_user(tmp2, &uarg->send_sizes) ||
421 get_user(karg.flags, &uarg->flags) ||
422 get_user(karg.request_count, &uarg->request_count) ||
423 get_user(karg.request_size, &uarg->request_size) ||
424 get_user(tmp3, &uarg->request_indices) ||
425 get_user(tmp4, &uarg->request_sizes) ||
426 get_user(karg.granted_count, &uarg->granted_count))
427 return -EFAULT;
428
429 u_si = (int *) A(tmp1);
430 u_ss = (int *) A(tmp2);
431 u_ri = (int *) A(tmp3);
432 u_rs = (int *) A(tmp4);
433
434 if (karg.send_count) {
435 karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL);
436 karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL);
437
438 ret = -ENOMEM;
439 if (!karg.send_indices || !karg.send_sizes)
440 goto out;
441
442 ret = -EFAULT;
443 if (copy_from_user(karg.send_indices, u_si,
444 (karg.send_count * sizeof(int))) ||
445 copy_from_user(karg.send_sizes, u_ss,
446 (karg.send_count * sizeof(int))))
447 goto out;
448 }
449
450 if (karg.request_count) {
451 karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL);
452 karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL);
453
454 ret = -ENOMEM;
455 if (!karg.request_indices || !karg.request_sizes)
456 goto out;
457
458 ret = -EFAULT;
459 if (copy_from_user(karg.request_indices, u_ri,
460 (karg.request_count * sizeof(int))) ||
461 copy_from_user(karg.request_sizes, u_rs,
462 (karg.request_count * sizeof(int))))
463 goto out;
464 }
465
466 old_fs = get_fs();
467 set_fs(KERNEL_DS);
468 ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg);
469 set_fs(old_fs);
470
471 if (!ret) {
472 if (put_user(karg.context, &uarg->context) ||
473 put_user(karg.send_count, &uarg->send_count) ||
474 put_user(karg.flags, &uarg->flags) ||
475 put_user(karg.request_count, &uarg->request_count) ||
476 put_user(karg.request_size, &uarg->request_size) ||
477 put_user(karg.granted_count, &uarg->granted_count))
478 ret = -EFAULT;
479
480 if (karg.send_count) {
481 if (copy_to_user(u_si, karg.send_indices,
482 (karg.send_count * sizeof(int))) ||
483 copy_to_user(u_ss, karg.send_sizes,
484 (karg.send_count * sizeof(int))))
485 ret = -EFAULT;
486 }
487 if (karg.request_count) {
488 if (copy_to_user(u_ri, karg.request_indices,
489 (karg.request_count * sizeof(int))) ||
490 copy_to_user(u_rs, karg.request_sizes,
491 (karg.request_count * sizeof(int))))
492 ret = -EFAULT;
493 }
494 }
495
496out:
497 if (karg.send_indices)
498 kfree(karg.send_indices);
499 if (karg.send_sizes)
500 kfree(karg.send_sizes);
501 if (karg.request_indices)
502 kfree(karg.request_indices);
503 if (karg.request_sizes)
504 kfree(karg.request_sizes);
505
506 return ret;
507}
508
509typedef struct drm32_ctx_res {
510 int count;
511 u32 contexts; /* (drm_ctx_t *) */
512} drm32_ctx_res_t;
513#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t)
514
515static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg)
516{
517 drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg;
518 drm_ctx_t *ulist;
519 drm_ctx_res_t karg;
520 mm_segment_t old_fs;
521 int orig_count, ret;
522 u32 tmp;
523
524 karg.contexts = NULL;
525 if (get_user(karg.count, &uarg->count) ||
526 get_user(tmp, &uarg->contexts))
527 return -EFAULT;
528
529 ulist = (drm_ctx_t *) A(tmp);
530
531 orig_count = karg.count;
532 if (karg.count && ulist) {
533 karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL);
534 if (!karg.contexts)
535 return -ENOMEM;
536 if (copy_from_user(karg.contexts, ulist,
537 (karg.count * sizeof(drm_ctx_t)))) {
538 kfree(karg.contexts);
539 return -EFAULT;
540 }
541 }
542
543 old_fs = get_fs();
544 set_fs(KERNEL_DS);
545 ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg);
546 set_fs(old_fs);
547
548 if (!ret) {
549 if (orig_count) {
550 if (copy_to_user(ulist, karg.contexts,
551 (orig_count * sizeof(drm_ctx_t))))
552 ret = -EFAULT;
553 }
554 if (put_user(karg.count, &uarg->count))
555 ret = -EFAULT;
556 }
557
558 if (karg.contexts)
559 kfree(karg.contexts);
560
561 return ret;
562}
563
564#endif
565
566#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
567#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl)
568
569#define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = {
570#define IOCTL_TABLE_END };
571
572IOCTL_TABLE_START
573#include <linux/compat_ioctl.h>
574
575#define DECLARES
576#include "compat_ioctl.c"
577
578/* Might be moved to compat_ioctl.h with some ifdefs... */
579COMPATIBLE_IOCTL(TIOCSTART)
580COMPATIBLE_IOCTL(TIOCSTOP)
581COMPATIBLE_IOCTL(TIOCSLTC)
582
583/* PA-specific ioctls */
584COMPATIBLE_IOCTL(PA_PERF_ON)
585COMPATIBLE_IOCTL(PA_PERF_OFF)
586COMPATIBLE_IOCTL(PA_PERF_VERSION)
587
588/* And these ioctls need translation */
589HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
590HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
591HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
592
593#if defined(CONFIG_GEN_RTC)
594COMPATIBLE_IOCTL(RTC_AIE_ON)
595COMPATIBLE_IOCTL(RTC_AIE_OFF)
596COMPATIBLE_IOCTL(RTC_UIE_ON)
597COMPATIBLE_IOCTL(RTC_UIE_OFF)
598COMPATIBLE_IOCTL(RTC_PIE_ON)
599COMPATIBLE_IOCTL(RTC_PIE_OFF)
600COMPATIBLE_IOCTL(RTC_WIE_ON)
601COMPATIBLE_IOCTL(RTC_WIE_OFF)
602COMPATIBLE_IOCTL(RTC_ALM_SET) /* struct rtc_time only has ints */
603COMPATIBLE_IOCTL(RTC_ALM_READ) /* struct rtc_time only has ints */
604COMPATIBLE_IOCTL(RTC_RD_TIME) /* struct rtc_time only has ints */
605COMPATIBLE_IOCTL(RTC_SET_TIME) /* struct rtc_time only has ints */
606HANDLE_IOCTL(RTC_IRQP_READ, w_long)
607COMPATIBLE_IOCTL(RTC_IRQP_SET)
608HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
609COMPATIBLE_IOCTL(RTC_EPOCH_SET)
610#endif
611
612#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
613HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version);
614HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique);
615HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique);
616HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap);
617HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs);
618HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs);
619HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs);
620HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma);
621HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx);
622#endif /* DRM */
623IOCTL_TABLE_END
624
625int 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 @@
1/*
2 * Code to handle x86 style IRQs plus some generic interrupt stuff.
3 *
4 * Copyright (C) 1992 Linus Torvalds
5 * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
6 * Copyright (C) 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
7 * Copyright (C) 1999-2000 Grant Grundler
8 * Copyright (c) 2005 Matthew Wilcox
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24#include <linux/bitops.h>
25#include <linux/config.h>
26#include <linux/errno.h>
27#include <linux/init.h>
28#include <linux/interrupt.h>
29#include <linux/kernel_stat.h>
30#include <linux/seq_file.h>
31#include <linux/spinlock.h>
32#include <linux/types.h>
33
34#undef PARISC_IRQ_CR16_COUNTS
35
36extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
37extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
38
39#define EIEM_MASK(irq) (1UL<<(CPU_IRQ_MAX - irq))
40
41/* Bits in EIEM correlate with cpu_irq_action[].
42** Numbered *Big Endian*! (ie bit 0 is MSB)
43*/
44static volatile unsigned long cpu_eiem = 0;
45
46static void cpu_set_eiem(void *info)
47{
48 set_eiem((unsigned long) info);
49}
50
51static inline void cpu_disable_irq(unsigned int irq)
52{
53 unsigned long eirr_bit = EIEM_MASK(irq);
54
55 cpu_eiem &= ~eirr_bit;
56 on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
57}
58
59static void cpu_enable_irq(unsigned int irq)
60{
61 unsigned long eirr_bit = EIEM_MASK(irq);
62
63 mtctl(eirr_bit, 23); /* clear EIRR bit before unmasking */
64 cpu_eiem |= eirr_bit;
65 on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
66}
67
68static unsigned int cpu_startup_irq(unsigned int irq)
69{
70 cpu_enable_irq(irq);
71 return 0;
72}
73
74void no_ack_irq(unsigned int irq) { }
75void no_end_irq(unsigned int irq) { }
76
77static struct hw_interrupt_type cpu_interrupt_type = {
78 .typename = "CPU",
79 .startup = cpu_startup_irq,
80 .shutdown = cpu_disable_irq,
81 .enable = cpu_enable_irq,
82 .disable = cpu_disable_irq,
83 .ack = no_ack_irq,
84 .end = no_end_irq,
85// .set_affinity = cpu_set_affinity_irq,
86};
87
88int show_interrupts(struct seq_file *p, void *v)
89{
90 int i = *(loff_t *) v, j;
91 unsigned long flags;
92
93 if (i == 0) {
94 seq_puts(p, " ");
95 for_each_online_cpu(j)
96 seq_printf(p, " CPU%d", j);
97
98#ifdef PARISC_IRQ_CR16_COUNTS
99 seq_printf(p, " [min/avg/max] (CPU cycle counts)");
100#endif
101 seq_putc(p, '\n');
102 }
103
104 if (i < NR_IRQS) {
105 struct irqaction *action;
106
107 spin_lock_irqsave(&irq_desc[i].lock, flags);
108 action = irq_desc[i].action;
109 if (!action)
110 goto skip;
111 seq_printf(p, "%3d: ", i);
112#ifdef CONFIG_SMP
113 for_each_online_cpu(j)
114 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
115#else
116 seq_printf(p, "%10u ", kstat_irqs(i));
117#endif
118
119 seq_printf(p, " %14s", irq_desc[i].handler->typename);
120#ifndef PARISC_IRQ_CR16_COUNTS
121 seq_printf(p, " %s", action->name);
122
123 while ((action = action->next))
124 seq_printf(p, ", %s", action->name);
125#else
126 for ( ;action; action = action->next) {
127 unsigned int k, avg, min, max;
128
129 min = max = action->cr16_hist[0];
130
131 for (avg = k = 0; k < PARISC_CR16_HIST_SIZE; k++) {
132 int hist = action->cr16_hist[k];
133
134 if (hist) {
135 avg += hist;
136 } else
137 break;
138
139 if (hist > max) max = hist;
140 if (hist < min) min = hist;
141 }
142
143 avg /= k;
144 seq_printf(p, " %s[%d/%d/%d]", action->name,
145 min,avg,max);
146 }
147#endif
148
149 seq_putc(p, '\n');
150 skip:
151 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
152 }
153
154 return 0;
155}
156
157
158
159/*
160** The following form a "set": Virtual IRQ, Transaction Address, Trans Data.
161** Respectively, these map to IRQ region+EIRR, Processor HPA, EIRR bit.
162**
163** To use txn_XXX() interfaces, get a Virtual IRQ first.
164** Then use that to get the Transaction address and data.
165*/
166
167int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *type, void *data)
168{
169 if (irq_desc[irq].action)
170 return -EBUSY;
171 if (irq_desc[irq].handler != &cpu_interrupt_type)
172 return -EBUSY;
173
174 if (type) {
175 irq_desc[irq].handler = type;
176 irq_desc[irq].handler_data = data;
177 cpu_interrupt_type.enable(irq);
178 }
179 return 0;
180}
181
182int txn_claim_irq(int irq)
183{
184 return cpu_claim_irq(irq, NULL, NULL) ? -1 : irq;
185}
186
187/*
188 * The bits_wide parameter accommodates the limitations of the HW/SW which
189 * use these bits:
190 * Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register)
191 * V-class (EPIC): 6 bits
192 * N/L/A-class (iosapic): 8 bits
193 * PCI 2.2 MSI: 16 bits
194 * Some PCI devices: 32 bits (Symbios SCSI/ATM/HyperFabric)
195 *
196 * On the service provider side:
197 * o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register)
198 * o PA 2.0 wide mode 6-bits (per processor)
199 * o IA64 8-bits (0-256 total)
200 *
201 * So a Legacy PA I/O device on a PA 2.0 box can't use all the bits supported
202 * by the processor...and the N/L-class I/O subsystem supports more bits than
203 * PA2.0 has. The first case is the problem.
204 */
205int txn_alloc_irq(unsigned int bits_wide)
206{
207 int irq;
208
209 /* never return irq 0 cause that's the interval timer */
210 for (irq = CPU_IRQ_BASE + 1; irq <= CPU_IRQ_MAX; irq++) {
211 if (cpu_claim_irq(irq, NULL, NULL) < 0)
212 continue;
213 if ((irq - CPU_IRQ_BASE) >= (1 << bits_wide))
214 continue;
215 return irq;
216 }
217
218 /* unlikely, but be prepared */
219 return -1;
220}
221
222unsigned long txn_alloc_addr(unsigned int virt_irq)
223{
224 static int next_cpu = -1;
225
226 next_cpu++; /* assign to "next" CPU we want this bugger on */
227
228 /* validate entry */
229 while ((next_cpu < NR_CPUS) && (!cpu_data[next_cpu].txn_addr ||
230 !cpu_online(next_cpu)))
231 next_cpu++;
232
233 if (next_cpu >= NR_CPUS)
234 next_cpu = 0; /* nothing else, assign monarch */
235
236 return cpu_data[next_cpu].txn_addr;
237}
238
239
240unsigned int txn_alloc_data(unsigned int virt_irq)
241{
242 return virt_irq - CPU_IRQ_BASE;
243}
244
245/* ONLY called from entry.S:intr_extint() */
246void do_cpu_irq_mask(struct pt_regs *regs)
247{
248 unsigned long eirr_val;
249
250 irq_enter();
251
252 /*
253 * Only allow interrupt processing to be interrupted by the
254 * timer tick
255 */
256 set_eiem(EIEM_MASK(TIMER_IRQ));
257
258 /* 1) only process IRQs that are enabled/unmasked (cpu_eiem)
259 * 2) We loop here on EIRR contents in order to avoid
260 * nested interrupts or having to take another interrupt
261 * when we could have just handled it right away.
262 */
263 for (;;) {
264 unsigned long bit = (1UL << (BITS_PER_LONG - 1));
265 unsigned int irq;
266 eirr_val = mfctl(23) & cpu_eiem;
267 if (!eirr_val)
268 break;
269
270 if (eirr_val & EIEM_MASK(TIMER_IRQ))
271 set_eiem(0);
272
273 mtctl(eirr_val, 23); /* reset bits we are going to process */
274
275 /* Work our way from MSb to LSb...same order we alloc EIRs */
276 for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) {
277 if (!(bit & eirr_val))
278 continue;
279
280 /* clear bit in mask - can exit loop sooner */
281 eirr_val &= ~bit;
282
283 __do_IRQ(irq, regs);
284 }
285 }
286 set_eiem(cpu_eiem);
287 irq_exit();
288}
289
290
291static struct irqaction timer_action = {
292 .handler = timer_interrupt,
293 .name = "timer",
294};
295
296#ifdef CONFIG_SMP
297static struct irqaction ipi_action = {
298 .handler = ipi_interrupt,
299 .name = "IPI",
300};
301#endif
302
303static void claim_cpu_irqs(void)
304{
305 int i;
306 for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) {
307 irq_desc[i].handler = &cpu_interrupt_type;
308 }
309
310 irq_desc[TIMER_IRQ].action = &timer_action;
311 irq_desc[TIMER_IRQ].status |= IRQ_PER_CPU;
312#ifdef CONFIG_SMP
313 irq_desc[IPI_IRQ].action = &ipi_action;
314 irq_desc[IPI_IRQ].status = IRQ_PER_CPU;
315#endif
316}
317
318void __init init_IRQ(void)
319{
320 local_irq_disable(); /* PARANOID - should already be disabled */
321 mtctl(~0UL, 23); /* EIRR : clear all pending external intr */
322 claim_cpu_irqs();
323#ifdef CONFIG_SMP
324 if (!cpu_eiem)
325 cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ);
326#else
327 cpu_eiem = EIEM_MASK(TIMER_IRQ);
328#endif
329 set_eiem(cpu_eiem); /* EIEM : enable all external intr */
330
331}
332
333void hw_resend_irq(struct hw_interrupt_type *type, unsigned int irq)
334{
335 /* XXX: Needs to be written. We managed without it so far, but
336 * we really ought to write it.
337 */
338}
339
340void ack_bad_irq(unsigned int irq)
341{
342 printk("unexpected IRQ %d\n", irq);
343}
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 @@
1/* Kernel dynamically loadable module help for PARISC.
2 *
3 * The best reference for this stuff is probably the Processor-
4 * Specific ELF Supplement for PA-RISC:
5 * http://ftp.parisc-linux.org/docs/arch/elf-pa-hp.pdf
6 *
7 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
8 * Copyright (C) 2003 Randolph Chung <tausq at debian . org>
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 *
26 * Notes:
27 * - SEGREL32 handling
28 * We are not doing SEGREL32 handling correctly. According to the ABI, we
29 * should do a value offset, like this:
30 * if (is_init(me, (void *)val))
31 * val -= (uint32_t)me->module_init;
32 * else
33 * val -= (uint32_t)me->module_core;
34 * However, SEGREL32 is used only for PARISC unwind entries, and we want
35 * those entries to have an absolute address, and not just an offset.
36 *
37 * The unwind table mechanism has the ability to specify an offset for
38 * the unwind table; however, because we split off the init functions into
39 * a different piece of memory, it is not possible to do this using a
40 * single offset. Instead, we use the above hack for now.
41 */
42
43#include <linux/moduleloader.h>
44#include <linux/elf.h>
45#include <linux/vmalloc.h>
46#include <linux/fs.h>
47#include <linux/string.h>
48#include <linux/kernel.h>
49
50#include <asm/unwind.h>
51
52#if 0
53#define DEBUGP printk
54#else
55#define DEBUGP(fmt...)
56#endif
57
58#define CHECK_RELOC(val, bits) \
59 if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
60 ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \
61 printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \
62 me->name, strtab + sym->st_name, (unsigned long)val, bits); \
63 return -ENOEXEC; \
64 }
65
66/* Maximum number of GOT entries. We use a long displacement ldd from
67 * the bottom of the table, which has a maximum signed displacement of
68 * 0x3fff; however, since we're only going forward, this becomes
69 * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have
70 * at most 1023 entries */
71#define MAX_GOTS 1023
72
73/* three functions to determine where in the module core
74 * or init pieces the location is */
75static inline int is_init(struct module *me, void *loc)
76{
77 return (loc >= me->module_init &&
78 loc <= (me->module_init + me->init_size));
79}
80
81static inline int is_core(struct module *me, void *loc)
82{
83 return (loc >= me->module_core &&
84 loc <= (me->module_core + me->core_size));
85}
86
87static inline int is_local(struct module *me, void *loc)
88{
89 return is_init(me, loc) || is_core(me, loc);
90}
91
92
93#ifndef __LP64__
94struct got_entry {
95 Elf32_Addr addr;
96};
97
98#define Elf_Fdesc Elf32_Fdesc
99
100struct stub_entry {
101 Elf32_Word insns[2]; /* each stub entry has two insns */
102};
103#else
104struct got_entry {
105 Elf64_Addr addr;
106};
107
108#define Elf_Fdesc Elf64_Fdesc
109
110struct stub_entry {
111 Elf64_Word insns[4]; /* each stub entry has four insns */
112};
113#endif
114
115/* Field selection types defined by hppa */
116#define rnd(x) (((x)+0x1000)&~0x1fff)
117/* fsel: full 32 bits */
118#define fsel(v,a) ((v)+(a))
119/* lsel: select left 21 bits */
120#define lsel(v,a) (((v)+(a))>>11)
121/* rsel: select right 11 bits */
122#define rsel(v,a) (((v)+(a))&0x7ff)
123/* lrsel with rounding of addend to nearest 8k */
124#define lrsel(v,a) (((v)+rnd(a))>>11)
125/* rrsel with rounding of addend to nearest 8k */
126#define rrsel(v,a) ((((v)+rnd(a))&0x7ff)+((a)-rnd(a)))
127
128#define mask(x,sz) ((x) & ~((1<<(sz))-1))
129
130
131/* The reassemble_* functions prepare an immediate value for
132 insertion into an opcode. pa-risc uses all sorts of weird bitfields
133 in the instruction to hold the value. */
134static inline int reassemble_14(int as14)
135{
136 return (((as14 & 0x1fff) << 1) |
137 ((as14 & 0x2000) >> 13));
138}
139
140static inline int reassemble_17(int as17)
141{
142 return (((as17 & 0x10000) >> 16) |
143 ((as17 & 0x0f800) << 5) |
144 ((as17 & 0x00400) >> 8) |
145 ((as17 & 0x003ff) << 3));
146}
147
148static inline int reassemble_21(int as21)
149{
150 return (((as21 & 0x100000) >> 20) |
151 ((as21 & 0x0ffe00) >> 8) |
152 ((as21 & 0x000180) << 7) |
153 ((as21 & 0x00007c) << 14) |
154 ((as21 & 0x000003) << 12));
155}
156
157static inline int reassemble_22(int as22)
158{
159 return (((as22 & 0x200000) >> 21) |
160 ((as22 & 0x1f0000) << 5) |
161 ((as22 & 0x00f800) << 5) |
162 ((as22 & 0x000400) >> 8) |
163 ((as22 & 0x0003ff) << 3));
164}
165
166void *module_alloc(unsigned long size)
167{
168 if (size == 0)
169 return NULL;
170 return vmalloc(size);
171}
172
173#ifndef __LP64__
174static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n)
175{
176 return 0;
177}
178
179static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n)
180{
181 return 0;
182}
183
184static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
185{
186 unsigned long cnt = 0;
187
188 for (; n > 0; n--, rela++)
189 {
190 switch (ELF32_R_TYPE(rela->r_info)) {
191 case R_PARISC_PCREL17F:
192 case R_PARISC_PCREL22F:
193 cnt++;
194 }
195 }
196
197 return cnt;
198}
199#else
200static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n)
201{
202 unsigned long cnt = 0;
203
204 for (; n > 0; n--, rela++)
205 {
206 switch (ELF64_R_TYPE(rela->r_info)) {
207 case R_PARISC_LTOFF21L:
208 case R_PARISC_LTOFF14R:
209 case R_PARISC_PCREL22F:
210 cnt++;
211 }
212 }
213
214 return cnt;
215}
216
217static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n)
218{
219 unsigned long cnt = 0;
220
221 for (; n > 0; n--, rela++)
222 {
223 switch (ELF64_R_TYPE(rela->r_info)) {
224 case R_PARISC_FPTR64:
225 cnt++;
226 }
227 }
228
229 return cnt;
230}
231
232static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
233{
234 unsigned long cnt = 0;
235
236 for (; n > 0; n--, rela++)
237 {
238 switch (ELF64_R_TYPE(rela->r_info)) {
239 case R_PARISC_PCREL22F:
240 cnt++;
241 }
242 }
243
244 return cnt;
245}
246#endif
247
248
249/* Free memory returned from module_alloc */
250void module_free(struct module *mod, void *module_region)
251{
252 vfree(module_region);
253 /* FIXME: If module_region == mod->init_region, trim exception
254 table entries. */
255}
256
257#define CONST
258int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
259 CONST Elf_Shdr *sechdrs,
260 CONST char *secstrings,
261 struct module *me)
262{
263 unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0;
264 unsigned int i;
265
266 for (i = 1; i < hdr->e_shnum; i++) {
267 const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset;
268 unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels);
269
270 if (strncmp(secstrings + sechdrs[i].sh_name,
271 ".PARISC.unwind", 14) == 0)
272 me->arch.unwind_section = i;
273
274 if (sechdrs[i].sh_type != SHT_RELA)
275 continue;
276
277 /* some of these are not relevant for 32-bit/64-bit
278 * we leave them here to make the code common. the
279 * compiler will do its thing and optimize out the
280 * stuff we don't need
281 */
282 gots += count_gots(rels, nrels);
283 fdescs += count_fdescs(rels, nrels);
284 if(strncmp(secstrings + sechdrs[i].sh_name,
285 ".rela.init", 10) == 0)
286 init_stubs += count_stubs(rels, nrels);
287 else
288 stubs += count_stubs(rels, nrels);
289 }
290
291 /* align things a bit */
292 me->core_size = ALIGN(me->core_size, 16);
293 me->arch.got_offset = me->core_size;
294 me->core_size += gots * sizeof(struct got_entry);
295
296 me->core_size = ALIGN(me->core_size, 16);
297 me->arch.fdesc_offset = me->core_size;
298 me->core_size += fdescs * sizeof(Elf_Fdesc);
299
300 me->core_size = ALIGN(me->core_size, 16);
301 me->arch.stub_offset = me->core_size;
302 me->core_size += stubs * sizeof(struct stub_entry);
303
304 me->init_size = ALIGN(me->init_size, 16);
305 me->arch.init_stub_offset = me->init_size;
306 me->init_size += init_stubs * sizeof(struct stub_entry);
307
308 me->arch.got_max = gots;
309 me->arch.fdesc_max = fdescs;
310 me->arch.stub_max = stubs;
311 me->arch.init_stub_max = init_stubs;
312
313 return 0;
314}
315
316#ifdef __LP64__
317static Elf64_Word get_got(struct module *me, unsigned long value, long addend)
318{
319 unsigned int i;
320 struct got_entry *got;
321
322 value += addend;
323
324 BUG_ON(value == 0);
325
326 got = me->module_core + me->arch.got_offset;
327 for (i = 0; got[i].addr; i++)
328 if (got[i].addr == value)
329 goto out;
330
331 BUG_ON(++me->arch.got_count > me->arch.got_max);
332
333 got[i].addr = value;
334 out:
335 DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry),
336 value);
337 return i * sizeof(struct got_entry);
338}
339#endif /* __LP64__ */
340
341#ifdef __LP64__
342static Elf_Addr get_fdesc(struct module *me, unsigned long value)
343{
344 Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
345
346 if (!value) {
347 printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
348 return 0;
349 }
350
351 /* Look for existing fdesc entry. */
352 while (fdesc->addr) {
353 if (fdesc->addr == value)
354 return (Elf_Addr)fdesc;
355 fdesc++;
356 }
357
358 BUG_ON(++me->arch.fdesc_count > me->arch.fdesc_max);
359
360 /* Create new one */
361 fdesc->addr = value;
362 fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
363 return (Elf_Addr)fdesc;
364}
365#endif /* __LP64__ */
366
367static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
368 int millicode, int init_section)
369{
370 unsigned long i;
371 struct stub_entry *stub;
372
373 if(init_section) {
374 i = me->arch.init_stub_count++;
375 BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
376 stub = me->module_init + me->arch.init_stub_offset +
377 i * sizeof(struct stub_entry);
378 } else {
379 i = me->arch.stub_count++;
380 BUG_ON(me->arch.stub_count > me->arch.stub_max);
381 stub = me->module_core + me->arch.stub_offset +
382 i * sizeof(struct stub_entry);
383 }
384
385#ifndef __LP64__
386/* for 32-bit the stub looks like this:
387 * ldil L'XXX,%r1
388 * be,n R'XXX(%sr4,%r1)
389 */
390 //value = *(unsigned long *)((value + addend) & ~3); /* why? */
391
392 stub->insns[0] = 0x20200000; /* ldil L'XXX,%r1 */
393 stub->insns[1] = 0xe0202002; /* be,n R'XXX(%sr4,%r1) */
394
395 stub->insns[0] |= reassemble_21(lrsel(value, addend));
396 stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4);
397
398#else
399/* for 64-bit we have two kinds of stubs:
400 * for normal function calls:
401 * ldd 0(%dp),%dp
402 * ldd 10(%dp), %r1
403 * bve (%r1)
404 * ldd 18(%dp), %dp
405 *
406 * for millicode:
407 * ldil 0, %r1
408 * ldo 0(%r1), %r1
409 * ldd 10(%r1), %r1
410 * bve,n (%r1)
411 */
412 if (!millicode)
413 {
414 stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */
415 stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */
416 stub->insns[2] = 0xe820d000; /* bve (%r1) */
417 stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */
418
419 stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff);
420 }
421 else
422 {
423 stub->insns[0] = 0x20200000; /* ldil 0,%r1 */
424 stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */
425 stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */
426 stub->insns[3] = 0xe820d002; /* bve,n (%r1) */
427
428 stub->insns[0] |= reassemble_21(lrsel(value, addend));
429 stub->insns[1] |= reassemble_14(rrsel(value, addend));
430 }
431#endif
432
433 return (Elf_Addr)stub;
434}
435
436int apply_relocate(Elf_Shdr *sechdrs,
437 const char *strtab,
438 unsigned int symindex,
439 unsigned int relsec,
440 struct module *me)
441{
442 /* parisc should not need this ... */
443 printk(KERN_ERR "module %s: RELOCATION unsupported\n",
444 me->name);
445 return -ENOEXEC;
446}
447
448#ifndef __LP64__
449int apply_relocate_add(Elf_Shdr *sechdrs,
450 const char *strtab,
451 unsigned int symindex,
452 unsigned int relsec,
453 struct module *me)
454{
455 int i;
456 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
457 Elf32_Sym *sym;
458 Elf32_Word *loc;
459 Elf32_Addr val;
460 Elf32_Sword addend;
461 Elf32_Addr dot;
462 //unsigned long dp = (unsigned long)$global$;
463 register unsigned long dp asm ("r27");
464
465 DEBUGP("Applying relocate section %u to %u\n", relsec,
466 sechdrs[relsec].sh_info);
467 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
468 /* This is where to make the change */
469 loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
470 + rel[i].r_offset;
471 /* This is the symbol it is referring to */
472 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
473 + ELF32_R_SYM(rel[i].r_info);
474 if (!sym->st_value) {
475 printk(KERN_WARNING "%s: Unknown symbol %s\n",
476 me->name, strtab + sym->st_name);
477 return -ENOENT;
478 }
479 //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
480 dot = (Elf32_Addr)loc & ~0x03;
481
482 val = sym->st_value;
483 addend = rel[i].r_addend;
484
485#if 0
486#define r(t) ELF32_R_TYPE(rel[i].r_info)==t ? #t :
487 DEBUGP("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n",
488 strtab + sym->st_name,
489 (uint32_t)loc, val, addend,
490 r(R_PARISC_PLABEL32)
491 r(R_PARISC_DIR32)
492 r(R_PARISC_DIR21L)
493 r(R_PARISC_DIR14R)
494 r(R_PARISC_SEGREL32)
495 r(R_PARISC_DPREL21L)
496 r(R_PARISC_DPREL14R)
497 r(R_PARISC_PCREL17F)
498 r(R_PARISC_PCREL22F)
499 "UNKNOWN");
500#undef r
501#endif
502
503 switch (ELF32_R_TYPE(rel[i].r_info)) {
504 case R_PARISC_PLABEL32:
505 /* 32-bit function address */
506 /* no function descriptors... */
507 *loc = fsel(val, addend);
508 break;
509 case R_PARISC_DIR32:
510 /* direct 32-bit ref */
511 *loc = fsel(val, addend);
512 break;
513 case R_PARISC_DIR21L:
514 /* left 21 bits of effective address */
515 val = lrsel(val, addend);
516 *loc = mask(*loc, 21) | reassemble_21(val);
517 break;
518 case R_PARISC_DIR14R:
519 /* right 14 bits of effective address */
520 val = rrsel(val, addend);
521 *loc = mask(*loc, 14) | reassemble_14(val);
522 break;
523 case R_PARISC_SEGREL32:
524 /* 32-bit segment relative address */
525 /* See note about special handling of SEGREL32 at
526 * the beginning of this file.
527 */
528 *loc = fsel(val, addend);
529 break;
530 case R_PARISC_DPREL21L:
531 /* left 21 bit of relative address */
532 val = lrsel(val - dp, addend);
533 *loc = mask(*loc, 21) | reassemble_21(val);
534 break;
535 case R_PARISC_DPREL14R:
536 /* right 14 bit of relative address */
537 val = rrsel(val - dp, addend);
538 *loc = mask(*loc, 14) | reassemble_14(val);
539 break;
540 case R_PARISC_PCREL17F:
541 /* 17-bit PC relative address */
542 val = get_stub(me, val, addend, 0, is_init(me, loc));
543 val = (val - dot - 8)/4;
544 CHECK_RELOC(val, 17)
545 *loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
546 break;
547 case R_PARISC_PCREL22F:
548 /* 22-bit PC relative address; only defined for pa20 */
549 val = get_stub(me, val, addend, 0, is_init(me, loc));
550 DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n",
551 strtab + sym->st_name, (unsigned long)loc, addend,
552 val)
553 val = (val - dot - 8)/4;
554 CHECK_RELOC(val, 22);
555 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
556 break;
557
558 default:
559 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
560 me->name, ELF32_R_TYPE(rel[i].r_info));
561 return -ENOEXEC;
562 }
563 }
564
565 return 0;
566}
567
568#else
569int apply_relocate_add(Elf_Shdr *sechdrs,
570 const char *strtab,
571 unsigned int symindex,
572 unsigned int relsec,
573 struct module *me)
574{
575 int i;
576 Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
577 Elf64_Sym *sym;
578 Elf64_Word *loc;
579 Elf64_Xword *loc64;
580 Elf64_Addr val;
581 Elf64_Sxword addend;
582 Elf64_Addr dot;
583
584 DEBUGP("Applying relocate section %u to %u\n", relsec,
585 sechdrs[relsec].sh_info);
586 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
587 /* This is where to make the change */
588 loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
589 + rel[i].r_offset;
590 /* This is the symbol it is referring to */
591 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
592 + ELF64_R_SYM(rel[i].r_info);
593 if (!sym->st_value) {
594 printk(KERN_WARNING "%s: Unknown symbol %s\n",
595 me->name, strtab + sym->st_name);
596 return -ENOENT;
597 }
598 //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
599 dot = (Elf64_Addr)loc & ~0x03;
600 loc64 = (Elf64_Xword *)loc;
601
602 val = sym->st_value;
603 addend = rel[i].r_addend;
604
605#if 0
606#define r(t) ELF64_R_TYPE(rel[i].r_info)==t ? #t :
607 printk("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n",
608 strtab + sym->st_name,
609 loc, val, addend,
610 r(R_PARISC_LTOFF14R)
611 r(R_PARISC_LTOFF21L)
612 r(R_PARISC_PCREL22F)
613 r(R_PARISC_DIR64)
614 r(R_PARISC_SEGREL32)
615 r(R_PARISC_FPTR64)
616 "UNKNOWN");
617#undef r
618#endif
619
620 switch (ELF64_R_TYPE(rel[i].r_info)) {
621 case R_PARISC_LTOFF21L:
622 /* LT-relative; left 21 bits */
623 val = get_got(me, val, addend);
624 DEBUGP("LTOFF21L Symbol %s loc %p val %lx\n",
625 strtab + sym->st_name,
626 loc, val);
627 val = lrsel(val, 0);
628 *loc = mask(*loc, 21) | reassemble_21(val);
629 break;
630 case R_PARISC_LTOFF14R:
631 /* L(ltoff(val+addend)) */
632 /* LT-relative; right 14 bits */
633 val = get_got(me, val, addend);
634 val = rrsel(val, 0);
635 DEBUGP("LTOFF14R Symbol %s loc %p val %lx\n",
636 strtab + sym->st_name,
637 loc, val);
638 *loc = mask(*loc, 14) | reassemble_14(val);
639 break;
640 case R_PARISC_PCREL22F:
641 /* PC-relative; 22 bits */
642 DEBUGP("PCREL22F Symbol %s loc %p val %lx\n",
643 strtab + sym->st_name,
644 loc, val);
645 /* can we reach it locally? */
646 if(!is_local(me, (void *)val)) {
647 if (strncmp(strtab + sym->st_name, "$$", 2)
648 == 0)
649 val = get_stub(me, val, addend, 1,
650 is_init(me, loc));
651 else
652 val = get_stub(me, val, addend, 0,
653 is_init(me, loc));
654 }
655 DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n",
656 strtab + sym->st_name, loc, sym->st_value,
657 addend, val);
658 /* FIXME: local symbols work as long as the
659 * core and init pieces aren't separated too
660 * far. If this is ever broken, you will trip
661 * the check below. The way to fix it would
662 * be to generate local stubs to go between init
663 * and core */
664 if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 ||
665 (Elf64_Sxword)(val - dot - 8) < -0x800000) {
666 printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n",
667 me->name, strtab + sym->st_name);
668 return -ENOEXEC;
669 }
670 val = (val - dot - 8)/4;
671 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
672 break;
673 case R_PARISC_DIR64:
674 /* 64-bit effective address */
675 *loc64 = val + addend;
676 break;
677 case R_PARISC_SEGREL32:
678 /* 32-bit segment relative address */
679 /* See note about special handling of SEGREL32 at
680 * the beginning of this file.
681 */
682 *loc = fsel(val, addend);
683 break;
684 case R_PARISC_FPTR64:
685 /* 64-bit function address */
686 if(is_local(me, (void *)(val + addend))) {
687 *loc64 = get_fdesc(me, val+addend);
688 DEBUGP("FDESC for %s at %p points to %lx\n",
689 strtab + sym->st_name, *loc64,
690 ((Elf_Fdesc *)*loc64)->addr);
691 } else {
692 /* if the symbol is not local to this
693 * module then val+addend is a pointer
694 * to the function descriptor */
695 DEBUGP("Non local FPTR64 Symbol %s loc %p val %lx\n",
696 strtab + sym->st_name,
697 loc, val);
698 *loc64 = val + addend;
699 }
700 break;
701
702 default:
703 printk(KERN_ERR "module %s: Unknown relocation: %Lu\n",
704 me->name, ELF64_R_TYPE(rel[i].r_info));
705 return -ENOEXEC;
706 }
707 }
708 return 0;
709}
710#endif
711
712static void
713register_unwind_table(struct module *me,
714 const Elf_Shdr *sechdrs)
715{
716 unsigned char *table, *end;
717 unsigned long gp;
718
719 if (!me->arch.unwind_section)
720 return;
721
722 table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
723 end = table + sechdrs[me->arch.unwind_section].sh_size;
724 gp = (Elf_Addr)me->module_core + me->arch.got_offset;
725
726 DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
727 me->arch.unwind_section, table, end, gp);
728 me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end);
729}
730
731static void
732deregister_unwind_table(struct module *me)
733{
734 if (me->arch.unwind)
735 unwind_table_remove(me->arch.unwind);
736}
737
738int module_finalize(const Elf_Ehdr *hdr,
739 const Elf_Shdr *sechdrs,
740 struct module *me)
741{
742 int i;
743 unsigned long nsyms;
744 const char *strtab = NULL;
745 Elf_Sym *newptr, *oldptr;
746 Elf_Shdr *symhdr = NULL;
747#ifdef DEBUG
748 Elf_Fdesc *entry;
749 u32 *addr;
750
751 entry = (Elf_Fdesc *)me->init;
752 printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry,
753 entry->gp, entry->addr);
754 addr = (u32 *)entry->addr;
755 printk("INSNS: %x %x %x %x\n",
756 addr[0], addr[1], addr[2], addr[3]);
757 printk("stubs used %ld, stubs max %ld\n"
758 "init_stubs used %ld, init stubs max %ld\n"
759 "got entries used %ld, gots max %ld\n"
760 "fdescs used %ld, fdescs max %ld\n",
761 me->arch.stub_count, me->arch.stub_max,
762 me->arch.init_stub_count, me->arch.init_stub_max,
763 me->arch.got_count, me->arch.got_max,
764 me->arch.fdesc_count, me->arch.fdesc_max);
765#endif
766
767 register_unwind_table(me, sechdrs);
768
769 /* haven't filled in me->symtab yet, so have to find it
770 * ourselves */
771 for (i = 1; i < hdr->e_shnum; i++) {
772 if(sechdrs[i].sh_type == SHT_SYMTAB
773 && (sechdrs[i].sh_type & SHF_ALLOC)) {
774 int strindex = sechdrs[i].sh_link;
775 /* FIXME: AWFUL HACK
776 * The cast is to drop the const from
777 * the sechdrs pointer */
778 symhdr = (Elf_Shdr *)&sechdrs[i];
779 strtab = (char *)sechdrs[strindex].sh_addr;
780 break;
781 }
782 }
783
784 DEBUGP("module %s: strtab %p, symhdr %p\n",
785 me->name, strtab, symhdr);
786
787 if(me->arch.got_count > MAX_GOTS) {
788 printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d\n", me->name, me->arch.got_count, MAX_GOTS);
789 return -EINVAL;
790 }
791
792 /* no symbol table */
793 if(symhdr == NULL)
794 return 0;
795
796 oldptr = (void *)symhdr->sh_addr;
797 newptr = oldptr + 1; /* we start counting at 1 */
798 nsyms = symhdr->sh_size / sizeof(Elf_Sym);
799 DEBUGP("OLD num_symtab %lu\n", nsyms);
800
801 for (i = 1; i < nsyms; i++) {
802 oldptr++; /* note, count starts at 1 so preincrement */
803 if(strncmp(strtab + oldptr->st_name,
804 ".L", 2) == 0)
805 continue;
806
807 if(newptr != oldptr)
808 *newptr++ = *oldptr;
809 else
810 newptr++;
811
812 }
813 nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
814 DEBUGP("NEW num_symtab %lu\n", nsyms);
815 symhdr->sh_size = nsyms * sizeof(Elf_Sym);
816 return 0;
817}
818
819void module_arch_cleanup(struct module *mod)
820{
821 deregister_unwind_table(mod);
822}
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 @@
1/*
2 * linux/arch/parisc/kernel/pa7300lc.c
3 * - PA7300LC-specific functions
4 *
5 * Copyright (C) 2000 Philipp Rumpf */
6
7#include <linux/sched.h>
8#include <linux/smp.h>
9#include <linux/kernel.h>
10#include <asm/io.h>
11#include <asm/ptrace.h>
12#include <asm/machdep.h>
13
14/* CPU register indices */
15
16#define MIOC_STATUS 0xf040
17#define MIOC_CONTROL 0xf080
18#define MDERRADD 0xf0e0
19#define DMAERR 0xf0e8
20#define DIOERR 0xf0ec
21#define HIDMAMEM 0xf0f4
22
23/* this returns the HPA of the CPU it was called on */
24static u32 cpu_hpa(void)
25{
26 return 0xfffb0000;
27}
28
29static void pa7300lc_lpmc(int code, struct pt_regs *regs)
30{
31 u32 hpa;
32 printk(KERN_WARNING "LPMC on CPU %d\n", smp_processor_id());
33
34 show_regs(regs);
35
36 hpa = cpu_hpa();
37 printk(KERN_WARNING
38 "MIOC_CONTROL %08x\n" "MIOC_STATUS %08x\n"
39 "MDERRADD %08x\n" "DMAERR %08x\n"
40 "DIOERR %08x\n" "HIDMAMEM %08x\n",
41 gsc_readl(hpa+MIOC_CONTROL), gsc_readl(hpa+MIOC_STATUS),
42 gsc_readl(hpa+MDERRADD), gsc_readl(hpa+DMAERR),
43 gsc_readl(hpa+DIOERR), gsc_readl(hpa+HIDMAMEM));
44}
45
46void pa7300lc_init(void)
47{
48 cpu_lpmc = pa7300lc_lpmc;
49}
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 @@
1/*
2 * PARISC TLB and cache flushing support
3 * Copyright (C) 2000-2001 Hewlett-Packard (John Marvin)
4 * Copyright (C) 2001 Matthew Wilcox (willy at parisc-linux.org)
5 * Copyright (C) 2002 Richard Hirst (rhirst with parisc-linux.org)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/*
23 * NOTE: fdc,fic, and pdc instructions that use base register modification
24 * should only use index and base registers that are not shadowed,
25 * so that the fast path emulation in the non access miss handler
26 * can be used.
27 */
28
29#ifdef __LP64__
30#define ADDIB addib,*
31#define CMPB cmpb,*
32#define ANDCM andcm,*
33
34 .level 2.0w
35#else
36#define ADDIB addib,
37#define CMPB cmpb,
38#define ANDCM andcm
39
40 .level 2.0
41#endif
42
43#include <asm/assembly.h>
44#include <asm/psw.h>
45#include <asm/pgtable.h>
46#include <asm/cache.h>
47
48 .text
49 .align 128
50
51 .export flush_tlb_all_local,code
52
53flush_tlb_all_local:
54 .proc
55 .callinfo NO_CALLS
56 .entry
57
58 /*
59 * The pitlbe and pdtlbe instructions should only be used to
60 * flush the entire tlb. Also, there needs to be no intervening
61 * tlb operations, e.g. tlb misses, so the operation needs
62 * to happen in real mode with all interruptions disabled.
63 */
64
65 /*
66 * Once again, we do the rfi dance ... some day we need examine
67 * all of our uses of this type of code and see what can be
68 * consolidated.
69 */
70
71 rsm PSW_SM_I, %r19 /* relied upon translation! PA 2.0 Arch. F-5 */
72 nop
73 nop
74 nop
75 nop
76 nop
77 nop
78 nop
79
80 rsm PSW_SM_Q, %r0 /* Turn off Q bit to load iia queue */
81 ldil L%REAL_MODE_PSW, %r1
82 ldo R%REAL_MODE_PSW(%r1), %r1
83 mtctl %r1, %cr22
84 mtctl %r0, %cr17 /* Clear IIASQ tail */
85 mtctl %r0, %cr17 /* Clear IIASQ head */
86 ldil L%PA(1f), %r1
87 ldo R%PA(1f)(%r1), %r1
88 mtctl %r1, %cr18 /* IIAOQ head */
89 ldo 4(%r1), %r1
90 mtctl %r1, %cr18 /* IIAOQ tail */
91 rfi
92 nop
93
941: ldil L%PA(cache_info), %r1
95 ldo R%PA(cache_info)(%r1), %r1
96
97 /* Flush Instruction Tlb */
98
99 LDREG ITLB_SID_BASE(%r1), %r20
100 LDREG ITLB_SID_STRIDE(%r1), %r21
101 LDREG ITLB_SID_COUNT(%r1), %r22
102 LDREG ITLB_OFF_BASE(%r1), %arg0
103 LDREG ITLB_OFF_STRIDE(%r1), %arg1
104 LDREG ITLB_OFF_COUNT(%r1), %arg2
105 LDREG ITLB_LOOP(%r1), %arg3
106
107 ADDIB= -1, %arg3, fitoneloop /* Preadjust and test */
108 movb,<,n %arg3, %r31, fitdone /* If loop < 0, skip */
109 copy %arg0, %r28 /* Init base addr */
110
111fitmanyloop: /* Loop if LOOP >= 2 */
112 mtsp %r20, %sr1
113 add %r21, %r20, %r20 /* increment space */
114 copy %arg2, %r29 /* Init middle loop count */
115
116fitmanymiddle: /* Loop if LOOP >= 2 */
117 ADDIB> -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
118 pitlbe 0(%sr1, %r28)
119 pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */
120 ADDIB> -1, %r29, fitmanymiddle /* Middle loop decr */
121 copy %arg3, %r31 /* Re-init inner loop count */
122
123 movb,tr %arg0, %r28, fitmanyloop /* Re-init base addr */
124 ADDIB<=,n -1, %r22, fitdone /* Outer loop count decr */
125
126fitoneloop: /* Loop if LOOP = 1 */
127 mtsp %r20, %sr1
128 copy %arg0, %r28 /* init base addr */
129 copy %arg2, %r29 /* init middle loop count */
130
131fitonemiddle: /* Loop if LOOP = 1 */
132 ADDIB> -1, %r29, fitonemiddle /* Middle loop count decr */
133 pitlbe,m %arg1(%sr1, %r28) /* pitlbe for one loop */
134
135 ADDIB> -1, %r22, fitoneloop /* Outer loop count decr */
136 add %r21, %r20, %r20 /* increment space */
137
138fitdone:
139
140 /* Flush Data Tlb */
141
142 LDREG DTLB_SID_BASE(%r1), %r20
143 LDREG DTLB_SID_STRIDE(%r1), %r21
144 LDREG DTLB_SID_COUNT(%r1), %r22
145 LDREG DTLB_OFF_BASE(%r1), %arg0
146 LDREG DTLB_OFF_STRIDE(%r1), %arg1
147 LDREG DTLB_OFF_COUNT(%r1), %arg2
148 LDREG DTLB_LOOP(%r1), %arg3
149
150 ADDIB= -1, %arg3, fdtoneloop /* Preadjust and test */
151 movb,<,n %arg3, %r31, fdtdone /* If loop < 0, skip */
152 copy %arg0, %r28 /* Init base addr */
153
154fdtmanyloop: /* Loop if LOOP >= 2 */
155 mtsp %r20, %sr1
156 add %r21, %r20, %r20 /* increment space */
157 copy %arg2, %r29 /* Init middle loop count */
158
159fdtmanymiddle: /* Loop if LOOP >= 2 */
160 ADDIB> -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
161 pdtlbe 0(%sr1, %r28)
162 pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */
163 ADDIB> -1, %r29, fdtmanymiddle /* Middle loop decr */
164 copy %arg3, %r31 /* Re-init inner loop count */
165
166 movb,tr %arg0, %r28, fdtmanyloop /* Re-init base addr */
167 ADDIB<=,n -1, %r22,fdtdone /* Outer loop count decr */
168
169fdtoneloop: /* Loop if LOOP = 1 */
170 mtsp %r20, %sr1
171 copy %arg0, %r28 /* init base addr */
172 copy %arg2, %r29 /* init middle loop count */
173
174fdtonemiddle: /* Loop if LOOP = 1 */
175 ADDIB> -1, %r29, fdtonemiddle /* Middle loop count decr */
176 pdtlbe,m %arg1(%sr1, %r28) /* pdtlbe for one loop */
177
178 ADDIB> -1, %r22, fdtoneloop /* Outer loop count decr */
179 add %r21, %r20, %r20 /* increment space */
180
181fdtdone:
182
183 /* Switch back to virtual mode */
184
185 rsm PSW_SM_Q, %r0 /* clear Q bit to load iia queue */
186 ldil L%KERNEL_PSW, %r1
187 ldo R%KERNEL_PSW(%r1), %r1
188 or %r1, %r19, %r1 /* Set I bit if set on entry */
189 mtctl %r1, %cr22
190 mtctl %r0, %cr17 /* Clear IIASQ tail */
191 mtctl %r0, %cr17 /* Clear IIASQ head */
192 ldil L%(2f), %r1
193 ldo R%(2f)(%r1), %r1
194 mtctl %r1, %cr18 /* IIAOQ head */
195 ldo 4(%r1), %r1
196 mtctl %r1, %cr18 /* IIAOQ tail */
197 rfi
198 nop
199
2002: bv %r0(%r2)
201 nop
202 .exit
203
204 .procend
205
206 .export flush_instruction_cache_local,code
207 .import cache_info,data
208
209flush_instruction_cache_local:
210 .proc
211 .callinfo NO_CALLS
212 .entry
213
214 mtsp %r0, %sr1
215 ldil L%cache_info, %r1
216 ldo R%cache_info(%r1), %r1
217
218 /* Flush Instruction Cache */
219
220 LDREG ICACHE_BASE(%r1), %arg0
221 LDREG ICACHE_STRIDE(%r1), %arg1
222 LDREG ICACHE_COUNT(%r1), %arg2
223 LDREG ICACHE_LOOP(%r1), %arg3
224 rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/
225 ADDIB= -1, %arg3, fioneloop /* Preadjust and test */
226 movb,<,n %arg3, %r31, fisync /* If loop < 0, do sync */
227
228fimanyloop: /* Loop if LOOP >= 2 */
229 ADDIB> -1, %r31, fimanyloop /* Adjusted inner loop decr */
230 fice 0(%sr1, %arg0)
231 fice,m %arg1(%sr1, %arg0) /* Last fice and addr adjust */
232 movb,tr %arg3, %r31, fimanyloop /* Re-init inner loop count */
233 ADDIB<=,n -1, %arg2, fisync /* Outer loop decr */
234
235fioneloop: /* Loop if LOOP = 1 */
236 ADDIB> -1, %arg2, fioneloop /* Outer loop count decr */
237 fice,m %arg1(%sr1, %arg0) /* Fice for one loop */
238
239fisync:
240 sync
241 mtsm %r22
242 bv %r0(%r2)
243 nop
244 .exit
245
246 .procend
247
248 .export flush_data_cache_local, code
249 .import cache_info, data
250
251flush_data_cache_local:
252 .proc
253 .callinfo NO_CALLS
254 .entry
255
256 mtsp %r0, %sr1
257 ldil L%cache_info, %r1
258 ldo R%cache_info(%r1), %r1
259
260 /* Flush Data Cache */
261
262 LDREG DCACHE_BASE(%r1), %arg0
263 LDREG DCACHE_STRIDE(%r1), %arg1
264 LDREG DCACHE_COUNT(%r1), %arg2
265 LDREG DCACHE_LOOP(%r1), %arg3
266 rsm PSW_SM_I, %r22
267 ADDIB= -1, %arg3, fdoneloop /* Preadjust and test */
268 movb,<,n %arg3, %r31, fdsync /* If loop < 0, do sync */
269
270fdmanyloop: /* Loop if LOOP >= 2 */
271 ADDIB> -1, %r31, fdmanyloop /* Adjusted inner loop decr */
272 fdce 0(%sr1, %arg0)
273 fdce,m %arg1(%sr1, %arg0) /* Last fdce and addr adjust */
274 movb,tr %arg3, %r31, fdmanyloop /* Re-init inner loop count */
275 ADDIB<=,n -1, %arg2, fdsync /* Outer loop decr */
276
277fdoneloop: /* Loop if LOOP = 1 */
278 ADDIB> -1, %arg2, fdoneloop /* Outer loop count decr */
279 fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */
280
281fdsync:
282 syncdma
283 sync
284 mtsm %r22
285 bv %r0(%r2)
286 nop
287 .exit
288
289 .procend
290
291 .export copy_user_page_asm,code
292 .align 16
293
294copy_user_page_asm:
295 .proc
296 .callinfo NO_CALLS
297 .entry
298
299#ifdef __LP64__
300 /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
301 * Unroll the loop by hand and arrange insn appropriately.
302 * GCC probably can do this just as well.
303 */
304
305 ldd 0(%r25), %r19
306 ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
307 ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */
308 ldw 128(%r25), %r0 /* prefetch 2 */
309
3101: ldd 8(%r25), %r20
311 ldw 192(%r25), %r0 /* prefetch 3 */
312 ldw 256(%r25), %r0 /* prefetch 4 */
313
314 ldd 16(%r25), %r21
315 ldd 24(%r25), %r22
316 std %r19, 0(%r26)
317 std %r20, 8(%r26)
318
319 ldd 32(%r25), %r19
320 ldd 40(%r25), %r20
321 std %r21, 16(%r26)
322 std %r22, 24(%r26)
323
324 ldd 48(%r25), %r21
325 ldd 56(%r25), %r22
326 std %r19, 32(%r26)
327 std %r20, 40(%r26)
328
329 ldd 64(%r25), %r19
330 ldd 72(%r25), %r20
331 std %r21, 48(%r26)
332 std %r22, 56(%r26)
333
334 ldd 80(%r25), %r21
335 ldd 88(%r25), %r22
336 std %r19, 64(%r26)
337 std %r20, 72(%r26)
338
339 ldd 96(%r25), %r19
340 ldd 104(%r25), %r20
341 std %r21, 80(%r26)
342 std %r22, 88(%r26)
343
344 ldd 112(%r25), %r21
345 ldd 120(%r25), %r22
346 std %r19, 96(%r26)
347 std %r20, 104(%r26)
348
349 ldo 128(%r25), %r25
350 std %r21, 112(%r26)
351 std %r22, 120(%r26)
352 ldo 128(%r26), %r26
353
354 ADDIB> -1, %r1, 1b /* bundle 10 */
355 ldd 0(%r25), %r19 /* start next loads */
356
357#else
358
359 /*
360 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
361 * bundles (very restricted rules for bundling).
362 * Note that until (if) we start saving
363 * the full 64 bit register values on interrupt, we can't
364 * use ldd/std on a 32 bit kernel.
365 */
366 ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
367
3681:
369 ldw 0(%r25), %r19
370 ldw 4(%r25), %r20
371 ldw 8(%r25), %r21
372 ldw 12(%r25), %r22
373 stw %r19, 0(%r26)
374 stw %r20, 4(%r26)
375 stw %r21, 8(%r26)
376 stw %r22, 12(%r26)
377 ldw 16(%r25), %r19
378 ldw 20(%r25), %r20
379 ldw 24(%r25), %r21
380 ldw 28(%r25), %r22
381 stw %r19, 16(%r26)
382 stw %r20, 20(%r26)
383 stw %r21, 24(%r26)
384 stw %r22, 28(%r26)
385 ldw 32(%r25), %r19
386 ldw 36(%r25), %r20
387 ldw 40(%r25), %r21
388 ldw 44(%r25), %r22
389 stw %r19, 32(%r26)
390 stw %r20, 36(%r26)
391 stw %r21, 40(%r26)
392 stw %r22, 44(%r26)
393 ldw 48(%r25), %r19
394 ldw 52(%r25), %r20
395 ldw 56(%r25), %r21
396 ldw 60(%r25), %r22
397 stw %r19, 48(%r26)
398 stw %r20, 52(%r26)
399 stw %r21, 56(%r26)
400 stw %r22, 60(%r26)
401 ldo 64(%r26), %r26
402 ADDIB> -1, %r1, 1b
403 ldo 64(%r25), %r25
404#endif
405 bv %r0(%r2)
406 nop
407 .exit
408
409 .procend
410
411/*
412 * NOTE: Code in clear_user_page has a hard coded dependency on the
413 * maximum alias boundary being 4 Mb. We've been assured by the
414 * parisc chip designers that there will not ever be a parisc
415 * chip with a larger alias boundary (Never say never :-) ).
416 *
417 * Subtle: the dtlb miss handlers support the temp alias region by
418 * "knowing" that if a dtlb miss happens within the temp alias
419 * region it must have occurred while in clear_user_page. Since
420 * this routine makes use of processor local translations, we
421 * don't want to insert them into the kernel page table. Instead,
422 * we load up some general registers (they need to be registers
423 * which aren't shadowed) with the physical page numbers (preshifted
424 * for tlb insertion) needed to insert the translations. When we
425 * miss on the translation, the dtlb miss handler inserts the
426 * translation into the tlb using these values:
427 *
428 * %r26 physical page (shifted for tlb insert) of "to" translation
429 * %r23 physical page (shifted for tlb insert) of "from" translation
430 */
431
432#if 0
433
434 /*
435 * We can't do this since copy_user_page is used to bring in
436 * file data that might have instructions. Since the data would
437 * then need to be flushed out so the i-fetch can see it, it
438 * makes more sense to just copy through the kernel translation
439 * and flush it.
440 *
441 * I'm still keeping this around because it may be possible to
442 * use it if more information is passed into copy_user_page().
443 * Have to do some measurements to see if it is worthwhile to
444 * lobby for such a change.
445 */
446
447 .export copy_user_page_asm,code
448
449copy_user_page_asm:
450 .proc
451 .callinfo NO_CALLS
452 .entry
453
454 ldil L%(__PAGE_OFFSET), %r1
455 sub %r26, %r1, %r26
456 sub %r25, %r1, %r23 /* move physical addr into non shadowed reg */
457
458 ldil L%(TMPALIAS_MAP_START), %r28
459#ifdef __LP64__
460 extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */
461 extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */
462 depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */
463 depdi 0, 63,12, %r28 /* Clear any offset bits */
464 copy %r28, %r29
465 depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */
466#else
467 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
468 extrw,u %r23, 24,25, %r23 /* convert phys addr to tlb insert format */
469 depw %r24, 31,22, %r28 /* Form aliased virtual address 'to' */
470 depwi 0, 31,12, %r28 /* Clear any offset bits */
471 copy %r28, %r29
472 depwi 1, 9,1, %r29 /* Form aliased virtual address 'from' */
473#endif
474
475 /* Purge any old translations */
476
477 pdtlb 0(%r28)
478 pdtlb 0(%r29)
479
480 ldi 64, %r1
481
482 /*
483 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
484 * bundles (very restricted rules for bundling). It probably
485 * does OK on PCXU and better, but we could do better with
486 * ldd/std instructions. Note that until (if) we start saving
487 * the full 64 bit register values on interrupt, we can't
488 * use ldd/std on a 32 bit kernel.
489 */
490
491
4921:
493 ldw 0(%r29), %r19
494 ldw 4(%r29), %r20
495 ldw 8(%r29), %r21
496 ldw 12(%r29), %r22
497 stw %r19, 0(%r28)
498 stw %r20, 4(%r28)
499 stw %r21, 8(%r28)
500 stw %r22, 12(%r28)
501 ldw 16(%r29), %r19
502 ldw 20(%r29), %r20
503 ldw 24(%r29), %r21
504 ldw 28(%r29), %r22
505 stw %r19, 16(%r28)
506 stw %r20, 20(%r28)
507 stw %r21, 24(%r28)
508 stw %r22, 28(%r28)
509 ldw 32(%r29), %r19
510 ldw 36(%r29), %r20
511 ldw 40(%r29), %r21
512 ldw 44(%r29), %r22
513 stw %r19, 32(%r28)
514 stw %r20, 36(%r28)
515 stw %r21, 40(%r28)
516 stw %r22, 44(%r28)
517 ldw 48(%r29), %r19
518 ldw 52(%r29), %r20
519 ldw 56(%r29), %r21
520 ldw 60(%r29), %r22
521 stw %r19, 48(%r28)
522 stw %r20, 52(%r28)
523 stw %r21, 56(%r28)
524 stw %r22, 60(%r28)
525 ldo 64(%r28), %r28
526 ADDIB> -1, %r1,1b
527 ldo 64(%r29), %r29
528
529 bv %r0(%r2)
530 nop
531 .exit
532
533 .procend
534#endif
535
536 .export __clear_user_page_asm,code
537
538__clear_user_page_asm:
539 .proc
540 .callinfo NO_CALLS
541 .entry
542
543 tophys_r1 %r26
544
545 ldil L%(TMPALIAS_MAP_START), %r28
546#ifdef __LP64__
547#if (TMPALIAS_MAP_START >= 0x80000000)
548 depdi 0, 31,32, %r28 /* clear any sign extension */
549#endif
550 extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
551 depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
552 depdi 0, 63,12, %r28 /* Clear any offset bits */
553#else
554 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
555 depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
556 depwi 0, 31,12, %r28 /* Clear any offset bits */
557#endif
558
559 /* Purge any old translation */
560
561 pdtlb 0(%r28)
562
563#ifdef __LP64__
564 ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
565
566 /* PREFETCH (Write) has not (yet) been proven to help here */
567/* #define PREFETCHW_OP ldd 256(%0), %r0 */
568
5691: std %r0, 0(%r28)
570 std %r0, 8(%r28)
571 std %r0, 16(%r28)
572 std %r0, 24(%r28)
573 std %r0, 32(%r28)
574 std %r0, 40(%r28)
575 std %r0, 48(%r28)
576 std %r0, 56(%r28)
577 std %r0, 64(%r28)
578 std %r0, 72(%r28)
579 std %r0, 80(%r28)
580 std %r0, 88(%r28)
581 std %r0, 96(%r28)
582 std %r0, 104(%r28)
583 std %r0, 112(%r28)
584 std %r0, 120(%r28)
585 ADDIB> -1, %r1, 1b
586 ldo 128(%r28), %r28
587
588#else /* ! __LP64 */
589
590 ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
591
5921:
593 stw %r0, 0(%r28)
594 stw %r0, 4(%r28)
595 stw %r0, 8(%r28)
596 stw %r0, 12(%r28)
597 stw %r0, 16(%r28)
598 stw %r0, 20(%r28)
599 stw %r0, 24(%r28)
600 stw %r0, 28(%r28)
601 stw %r0, 32(%r28)
602 stw %r0, 36(%r28)
603 stw %r0, 40(%r28)
604 stw %r0, 44(%r28)
605 stw %r0, 48(%r28)
606 stw %r0, 52(%r28)
607 stw %r0, 56(%r28)
608 stw %r0, 60(%r28)
609 ADDIB> -1, %r1, 1b
610 ldo 64(%r28), %r28
611#endif /* __LP64 */
612
613 bv %r0(%r2)
614 nop
615 .exit
616
617 .procend
618
619 .export flush_kernel_dcache_page
620
621flush_kernel_dcache_page:
622 .proc
623 .callinfo NO_CALLS
624 .entry
625
626 ldil L%dcache_stride, %r1
627 ldw R%dcache_stride(%r1), %r23
628
629#ifdef __LP64__
630 depdi,z 1, 63-PAGE_SHIFT,1, %r25
631#else
632 depwi,z 1, 31-PAGE_SHIFT,1, %r25
633#endif
634 add %r26, %r25, %r25
635 sub %r25, %r23, %r25
636
637
6381: fdc,m %r23(%r26)
639 fdc,m %r23(%r26)
640 fdc,m %r23(%r26)
641 fdc,m %r23(%r26)
642 fdc,m %r23(%r26)
643 fdc,m %r23(%r26)
644 fdc,m %r23(%r26)
645 fdc,m %r23(%r26)
646 fdc,m %r23(%r26)
647 fdc,m %r23(%r26)
648 fdc,m %r23(%r26)
649 fdc,m %r23(%r26)
650 fdc,m %r23(%r26)
651 fdc,m %r23(%r26)
652 fdc,m %r23(%r26)
653 CMPB<< %r26, %r25,1b
654 fdc,m %r23(%r26)
655
656 sync
657 bv %r0(%r2)
658 nop
659 .exit
660
661 .procend
662
663 .export flush_user_dcache_page
664
665flush_user_dcache_page:
666 .proc
667 .callinfo NO_CALLS
668 .entry
669
670 ldil L%dcache_stride, %r1
671 ldw R%dcache_stride(%r1), %r23
672
673#ifdef __LP64__
674 depdi,z 1,63-PAGE_SHIFT,1, %r25
675#else
676 depwi,z 1,31-PAGE_SHIFT,1, %r25
677#endif
678 add %r26, %r25, %r25
679 sub %r25, %r23, %r25
680
681
6821: fdc,m %r23(%sr3, %r26)
683 fdc,m %r23(%sr3, %r26)
684 fdc,m %r23(%sr3, %r26)
685 fdc,m %r23(%sr3, %r26)
686 fdc,m %r23(%sr3, %r26)
687 fdc,m %r23(%sr3, %r26)
688 fdc,m %r23(%sr3, %r26)
689 fdc,m %r23(%sr3, %r26)
690 fdc,m %r23(%sr3, %r26)
691 fdc,m %r23(%sr3, %r26)
692 fdc,m %r23(%sr3, %r26)
693 fdc,m %r23(%sr3, %r26)
694 fdc,m %r23(%sr3, %r26)
695 fdc,m %r23(%sr3, %r26)
696 fdc,m %r23(%sr3, %r26)
697 CMPB<< %r26, %r25,1b
698 fdc,m %r23(%sr3, %r26)
699
700 sync
701 bv %r0(%r2)
702 nop
703 .exit
704
705 .procend
706
707 .export flush_user_icache_page
708
709flush_user_icache_page:
710 .proc
711 .callinfo NO_CALLS
712 .entry
713
714 ldil L%dcache_stride, %r1
715 ldw R%dcache_stride(%r1), %r23
716
717#ifdef __LP64__
718 depdi,z 1, 63-PAGE_SHIFT,1, %r25
719#else
720 depwi,z 1, 31-PAGE_SHIFT,1, %r25
721#endif
722 add %r26, %r25, %r25
723 sub %r25, %r23, %r25
724
725
7261: fic,m %r23(%sr3, %r26)
727 fic,m %r23(%sr3, %r26)
728 fic,m %r23(%sr3, %r26)
729 fic,m %r23(%sr3, %r26)
730 fic,m %r23(%sr3, %r26)
731 fic,m %r23(%sr3, %r26)
732 fic,m %r23(%sr3, %r26)
733 fic,m %r23(%sr3, %r26)
734 fic,m %r23(%sr3, %r26)
735 fic,m %r23(%sr3, %r26)
736 fic,m %r23(%sr3, %r26)
737 fic,m %r23(%sr3, %r26)
738 fic,m %r23(%sr3, %r26)
739 fic,m %r23(%sr3, %r26)
740 fic,m %r23(%sr3, %r26)
741 CMPB<< %r26, %r25,1b
742 fic,m %r23(%sr3, %r26)
743
744 sync
745 bv %r0(%r2)
746 nop
747 .exit
748
749 .procend
750
751
752 .export purge_kernel_dcache_page
753
754purge_kernel_dcache_page:
755 .proc
756 .callinfo NO_CALLS
757 .entry
758
759 ldil L%dcache_stride, %r1
760 ldw R%dcache_stride(%r1), %r23
761
762#ifdef __LP64__
763 depdi,z 1, 63-PAGE_SHIFT,1, %r25
764#else
765 depwi,z 1, 31-PAGE_SHIFT,1, %r25
766#endif
767 add %r26, %r25, %r25
768 sub %r25, %r23, %r25
769
7701: pdc,m %r23(%r26)
771 pdc,m %r23(%r26)
772 pdc,m %r23(%r26)
773 pdc,m %r23(%r26)
774 pdc,m %r23(%r26)
775 pdc,m %r23(%r26)
776 pdc,m %r23(%r26)
777 pdc,m %r23(%r26)
778 pdc,m %r23(%r26)
779 pdc,m %r23(%r26)
780 pdc,m %r23(%r26)
781 pdc,m %r23(%r26)
782 pdc,m %r23(%r26)
783 pdc,m %r23(%r26)
784 pdc,m %r23(%r26)
785 CMPB<< %r26, %r25, 1b
786 pdc,m %r23(%r26)
787
788 sync
789 bv %r0(%r2)
790 nop
791 .exit
792
793 .procend
794
795#if 0
796 /* Currently not used, but it still is a possible alternate
797 * solution.
798 */
799
800 .export flush_alias_page
801
802flush_alias_page:
803 .proc
804 .callinfo NO_CALLS
805 .entry
806
807 tophys_r1 %r26
808
809 ldil L%(TMPALIAS_MAP_START), %r28
810#ifdef __LP64__
811 extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
812 depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
813 depdi 0, 63,12, %r28 /* Clear any offset bits */
814#else
815 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
816 depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
817 depwi 0, 31,12, %r28 /* Clear any offset bits */
818#endif
819
820 /* Purge any old translation */
821
822 pdtlb 0(%r28)
823
824 ldil L%dcache_stride, %r1
825 ldw R%dcache_stride(%r1), %r23
826
827#ifdef __LP64__
828 depdi,z 1, 63-PAGE_SHIFT,1, %r29
829#else
830 depwi,z 1, 31-PAGE_SHIFT,1, %r29
831#endif
832 add %r28, %r29, %r29
833 sub %r29, %r23, %r29
834
8351: fdc,m %r23(%r28)
836 fdc,m %r23(%r28)
837 fdc,m %r23(%r28)
838 fdc,m %r23(%r28)
839 fdc,m %r23(%r28)
840 fdc,m %r23(%r28)
841 fdc,m %r23(%r28)
842 fdc,m %r23(%r28)
843 fdc,m %r23(%r28)
844 fdc,m %r23(%r28)
845 fdc,m %r23(%r28)
846 fdc,m %r23(%r28)
847 fdc,m %r23(%r28)
848 fdc,m %r23(%r28)
849 fdc,m %r23(%r28)
850 CMPB<< %r28, %r29, 1b
851 fdc,m %r23(%r28)
852
853 sync
854 bv %r0(%r2)
855 nop
856 .exit
857
858 .procend
859#endif
860
861 .export flush_user_dcache_range_asm
862
863flush_user_dcache_range_asm:
864 .proc
865 .callinfo NO_CALLS
866 .entry
867
868 ldil L%dcache_stride, %r1
869 ldw R%dcache_stride(%r1), %r23
870 ldo -1(%r23), %r21
871 ANDCM %r26, %r21, %r26
872
8731: CMPB<<,n %r26, %r25, 1b
874 fdc,m %r23(%sr3, %r26)
875
876 sync
877 bv %r0(%r2)
878 nop
879 .exit
880
881 .procend
882
883 .export flush_kernel_dcache_range_asm
884
885flush_kernel_dcache_range_asm:
886 .proc
887 .callinfo NO_CALLS
888 .entry
889
890 ldil L%dcache_stride, %r1
891 ldw R%dcache_stride(%r1), %r23
892 ldo -1(%r23), %r21
893 ANDCM %r26, %r21, %r26
894
8951: CMPB<<,n %r26, %r25,1b
896 fdc,m %r23(%r26)
897
898 sync
899 syncdma
900 bv %r0(%r2)
901 nop
902 .exit
903
904 .procend
905
906 .export flush_user_icache_range_asm
907
908flush_user_icache_range_asm:
909 .proc
910 .callinfo NO_CALLS
911 .entry
912
913 ldil L%icache_stride, %r1
914 ldw R%icache_stride(%r1), %r23
915 ldo -1(%r23), %r21
916 ANDCM %r26, %r21, %r26
917
9181: CMPB<<,n %r26, %r25,1b
919 fic,m %r23(%sr3, %r26)
920
921 sync
922 bv %r0(%r2)
923 nop
924 .exit
925
926 .procend
927
928 .export flush_kernel_icache_page
929
930flush_kernel_icache_page:
931 .proc
932 .callinfo NO_CALLS
933 .entry
934
935 ldil L%icache_stride, %r1
936 ldw R%icache_stride(%r1), %r23
937
938#ifdef __LP64__
939 depdi,z 1, 63-PAGE_SHIFT,1, %r25
940#else
941 depwi,z 1, 31-PAGE_SHIFT,1, %r25
942#endif
943 add %r26, %r25, %r25
944 sub %r25, %r23, %r25
945
946
9471: fic,m %r23(%r26)
948 fic,m %r23(%r26)
949 fic,m %r23(%r26)
950 fic,m %r23(%r26)
951 fic,m %r23(%r26)
952 fic,m %r23(%r26)
953 fic,m %r23(%r26)
954 fic,m %r23(%r26)
955 fic,m %r23(%r26)
956 fic,m %r23(%r26)
957 fic,m %r23(%r26)
958 fic,m %r23(%r26)
959 fic,m %r23(%r26)
960 fic,m %r23(%r26)
961 fic,m %r23(%r26)
962 CMPB<< %r26, %r25, 1b
963 fic,m %r23(%r26)
964
965 sync
966 bv %r0(%r2)
967 nop
968 .exit
969
970 .procend
971
972 .export flush_kernel_icache_range_asm
973
974flush_kernel_icache_range_asm:
975 .proc
976 .callinfo NO_CALLS
977 .entry
978
979 ldil L%icache_stride, %r1
980 ldw R%icache_stride(%r1), %r23
981 ldo -1(%r23), %r21
982 ANDCM %r26, %r21, %r26
983
9841: CMPB<<,n %r26, %r25, 1b
985 fic,m %r23(%r26)
986
987 sync
988 bv %r0(%r2)
989 nop
990 .exit
991
992 .procend
993
994 .align 128
995
996 .export disable_sr_hashing_asm,code
997
998disable_sr_hashing_asm:
999 .proc
1000 .callinfo NO_CALLS
1001 .entry
1002
1003 /* Switch to real mode */
1004
1005 ssm 0, %r0 /* relied upon translation! */
1006 nop
1007 nop
1008 nop
1009 nop
1010 nop
1011 nop
1012 nop
1013
1014 rsm (PSW_SM_Q|PSW_SM_I), %r0 /* disable Q&I to load the iia queue */
1015 ldil L%REAL_MODE_PSW, %r1
1016 ldo R%REAL_MODE_PSW(%r1), %r1
1017 mtctl %r1, %cr22
1018 mtctl %r0, %cr17 /* Clear IIASQ tail */
1019 mtctl %r0, %cr17 /* Clear IIASQ head */
1020 ldil L%PA(1f), %r1
1021 ldo R%PA(1f)(%r1), %r1
1022 mtctl %r1, %cr18 /* IIAOQ head */
1023 ldo 4(%r1), %r1
1024 mtctl %r1, %cr18 /* IIAOQ tail */
1025 rfi
1026 nop
1027
10281: cmpib,=,n SRHASH_PCXST, %r26,srdis_pcxs
1029 cmpib,=,n SRHASH_PCXL, %r26,srdis_pcxl
1030 cmpib,=,n SRHASH_PA20, %r26,srdis_pa20
1031 b,n srdis_done
1032
1033srdis_pcxs:
1034
1035 /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
1036
1037 .word 0x141c1a00 /* mfdiag %dr0, %r28 */
1038 .word 0x141c1a00 /* must issue twice */
1039 depwi 0,18,1, %r28 /* Clear DHE (dcache hash enable) */
1040 depwi 0,20,1, %r28 /* Clear IHE (icache hash enable) */
1041 .word 0x141c1600 /* mtdiag %r28, %dr0 */
1042 .word 0x141c1600 /* must issue twice */
1043 b,n srdis_done
1044
1045srdis_pcxl:
1046
1047 /* Disable Space Register Hashing for PCXL */
1048
1049 .word 0x141c0600 /* mfdiag %dr0, %r28 */
1050 depwi 0,28,2, %r28 /* Clear DHASH_EN & IHASH_EN */
1051 .word 0x141c0240 /* mtdiag %r28, %dr0 */
1052 b,n srdis_done
1053
1054srdis_pa20:
1055
1056 /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */
1057
1058 .word 0x144008bc /* mfdiag %dr2, %r28 */
1059 depdi 0, 54,1, %r28 /* clear DIAG_SPHASH_ENAB (bit 54) */
1060 .word 0x145c1840 /* mtdiag %r28, %dr2 */
1061
1062srdis_done:
1063
1064 /* Switch back to virtual mode */
1065
1066 rsm PSW_SM_Q, %r0 /* clear Q bit to load iia queue */
1067 ldil L%KERNEL_PSW, %r1
1068 ldo R%KERNEL_PSW(%r1), %r1
1069 mtctl %r1, %cr22
1070 mtctl %r0, %cr17 /* Clear IIASQ tail */
1071 mtctl %r0, %cr17 /* Clear IIASQ head */
1072 ldil L%(2f), %r1
1073 ldo R%(2f)(%r1), %r1
1074 mtctl %r1, %cr18 /* IIAOQ head */
1075 ldo 4(%r1), %r1
1076 mtctl %r1, %cr18 /* IIAOQ tail */
1077 rfi
1078 nop
1079
10802: bv %r0(%r2)
1081 nop
1082 .exit
1083
1084 .procend
1085
1086 .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 @@
1/*
2 * Architecture-specific kernel symbols
3 *
4 * Copyright (C) 2000-2001 Richard Hirst <rhirst with parisc-linux.org>
5 * Copyright (C) 2001 Dave Kennedy
6 * Copyright (C) 2001 Paul Bame <bame at parisc-linux.org>
7 * Copyright (C) 2001-2003 Grant Grundler <grundler with parisc-linux.org>
8 * Copyright (C) 2002-2003 Matthew Wilcox <willy at parisc-linux.org>
9 * Copyright (C) 2002 Randolph Chung <tausq at parisc-linux.org>
10 * Copyright (C) 2002-2003 Helge Deller <deller with parisc-linux.org>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#include <linux/config.h>
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/syscalls.h>
31
32#include <linux/string.h>
33EXPORT_SYMBOL(memchr);
34EXPORT_SYMBOL(memcmp);
35EXPORT_SYMBOL(memmove);
36EXPORT_SYMBOL(memscan);
37EXPORT_SYMBOL(memset);
38EXPORT_SYMBOL(strcat);
39EXPORT_SYMBOL(strchr);
40EXPORT_SYMBOL(strcmp);
41EXPORT_SYMBOL(strcpy);
42EXPORT_SYMBOL(strlen);
43EXPORT_SYMBOL(strncat);
44EXPORT_SYMBOL(strncmp);
45EXPORT_SYMBOL(strncpy);
46EXPORT_SYMBOL(strnlen);
47EXPORT_SYMBOL(strrchr);
48EXPORT_SYMBOL(strstr);
49EXPORT_SYMBOL(strpbrk);
50
51#include <linux/pm.h>
52EXPORT_SYMBOL(pm_power_off);
53
54#include <asm/atomic.h>
55EXPORT_SYMBOL(__xchg8);
56EXPORT_SYMBOL(__xchg32);
57EXPORT_SYMBOL(__cmpxchg_u32);
58#ifdef CONFIG_SMP
59EXPORT_SYMBOL(__atomic_hash);
60#endif
61#ifdef __LP64__
62EXPORT_SYMBOL(__xchg64);
63EXPORT_SYMBOL(__cmpxchg_u64);
64#endif
65
66#include <asm/uaccess.h>
67EXPORT_SYMBOL(lstrncpy_from_user);
68EXPORT_SYMBOL(lclear_user);
69EXPORT_SYMBOL(lstrnlen_user);
70
71/* Global fixups */
72extern void fixup_get_user_skip_1(void);
73extern void fixup_get_user_skip_2(void);
74extern void fixup_put_user_skip_1(void);
75extern void fixup_put_user_skip_2(void);
76EXPORT_SYMBOL(fixup_get_user_skip_1);
77EXPORT_SYMBOL(fixup_get_user_skip_2);
78EXPORT_SYMBOL(fixup_put_user_skip_1);
79EXPORT_SYMBOL(fixup_put_user_skip_2);
80
81#ifndef __LP64__
82/* Needed so insmod can set dp value */
83extern int $global$;
84EXPORT_SYMBOL($global$);
85#endif
86
87#include <asm/io.h>
88EXPORT_SYMBOL(__ioremap);
89EXPORT_SYMBOL(iounmap);
90EXPORT_SYMBOL(memcpy_toio);
91EXPORT_SYMBOL(memcpy_fromio);
92EXPORT_SYMBOL(memset_io);
93
94#include <asm/unistd.h>
95EXPORT_SYMBOL(sys_open);
96EXPORT_SYMBOL(sys_lseek);
97EXPORT_SYMBOL(sys_read);
98EXPORT_SYMBOL(sys_write);
99
100#include <asm/semaphore.h>
101EXPORT_SYMBOL(__up);
102EXPORT_SYMBOL(__down_interruptible);
103EXPORT_SYMBOL(__down);
104
105extern void $$divI(void);
106extern void $$divU(void);
107extern void $$remI(void);
108extern void $$remU(void);
109extern void $$mulI(void);
110extern void $$divU_3(void);
111extern void $$divU_5(void);
112extern void $$divU_6(void);
113extern void $$divU_9(void);
114extern void $$divU_10(void);
115extern void $$divU_12(void);
116extern void $$divU_7(void);
117extern void $$divU_14(void);
118extern void $$divU_15(void);
119extern void $$divI_3(void);
120extern void $$divI_5(void);
121extern void $$divI_6(void);
122extern void $$divI_7(void);
123extern void $$divI_9(void);
124extern void $$divI_10(void);
125extern void $$divI_12(void);
126extern void $$divI_14(void);
127extern void $$divI_15(void);
128
129EXPORT_SYMBOL($$divI);
130EXPORT_SYMBOL($$divU);
131EXPORT_SYMBOL($$remI);
132EXPORT_SYMBOL($$remU);
133EXPORT_SYMBOL($$mulI);
134EXPORT_SYMBOL($$divU_3);
135EXPORT_SYMBOL($$divU_5);
136EXPORT_SYMBOL($$divU_6);
137EXPORT_SYMBOL($$divU_9);
138EXPORT_SYMBOL($$divU_10);
139EXPORT_SYMBOL($$divU_12);
140EXPORT_SYMBOL($$divU_7);
141EXPORT_SYMBOL($$divU_14);
142EXPORT_SYMBOL($$divU_15);
143EXPORT_SYMBOL($$divI_3);
144EXPORT_SYMBOL($$divI_5);
145EXPORT_SYMBOL($$divI_6);
146EXPORT_SYMBOL($$divI_7);
147EXPORT_SYMBOL($$divI_9);
148EXPORT_SYMBOL($$divI_10);
149EXPORT_SYMBOL($$divI_12);
150EXPORT_SYMBOL($$divI_14);
151EXPORT_SYMBOL($$divI_15);
152
153extern void __ashrdi3(void);
154extern void __ashldi3(void);
155extern void __lshrdi3(void);
156extern void __muldi3(void);
157
158EXPORT_SYMBOL(__ashrdi3);
159EXPORT_SYMBOL(__ashldi3);
160EXPORT_SYMBOL(__lshrdi3);
161EXPORT_SYMBOL(__muldi3);
162
163asmlinkage void * __canonicalize_funcptr_for_compare(void *);
164EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);
165
166#ifdef __LP64__
167extern void __divdi3(void);
168extern void __udivdi3(void);
169extern void __umoddi3(void);
170extern void __moddi3(void);
171
172EXPORT_SYMBOL(__divdi3);
173EXPORT_SYMBOL(__udivdi3);
174EXPORT_SYMBOL(__umoddi3);
175EXPORT_SYMBOL(__moddi3);
176#endif
177
178#ifndef __LP64__
179extern void $$dyncall(void);
180EXPORT_SYMBOL($$dyncall);
181#endif
182
183#ifdef CONFIG_DISCONTIGMEM
184#include <asm/mmzone.h>
185EXPORT_SYMBOL(node_data);
186EXPORT_SYMBOL(pfnnid_map);
187#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 @@
1/*
2** PARISC 1.1 Dynamic DMA mapping support.
3** This implementation is for PA-RISC platforms that do not support
4** I/O TLBs (aka DMA address translation hardware).
5** See Documentation/DMA-mapping.txt for interface definitions.
6**
7** (c) Copyright 1999,2000 Hewlett-Packard Company
8** (c) Copyright 2000 Grant Grundler
9** (c) Copyright 2000 Philipp Rumpf <prumpf@tux.org>
10** (c) Copyright 2000 John Marvin
11**
12** "leveraged" from 2.3.47: arch/ia64/kernel/pci-dma.c.
13** (I assume it's from David Mosberger-Tang but there was no Copyright)
14**
15** AFAIK, all PA7100LC and PA7300LC platforms can use this code.
16**
17** - ggg
18*/
19
20#include <linux/init.h>
21#include <linux/mm.h>
22#include <linux/pci.h>
23#include <linux/proc_fs.h>
24#include <linux/slab.h>
25#include <linux/string.h>
26#include <linux/types.h>
27
28#include <asm/cacheflush.h>
29#include <asm/dma.h> /* for DMA_CHUNK_SIZE */
30#include <asm/io.h>
31#include <asm/page.h> /* get_order */
32#include <asm/pgalloc.h>
33#include <asm/uaccess.h>
34
35
36static struct proc_dir_entry * proc_gsc_root = NULL;
37static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
38static unsigned long pcxl_used_bytes = 0;
39static unsigned long pcxl_used_pages = 0;
40
41extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */
42static spinlock_t pcxl_res_lock;
43static char *pcxl_res_map;
44static int pcxl_res_hint;
45static int pcxl_res_size;
46
47#ifdef DEBUG_PCXL_RESOURCE
48#define DBG_RES(x...) printk(x)
49#else
50#define DBG_RES(x...)
51#endif
52
53
54/*
55** Dump a hex representation of the resource map.
56*/
57
58#ifdef DUMP_RESMAP
59static
60void dump_resmap(void)
61{
62 u_long *res_ptr = (unsigned long *)pcxl_res_map;
63 u_long i = 0;
64
65 printk("res_map: ");
66 for(; i < (pcxl_res_size / sizeof(unsigned long)); ++i, ++res_ptr)
67 printk("%08lx ", *res_ptr);
68
69 printk("\n");
70}
71#else
72static inline void dump_resmap(void) {;}
73#endif
74
75static int pa11_dma_supported( struct device *dev, u64 mask)
76{
77 return 1;
78}
79
80static inline int map_pte_uncached(pte_t * pte,
81 unsigned long vaddr,
82 unsigned long size, unsigned long *paddr_ptr)
83{
84 unsigned long end;
85 unsigned long orig_vaddr = vaddr;
86
87 vaddr &= ~PMD_MASK;
88 end = vaddr + size;
89 if (end > PMD_SIZE)
90 end = PMD_SIZE;
91 do {
92 if (!pte_none(*pte))
93 printk(KERN_ERR "map_pte_uncached: page already exists\n");
94 set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
95 purge_tlb_start();
96 pdtlb_kernel(orig_vaddr);
97 purge_tlb_end();
98 vaddr += PAGE_SIZE;
99 orig_vaddr += PAGE_SIZE;
100 (*paddr_ptr) += PAGE_SIZE;
101 pte++;
102 } while (vaddr < end);
103 return 0;
104}
105
106static inline int map_pmd_uncached(pmd_t * pmd, unsigned long vaddr,
107 unsigned long size, unsigned long *paddr_ptr)
108{
109 unsigned long end;
110 unsigned long orig_vaddr = vaddr;
111
112 vaddr &= ~PGDIR_MASK;
113 end = vaddr + size;
114 if (end > PGDIR_SIZE)
115 end = PGDIR_SIZE;
116 do {
117 pte_t * pte = pte_alloc_kernel(&init_mm, pmd, vaddr);
118 if (!pte)
119 return -ENOMEM;
120 if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr))
121 return -ENOMEM;
122 vaddr = (vaddr + PMD_SIZE) & PMD_MASK;
123 orig_vaddr += PMD_SIZE;
124 pmd++;
125 } while (vaddr < end);
126 return 0;
127}
128
129static inline int map_uncached_pages(unsigned long vaddr, unsigned long size,
130 unsigned long paddr)
131{
132 pgd_t * dir;
133 unsigned long end = vaddr + size;
134
135 dir = pgd_offset_k(vaddr);
136 do {
137 pmd_t *pmd;
138
139 pmd = pmd_alloc(NULL, dir, vaddr);
140 if (!pmd)
141 return -ENOMEM;
142 if (map_pmd_uncached(pmd, vaddr, end - vaddr, &paddr))
143 return -ENOMEM;
144 vaddr = vaddr + PGDIR_SIZE;
145 dir++;
146 } while (vaddr && (vaddr < end));
147 return 0;
148}
149
150static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr,
151 unsigned long size)
152{
153 pte_t * pte;
154 unsigned long end;
155 unsigned long orig_vaddr = vaddr;
156
157 if (pmd_none(*pmd))
158 return;
159 if (pmd_bad(*pmd)) {
160 pmd_ERROR(*pmd);
161 pmd_clear(pmd);
162 return;
163 }
164 pte = pte_offset_map(pmd, vaddr);
165 vaddr &= ~PMD_MASK;
166 end = vaddr + size;
167 if (end > PMD_SIZE)
168 end = PMD_SIZE;
169 do {
170 pte_t page = *pte;
171 pte_clear(&init_mm, vaddr, pte);
172 purge_tlb_start();
173 pdtlb_kernel(orig_vaddr);
174 purge_tlb_end();
175 vaddr += PAGE_SIZE;
176 orig_vaddr += PAGE_SIZE;
177 pte++;
178 if (pte_none(page) || pte_present(page))
179 continue;
180 printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n");
181 } while (vaddr < end);
182}
183
184static inline void unmap_uncached_pmd(pgd_t * dir, unsigned long vaddr,
185 unsigned long size)
186{
187 pmd_t * pmd;
188 unsigned long end;
189 unsigned long orig_vaddr = vaddr;
190
191 if (pgd_none(*dir))
192 return;
193 if (pgd_bad(*dir)) {
194 pgd_ERROR(*dir);
195 pgd_clear(dir);
196 return;
197 }
198 pmd = pmd_offset(dir, vaddr);
199 vaddr &= ~PGDIR_MASK;
200 end = vaddr + size;
201 if (end > PGDIR_SIZE)
202 end = PGDIR_SIZE;
203 do {
204 unmap_uncached_pte(pmd, orig_vaddr, end - vaddr);
205 vaddr = (vaddr + PMD_SIZE) & PMD_MASK;
206 orig_vaddr += PMD_SIZE;
207 pmd++;
208 } while (vaddr < end);
209}
210
211static void unmap_uncached_pages(unsigned long vaddr, unsigned long size)
212{
213 pgd_t * dir;
214 unsigned long end = vaddr + size;
215
216 dir = pgd_offset_k(vaddr);
217 do {
218 unmap_uncached_pmd(dir, vaddr, end - vaddr);
219 vaddr = vaddr + PGDIR_SIZE;
220 dir++;
221 } while (vaddr && (vaddr < end));
222}
223
224#define PCXL_SEARCH_LOOP(idx, mask, size) \
225 for(; res_ptr < res_end; ++res_ptr) \
226 { \
227 if(0 == ((*res_ptr) & mask)) { \
228 *res_ptr |= mask; \
229 idx = (int)((u_long)res_ptr - (u_long)pcxl_res_map); \
230 pcxl_res_hint = idx + (size >> 3); \
231 goto resource_found; \
232 } \
233 }
234
235#define PCXL_FIND_FREE_MAPPING(idx, mask, size) { \
236 u##size *res_ptr = (u##size *)&(pcxl_res_map[pcxl_res_hint & ~((size >> 3) - 1)]); \
237 u##size *res_end = (u##size *)&pcxl_res_map[pcxl_res_size]; \
238 PCXL_SEARCH_LOOP(idx, mask, size); \
239 res_ptr = (u##size *)&pcxl_res_map[0]; \
240 PCXL_SEARCH_LOOP(idx, mask, size); \
241}
242
243unsigned long
244pcxl_alloc_range(size_t size)
245{
246 int res_idx;
247 u_long mask, flags;
248 unsigned int pages_needed = size >> PAGE_SHIFT;
249
250 mask = (u_long) -1L;
251 mask >>= BITS_PER_LONG - pages_needed;
252
253 DBG_RES("pcxl_alloc_range() size: %d pages_needed %d pages_mask 0x%08lx\n",
254 size, pages_needed, mask);
255
256 spin_lock_irqsave(&pcxl_res_lock, flags);
257
258 if(pages_needed <= 8) {
259 PCXL_FIND_FREE_MAPPING(res_idx, mask, 8);
260 } else if(pages_needed <= 16) {
261 PCXL_FIND_FREE_MAPPING(res_idx, mask, 16);
262 } else if(pages_needed <= 32) {
263 PCXL_FIND_FREE_MAPPING(res_idx, mask, 32);
264 } else {
265 panic("%s: pcxl_alloc_range() Too many pages to map.\n",
266 __FILE__);
267 }
268
269 dump_resmap();
270 panic("%s: pcxl_alloc_range() out of dma mapping resources\n",
271 __FILE__);
272
273resource_found:
274
275 DBG_RES("pcxl_alloc_range() res_idx %d mask 0x%08lx res_hint: %d\n",
276 res_idx, mask, pcxl_res_hint);
277
278 pcxl_used_pages += pages_needed;
279 pcxl_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1);
280
281 spin_unlock_irqrestore(&pcxl_res_lock, flags);
282
283 dump_resmap();
284
285 /*
286 ** return the corresponding vaddr in the pcxl dma map
287 */
288 return (pcxl_dma_start + (res_idx << (PAGE_SHIFT + 3)));
289}
290
291#define PCXL_FREE_MAPPINGS(idx, m, size) \
292 u##size *res_ptr = (u##size *)&(pcxl_res_map[(idx) + (((size >> 3) - 1) & (~((size >> 3) - 1)))]); \
293 /* BUG_ON((*res_ptr & m) != m); */ \
294 *res_ptr &= ~m;
295
296/*
297** clear bits in the pcxl resource map
298*/
299static void
300pcxl_free_range(unsigned long vaddr, size_t size)
301{
302 u_long mask, flags;
303 unsigned int res_idx = (vaddr - pcxl_dma_start) >> (PAGE_SHIFT + 3);
304 unsigned int pages_mapped = size >> PAGE_SHIFT;
305
306 mask = (u_long) -1L;
307 mask >>= BITS_PER_LONG - pages_mapped;
308
309 DBG_RES("pcxl_free_range() res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n",
310 res_idx, size, pages_mapped, mask);
311
312 spin_lock_irqsave(&pcxl_res_lock, flags);
313
314 if(pages_mapped <= 8) {
315 PCXL_FREE_MAPPINGS(res_idx, mask, 8);
316 } else if(pages_mapped <= 16) {
317 PCXL_FREE_MAPPINGS(res_idx, mask, 16);
318 } else if(pages_mapped <= 32) {
319 PCXL_FREE_MAPPINGS(res_idx, mask, 32);
320 } else {
321 panic("%s: pcxl_free_range() Too many pages to unmap.\n",
322 __FILE__);
323 }
324
325 pcxl_used_pages -= (pages_mapped ? pages_mapped : 1);
326 pcxl_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1);
327
328 spin_unlock_irqrestore(&pcxl_res_lock, flags);
329
330 dump_resmap();
331}
332
333static int __init
334pcxl_dma_init(void)
335{
336 if (pcxl_dma_start == 0)
337 return 0;
338
339 spin_lock_init(&pcxl_res_lock);
340 pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3);
341 pcxl_res_hint = 0;
342 pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
343 get_order(pcxl_res_size));
344 memset(pcxl_res_map, 0, pcxl_res_size);
345 proc_gsc_root = proc_mkdir("gsc", 0);
346 create_proc_info_entry("dino", 0, proc_gsc_root, pcxl_proc_info);
347 return 0;
348}
349
350__initcall(pcxl_dma_init);
351
352static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
353{
354 unsigned long vaddr;
355 unsigned long paddr;
356 int order;
357
358 order = get_order(size);
359 size = 1 << (order + PAGE_SHIFT);
360 vaddr = pcxl_alloc_range(size);
361 paddr = __get_free_pages(flag, order);
362 flush_kernel_dcache_range(paddr, size);
363 paddr = __pa(paddr);
364 map_uncached_pages(vaddr, size, paddr);
365 *dma_handle = (dma_addr_t) paddr;
366
367#if 0
368/* This probably isn't needed to support EISA cards.
369** ISA cards will certainly only support 24-bit DMA addressing.
370** Not clear if we can, want, or need to support ISA.
371*/
372 if (!dev || *dev->coherent_dma_mask < 0xffffffff)
373 gfp |= GFP_DMA;
374#endif
375 return (void *)vaddr;
376}
377
378static void pa11_dma_free_consistent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle)
379{
380 int order;
381
382 order = get_order(size);
383 size = 1 << (order + PAGE_SHIFT);
384 unmap_uncached_pages((unsigned long)vaddr, size);
385 pcxl_free_range((unsigned long)vaddr, size);
386 free_pages((unsigned long)__va(dma_handle), order);
387}
388
389static dma_addr_t pa11_dma_map_single(struct device *dev, void *addr, size_t size, enum dma_data_direction direction)
390{
391 if (direction == DMA_NONE) {
392 printk(KERN_ERR "pa11_dma_map_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
393 BUG();
394 }
395
396 flush_kernel_dcache_range((unsigned long) addr, size);
397 return virt_to_phys(addr);
398}
399
400static void pa11_dma_unmap_single(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
401{
402 if (direction == DMA_NONE) {
403 printk(KERN_ERR "pa11_dma_unmap_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
404 BUG();
405 }
406
407 if (direction == DMA_TO_DEVICE)
408 return;
409
410 /*
411 * For PCI_DMA_FROMDEVICE this flush is not necessary for the
412 * simple map/unmap case. However, it IS necessary if if
413 * pci_dma_sync_single_* has been called and the buffer reused.
414 */
415
416 flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size);
417 return;
418}
419
420static int pa11_dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
421{
422 int i;
423
424 if (direction == DMA_NONE)
425 BUG();
426
427 for (i = 0; i < nents; i++, sglist++ ) {
428 unsigned long vaddr = sg_virt_addr(sglist);
429 sg_dma_address(sglist) = (dma_addr_t) virt_to_phys(vaddr);
430 sg_dma_len(sglist) = sglist->length;
431 flush_kernel_dcache_range(vaddr, sglist->length);
432 }
433 return nents;
434}
435
436static void pa11_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
437{
438 int i;
439
440 if (direction == DMA_NONE)
441 BUG();
442
443 if (direction == DMA_TO_DEVICE)
444 return;
445
446 /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
447
448 for (i = 0; i < nents; i++, sglist++ )
449 flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
450 return;
451}
452
453static 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)
454{
455 if (direction == DMA_NONE)
456 BUG();
457
458 flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size);
459}
460
461static 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)
462{
463 if (direction == DMA_NONE)
464 BUG();
465
466 flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size);
467}
468
469static void pa11_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
470{
471 int i;
472
473 /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
474
475 for (i = 0; i < nents; i++, sglist++ )
476 flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
477}
478
479static void pa11_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
480{
481 int i;
482
483 /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
484
485 for (i = 0; i < nents; i++, sglist++ )
486 flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
487}
488
489struct hppa_dma_ops pcxl_dma_ops = {
490 .dma_supported = pa11_dma_supported,
491 .alloc_consistent = pa11_dma_alloc_consistent,
492 .alloc_noncoherent = pa11_dma_alloc_consistent,
493 .free_consistent = pa11_dma_free_consistent,
494 .map_single = pa11_dma_map_single,
495 .unmap_single = pa11_dma_unmap_single,
496 .map_sg = pa11_dma_map_sg,
497 .unmap_sg = pa11_dma_unmap_sg,
498 .dma_sync_single_for_cpu = pa11_dma_sync_single_for_cpu,
499 .dma_sync_single_for_device = pa11_dma_sync_single_for_device,
500 .dma_sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu,
501 .dma_sync_sg_for_device = pa11_dma_sync_sg_for_device,
502};
503
504static void *fail_alloc_consistent(struct device *dev, size_t size,
505 dma_addr_t *dma_handle, int flag)
506{
507 return NULL;
508}
509
510static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size,
511 dma_addr_t *dma_handle, int flag)
512{
513 void *addr = NULL;
514
515 /* rely on kmalloc to be cacheline aligned */
516 addr = kmalloc(size, flag);
517 if(addr)
518 *dma_handle = (dma_addr_t)virt_to_phys(addr);
519
520 return addr;
521}
522
523static void pa11_dma_free_noncoherent(struct device *dev, size_t size,
524 void *vaddr, dma_addr_t iova)
525{
526 kfree(vaddr);
527 return;
528}
529
530struct hppa_dma_ops pcx_dma_ops = {
531 .dma_supported = pa11_dma_supported,
532 .alloc_consistent = fail_alloc_consistent,
533 .alloc_noncoherent = pa11_dma_alloc_noncoherent,
534 .free_consistent = pa11_dma_free_noncoherent,
535 .map_single = pa11_dma_map_single,
536 .unmap_single = pa11_dma_unmap_single,
537 .map_sg = pa11_dma_map_sg,
538 .unmap_sg = pa11_dma_unmap_sg,
539 .dma_sync_single_for_cpu = pa11_dma_sync_single_for_cpu,
540 .dma_sync_single_for_device = pa11_dma_sync_single_for_device,
541 .dma_sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu,
542 .dma_sync_sg_for_device = pa11_dma_sync_sg_for_device,
543};
544
545
546static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
547{
548 u_long i = 0;
549 unsigned long *res_ptr = (u_long *)pcxl_res_map;
550 unsigned long total_pages = pcxl_res_size << 3; /* 8 bits per byte */
551
552 sprintf(buf, "\nDMA Mapping Area size : %d bytes (%d pages)\n",
553 PCXL_DMA_MAP_SIZE,
554 (pcxl_res_size << 3) ); /* 1 bit per page */
555
556 sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
557 buf, pcxl_res_size, pcxl_res_size << 3); /* 8 bits per byte */
558
559 strcat(buf, " total: free: used: % used:\n");
560 sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size,
561 pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes,
562 (pcxl_used_bytes * 100) / pcxl_res_size);
563
564 sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
565 total_pages - pcxl_used_pages, pcxl_used_pages,
566 (pcxl_used_pages * 100 / total_pages));
567
568 strcat(buf, "\nResource bitmap:");
569
570 for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
571 if ((i & 7) == 0)
572 strcat(buf,"\n ");
573 sprintf(buf, "%s %08lx", buf, *res_ptr);
574 }
575 strcat(buf, "\n");
576 return strlen(buf);
577}
578
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 @@
1/* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $
2 *
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 1997, 1998 Ralf Baechle
8 * Copyright (C) 1999 SuSE GmbH
9 * Copyright (C) 1999-2001 Hewlett-Packard Company
10 * Copyright (C) 1999-2001 Grant Grundler
11 */
12#include <linux/config.h>
13#include <linux/eisa.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/pci.h>
18#include <linux/slab.h>
19#include <linux/types.h>
20
21#include <asm/io.h>
22#include <asm/system.h>
23#include <asm/cache.h> /* for L1_CACHE_BYTES */
24#include <asm/superio.h>
25
26#define DEBUG_RESOURCES 0
27#define DEBUG_CONFIG 0
28
29#if DEBUG_CONFIG
30# define DBGC(x...) printk(KERN_DEBUG x)
31#else
32# define DBGC(x...)
33#endif
34
35
36#if DEBUG_RESOURCES
37#define DBG_RES(x...) printk(KERN_DEBUG x)
38#else
39#define DBG_RES(x...)
40#endif
41
42/* To be used as: mdelay(pci_post_reset_delay);
43 *
44 * post_reset is the time the kernel should stall to prevent anyone from
45 * accessing the PCI bus once #RESET is de-asserted.
46 * PCI spec somewhere says 1 second but with multi-PCI bus systems,
47 * this makes the boot time much longer than necessary.
48 * 20ms seems to work for all the HP PCI implementations to date.
49 *
50 * XXX: turn into a #defined constant in <asm/pci.h> ?
51 */
52int pci_post_reset_delay = 50;
53
54struct pci_port_ops *pci_port;
55struct pci_bios_ops *pci_bios;
56
57int pci_hba_count = 0;
58
59/* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. */
60#define PCI_HBA_MAX 32
61struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX];
62
63
64/********************************************************************
65**
66** I/O port space support
67**
68*********************************************************************/
69
70/* EISA port numbers and PCI port numbers share the same interface. Some
71 * machines have both EISA and PCI adapters installed. Rather than turn
72 * pci_port into an array, we reserve bus 0 for EISA and call the EISA
73 * routines if the access is to a port on bus 0. We don't want to fix
74 * EISA and ISA drivers which assume port space is <= 0xffff.
75 */
76
77#ifdef CONFIG_EISA
78#define EISA_IN(size) if (EISA_bus && (b == 0)) return eisa_in##size(addr)
79#define EISA_OUT(size) if (EISA_bus && (b == 0)) return eisa_out##size(d, addr)
80#else
81#define EISA_IN(size)
82#define EISA_OUT(size)
83#endif
84
85#define PCI_PORT_IN(type, size) \
86u##size in##type (int addr) \
87{ \
88 int b = PCI_PORT_HBA(addr); \
89 EISA_IN(size); \
90 if (!parisc_pci_hba[b]) return (u##size) -1; \
91 return pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \
92} \
93EXPORT_SYMBOL(in##type);
94
95PCI_PORT_IN(b, 8)
96PCI_PORT_IN(w, 16)
97PCI_PORT_IN(l, 32)
98
99
100#define PCI_PORT_OUT(type, size) \
101void out##type (u##size d, int addr) \
102{ \
103 int b = PCI_PORT_HBA(addr); \
104 EISA_OUT(size); \
105 if (!parisc_pci_hba[b]) return; \
106 pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \
107} \
108EXPORT_SYMBOL(out##type);
109
110PCI_PORT_OUT(b, 8)
111PCI_PORT_OUT(w, 16)
112PCI_PORT_OUT(l, 32)
113
114
115
116/*
117 * BIOS32 replacement.
118 */
119static int __init pcibios_init(void)
120{
121 if (!pci_bios)
122 return -1;
123
124 if (pci_bios->init) {
125 pci_bios->init();
126 } else {
127 printk(KERN_WARNING "pci_bios != NULL but init() is!\n");
128 }
129 return 0;
130}
131
132
133/* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */
134void pcibios_fixup_bus(struct pci_bus *bus)
135{
136 if (pci_bios->fixup_bus) {
137 pci_bios->fixup_bus(bus);
138 } else {
139 printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n");
140 }
141}
142
143
144char *pcibios_setup(char *str)
145{
146 return str;
147}
148
149/*
150 * Called by pci_set_master() - a driver interface.
151 *
152 * Legacy PDC guarantees to set:
153 * Map Memory BAR's into PA IO space.
154 * Map Expansion ROM BAR into one common PA IO space per bus.
155 * Map IO BAR's into PCI IO space.
156 * Command (see below)
157 * Cache Line Size
158 * Latency Timer
159 * Interrupt Line
160 * PPB: secondary latency timer, io/mmio base/limit,
161 * bus numbers, bridge control
162 *
163 */
164void pcibios_set_master(struct pci_dev *dev)
165{
166 u8 lat;
167
168 /* If someone already mucked with this, don't touch it. */
169 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
170 if (lat >= 16) return;
171
172 /*
173 ** HP generally has fewer devices on the bus than other architectures.
174 ** upper byte is PCI_LATENCY_TIMER.
175 */
176 pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
177 (0x80 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
178}
179
180
181void __init pcibios_init_bus(struct pci_bus *bus)
182{
183 struct pci_dev *dev = bus->self;
184 unsigned short bridge_ctl;
185
186 /* We deal only with pci controllers and pci-pci bridges. */
187 if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
188 return;
189
190 /* PCI-PCI bridge - set the cache line and default latency
191 (32) for primary and secondary buses. */
192 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32);
193
194 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl);
195 bridge_ctl |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
196 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl);
197}
198
199
200/* KLUGE: Link the child and parent resources - generic PCI didn't */
201static void
202pcibios_link_hba_resources( struct resource *hba_res, struct resource *r)
203{
204 if (!r->parent) {
205 printk(KERN_EMERG "PCI: Tell willy he's wrong\n");
206 r->parent = hba_res;
207
208 /* reverse link is harder *sigh* */
209 if (r->parent->child) {
210 if (r->parent->sibling) {
211 struct resource *next = r->parent->sibling;
212 while (next->sibling)
213 next = next->sibling;
214 next->sibling = r;
215 } else {
216 r->parent->sibling = r;
217 }
218 } else
219 r->parent->child = r;
220 }
221}
222
223/* called by drivers/pci/setup-bus.c:pci_setup_bridge(). */
224void __devinit pcibios_resource_to_bus(struct pci_dev *dev,
225 struct pci_bus_region *region, struct resource *res)
226{
227 struct pci_bus *bus = dev->bus;
228 struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data);
229
230 if (res->flags & IORESOURCE_IO) {
231 /*
232 ** I/O space may see busnumbers here. Something
233 ** in the form of 0xbbxxxx where bb is the bus num
234 ** and xxxx is the I/O port space address.
235 ** Remaining address translation are done in the
236 ** PCI Host adapter specific code - ie dino_out8.
237 */
238 region->start = PCI_PORT_ADDR(res->start);
239 region->end = PCI_PORT_ADDR(res->end);
240 } else if (res->flags & IORESOURCE_MEM) {
241 /* Convert MMIO addr to PCI addr (undo global virtualization) */
242 region->start = PCI_BUS_ADDR(hba, res->start);
243 region->end = PCI_BUS_ADDR(hba, res->end);
244 }
245
246 DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n",
247 bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM",
248 region->start, region->end);
249
250 /* KLUGE ALERT
251 ** if this resource isn't linked to a "parent", then it seems
252 ** to be a child of the HBA - lets link it in.
253 */
254 pcibios_link_hba_resources(&hba->io_space, bus->resource[0]);
255 pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]);
256}
257
258#ifdef CONFIG_HOTPLUG
259EXPORT_SYMBOL(pcibios_resource_to_bus);
260#endif
261
262/*
263 * pcibios align resources() is called every time generic PCI code
264 * wants to generate a new address. The process of looking for
265 * an available address, each candidate is first "aligned" and
266 * then checked if the resource is available until a match is found.
267 *
268 * Since we are just checking candidates, don't use any fields other
269 * than res->start.
270 */
271void pcibios_align_resource(void *data, struct resource *res,
272 unsigned long size, unsigned long alignment)
273{
274 unsigned long mask, align;
275
276 DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n",
277 pci_name(((struct pci_dev *) data)),
278 res->parent, res->start, res->end,
279 (int) res->flags, size, alignment);
280
281 /* If it's not IO, then it's gotta be MEM */
282 align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
283
284 /* Align to largest of MIN or input size */
285 mask = max(alignment, align) - 1;
286 res->start += mask;
287 res->start &= ~mask;
288
289 /* The caller updates the end field, we don't. */
290}
291
292
293/*
294 * A driver is enabling the device. We make sure that all the appropriate
295 * bits are set to allow the device to operate as the driver is expecting.
296 * We enable the port IO and memory IO bits if the device has any BARs of
297 * that type, and we enable the PERR and SERR bits unconditionally.
298 * Drivers that do not need parity (eg graphics and possibly networking)
299 * can clear these bits if they want.
300 */
301int pcibios_enable_device(struct pci_dev *dev, int mask)
302{
303 u16 cmd;
304 int idx;
305
306 pci_read_config_word(dev, PCI_COMMAND, &cmd);
307
308 for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
309 struct resource *r = &dev->resource[idx];
310
311 /* only setup requested resources */
312 if (!(mask & (1<<idx)))
313 continue;
314
315 if (r->flags & IORESOURCE_IO)
316 cmd |= PCI_COMMAND_IO;
317 if (r->flags & IORESOURCE_MEM)
318 cmd |= PCI_COMMAND_MEMORY;
319 }
320
321 cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
322
323#if 0
324 /* If bridge/bus controller has FBB enabled, child must too. */
325 if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
326 cmd |= PCI_COMMAND_FAST_BACK;
327#endif
328 DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", pci_name(dev), cmd);
329 pci_write_config_word(dev, PCI_COMMAND, cmd);
330 return 0;
331}
332
333
334/* PA-RISC specific */
335void pcibios_register_hba(struct pci_hba_data *hba)
336{
337 if (pci_hba_count >= PCI_HBA_MAX) {
338 printk(KERN_ERR "PCI: Too many Host Bus Adapters\n");
339 return;
340 }
341
342 parisc_pci_hba[pci_hba_count] = hba;
343 hba->hba_num = pci_hba_count++;
344}
345
346subsys_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 @@
1/*
2 * interfaces to log Chassis Codes via PDC (firmware)
3 *
4 * Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
5 * Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#undef PDC_CHASSIS_DEBUG
23#ifdef PDC_CHASSIS_DEBUG
24#define DPRINTK(fmt, args...) printk(fmt, ## args)
25#else
26#define DPRINTK(fmt, args...)
27#endif
28
29#include <linux/init.h>
30#include <linux/kernel.h>
31#include <linux/reboot.h>
32#include <linux/notifier.h>
33
34#include <asm/pdc_chassis.h>
35#include <asm/processor.h>
36#include <asm/pdc.h>
37#include <asm/pdcpat.h>
38
39
40#ifdef CONFIG_PDC_CHASSIS
41static int pdc_chassis_old = 0;
42static unsigned int pdc_chassis_enabled = 1;
43
44
45/**
46 * pdc_chassis_setup() - Enable/disable pdc_chassis code at boot time.
47 * @str configuration param: 0 to disable chassis log
48 * @return 1
49 */
50
51static int __init pdc_chassis_setup(char *str)
52{
53 /*panic_timeout = simple_strtoul(str, NULL, 0);*/
54 get_option(&str, &pdc_chassis_enabled);
55 return 1;
56}
57__setup("pdcchassis=", pdc_chassis_setup);
58
59
60/**
61 * pdc_chassis_checkold() - Checks for old PDC_CHASSIS compatibility
62 * @pdc_chassis_old: 1 if old pdc chassis style
63 *
64 * Currently, only E class and A180 are known to work with this.
65 * Inspired by Christoph Plattner
66 */
67
68static void __init pdc_chassis_checkold(void)
69{
70 switch(CPU_HVERSION) {
71 case 0x480: /* E25 */
72 case 0x481: /* E35 */
73 case 0x482: /* E45 */
74 case 0x483: /* E55 */
75 case 0x516: /* A180 */
76 pdc_chassis_old = 1;
77 break;
78
79 default:
80 break;
81 }
82 DPRINTK(KERN_DEBUG "%s: pdc_chassis_checkold(); pdc_chassis_old = %d\n", __FILE__, pdc_chassis_old);
83}
84
85
86/**
87 * pdc_chassis_panic_event() - Called by the panic handler.
88 *
89 * As soon as a panic occurs, we should inform the PDC.
90 */
91
92static int pdc_chassis_panic_event(struct notifier_block *this,
93 unsigned long event, void *ptr)
94{
95 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
96 return NOTIFY_DONE;
97}
98
99
100static struct notifier_block pdc_chassis_panic_block = {
101 .notifier_call = pdc_chassis_panic_event,
102 .priority = INT_MAX,
103};
104
105
106/**
107 * parisc_reboot_event() - Called by the reboot handler.
108 *
109 * As soon as a reboot occurs, we should inform the PDC.
110 */
111
112static int pdc_chassis_reboot_event(struct notifier_block *this,
113 unsigned long event, void *ptr)
114{
115 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
116 return NOTIFY_DONE;
117}
118
119
120static struct notifier_block pdc_chassis_reboot_block = {
121 .notifier_call = pdc_chassis_reboot_event,
122 .priority = INT_MAX,
123};
124#endif /* CONFIG_PDC_CHASSIS */
125
126
127/**
128 * parisc_pdc_chassis_init() - Called at boot time.
129 */
130
131void __init parisc_pdc_chassis_init(void)
132{
133#ifdef CONFIG_PDC_CHASSIS
134 int handle = 0;
135 if (pdc_chassis_enabled) {
136 DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__);
137
138 /* Let see if we have something to handle... */
139 /* Check for PDC_PAT or old LED Panel */
140 pdc_chassis_checkold();
141 if (is_pdc_pat()) {
142 printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n");
143 handle = 1;
144 }
145 else if (pdc_chassis_old) {
146 printk(KERN_INFO "Enabling old style chassis LED panel support.\n");
147 handle = 1;
148 }
149
150 if (handle) {
151 /* initialize panic notifier chain */
152 notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block);
153
154 /* initialize reboot notifier chain */
155 register_reboot_notifier(&pdc_chassis_reboot_block);
156 }
157 }
158#endif /* CONFIG_PDC_CHASSIS */
159}
160
161
162/**
163 * pdc_chassis_send_status() - Sends a predefined message to the chassis,
164 * and changes the front panel LEDs according to the new system state
165 * @retval: PDC call return value.
166 *
167 * Only machines with 64 bits PDC PAT and those reported in
168 * pdc_chassis_checkold() are supported atm.
169 *
170 * returns 0 if no error, -1 if no supported PDC is present or invalid message,
171 * else returns the appropriate PDC error code.
172 *
173 * For a list of predefined messages, see asm-parisc/pdc_chassis.h
174 */
175
176int pdc_chassis_send_status(int message)
177{
178 /* Maybe we should do that in an other way ? */
179 int retval = 0;
180#ifdef CONFIG_PDC_CHASSIS
181 if (pdc_chassis_enabled) {
182
183 DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message);
184
185#ifdef CONFIG_64BIT
186 if (is_pdc_pat()) {
187 switch(message) {
188 case PDC_CHASSIS_DIRECT_BSTART:
189 retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_BSTART, PDC_CHASSIS_LSTATE_RUN_NORMAL);
190 break;
191
192 case PDC_CHASSIS_DIRECT_BCOMPLETE:
193 retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_BCOMPLETE, PDC_CHASSIS_LSTATE_RUN_NORMAL);
194 break;
195
196 case PDC_CHASSIS_DIRECT_SHUTDOWN:
197 retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_SHUTDOWN, PDC_CHASSIS_LSTATE_NONOS);
198 break;
199
200 case PDC_CHASSIS_DIRECT_PANIC:
201 retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_PANIC, PDC_CHASSIS_LSTATE_RUN_CRASHREC);
202 break;
203
204 case PDC_CHASSIS_DIRECT_LPMC:
205 retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_LPMC, PDC_CHASSIS_LSTATE_RUN_SYSINT);
206 break;
207
208 case PDC_CHASSIS_DIRECT_HPMC:
209 retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_HPMC, PDC_CHASSIS_LSTATE_RUN_NCRIT);
210 break;
211
212 default:
213 retval = -1;
214 }
215 } else retval = -1;
216#else
217 if (pdc_chassis_old) {
218 switch (message) {
219 case PDC_CHASSIS_DIRECT_BSTART:
220 case PDC_CHASSIS_DIRECT_BCOMPLETE:
221 retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_RUN));
222 break;
223
224 case PDC_CHASSIS_DIRECT_SHUTDOWN:
225 retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_SHUT));
226 break;
227
228 case PDC_CHASSIS_DIRECT_HPMC:
229 case PDC_CHASSIS_DIRECT_PANIC:
230 retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_FLT));
231 break;
232
233 case PDC_CHASSIS_DIRECT_LPMC:
234 retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_WARN));
235 break;
236
237 default:
238 retval = -1;
239 }
240 } else retval = -1;
241#endif /* CONFIG_64BIT */
242 } /* if (pdc_chassis_enabled) */
243#endif /* CONFIG_PDC_CHASSIS */
244 return retval;
245}
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 @@
1/*
2 * PDC Console support - ie use firmware to dump text via boot console
3 *
4 * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
5 * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
6 * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
7 * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
8 * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
9 * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
10 * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
11 * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
12 * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
13 * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
14 * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
15 *
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 */
31
32/*
33 * The PDC console is a simple console, which can be used for debugging
34 * boot related problems on HP PA-RISC machines.
35 *
36 * This code uses the ROM (=PDC) based functions to read and write characters
37 * from and to PDC's boot path.
38 * Since all character read from that path must be polled, this code never
39 * can or will be a fully functional linux console.
40 */
41
42/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems.
43 * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
44#undef EARLY_BOOTUP_DEBUG
45
46
47#include <linux/config.h>
48#include <linux/kernel.h>
49#include <linux/console.h>
50#include <linux/string.h>
51#include <linux/init.h>
52#include <linux/delay.h>
53#include <linux/sched.h>
54#include <linux/interrupt.h>
55#include <linux/major.h>
56#include <linux/tty.h>
57#include <asm/page.h>
58#include <asm/types.h>
59#include <asm/system.h>
60#include <asm/pdc.h> /* for iodc_call() proto and friends */
61
62
63static void pdc_console_write(struct console *co, const char *s, unsigned count)
64{
65 while(count--)
66 pdc_iodc_putc(*s++);
67}
68
69void pdc_outc(unsigned char c)
70{
71 pdc_iodc_outc(c);
72}
73
74void pdc_printf(const char *fmt, ...)
75{
76 va_list args;
77 char buf[1024];
78 int i, len;
79
80 va_start(args, fmt);
81 len = vscnprintf(buf, sizeof(buf), fmt, args);
82 va_end(args);
83
84 for (i = 0; i < len; i++)
85 pdc_iodc_outc(buf[i]);
86}
87
88int pdc_console_poll_key(struct console *co)
89{
90 return pdc_iodc_getc();
91}
92
93static int pdc_console_setup(struct console *co, char *options)
94{
95 return 0;
96}
97
98#if defined(CONFIG_PDC_CONSOLE)
99#define PDC_CONSOLE_DEVICE pdc_console_device
100static struct tty_driver * pdc_console_device (struct console *c, int *index)
101{
102 extern struct tty_driver console_driver;
103 *index = c->index ? c->index-1 : fg_console;
104 return &console_driver;
105}
106#else
107#define PDC_CONSOLE_DEVICE NULL
108#endif
109
110static struct console pdc_cons = {
111 .name = "ttyB",
112 .write = pdc_console_write,
113 .device = PDC_CONSOLE_DEVICE,
114 .setup = pdc_console_setup,
115 .flags = CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
116 .index = -1,
117};
118
119static int pdc_console_initialized;
120extern unsigned long con_start; /* kernel/printk.c */
121extern unsigned long log_end; /* kernel/printk.c */
122
123
124static void pdc_console_init_force(void)
125{
126 if (pdc_console_initialized)
127 return;
128 ++pdc_console_initialized;
129
130 /* If the console is duplex then copy the COUT parameters to CIN. */
131 if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
132 memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
133
134 /* register the pdc console */
135 register_console(&pdc_cons);
136}
137
138void __init pdc_console_init(void)
139{
140#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE)
141 pdc_console_init_force();
142#endif
143#ifdef EARLY_BOOTUP_DEBUG
144 printk(KERN_INFO "Initialized PDC Console for debugging.\n");
145#endif
146}
147
148
149/* Unregister the pdc console with the printk console layer */
150void pdc_console_die(void)
151{
152 if (!pdc_console_initialized)
153 return;
154 --pdc_console_initialized;
155
156 printk(KERN_INFO "Switching from PDC console\n");
157
158 /* Don't repeat what we've already printed */
159 con_start = log_end;
160
161 unregister_console(&pdc_cons);
162}
163
164
165/*
166 * Used for emergencies. Currently only used if an HPMC occurs. If an
167 * HPMC occurs, it is possible that the current console may not be
168 * properly initialed after the PDC IO reset. This routine unregisters all
169 * of the current consoles, reinitializes the pdc console and
170 * registers it.
171 */
172
173void pdc_console_restart(void)
174{
175 struct console *console;
176
177 if (pdc_console_initialized)
178 return;
179
180 while ((console = console_drivers) != NULL)
181 unregister_console(console_drivers);
182
183 /* Don't repeat what we've already printed */
184 con_start = log_end;
185
186 /* force registering the pdc console */
187 pdc_console_init_force();
188}
189
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 @@
1/*
2 * Parisc performance counters
3 * Copyright (C) 2001 Randolph Chung <tausq@debian.org>
4 *
5 * This code is derived, with permission, from HP/UX sources.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22/*
23 * Edited comment from original sources:
24 *
25 * This driver programs the PCX-U/PCX-W performance counters
26 * on the PA-RISC 2.0 chips. The driver keeps all images now
27 * internally to the kernel to hopefully eliminate the possiblity
28 * of a bad image halting the CPU. Also, there are different
29 * images for the PCX-W and later chips vs the PCX-U chips.
30 *
31 * Only 1 process is allowed to access the driver at any time,
32 * so the only protection that is needed is at open and close.
33 * A variable "perf_enabled" is used to hold the state of the
34 * driver. The spinlock "perf_lock" is used to protect the
35 * modification of the state during open/close operations so
36 * multiple processes don't get into the driver simultaneously.
37 *
38 * This driver accesses the processor directly vs going through
39 * the PDC INTRIGUE calls. This is done to eliminate bugs introduced
40 * in various PDC revisions. The code is much more maintainable
41 * and reliable this way vs having to debug on every version of PDC
42 * on every box.
43 */
44
45#include <linux/init.h>
46#include <linux/proc_fs.h>
47#include <linux/miscdevice.h>
48#include <linux/spinlock.h>
49
50#include <asm/uaccess.h>
51#include <asm/perf.h>
52#include <asm/parisc-device.h>
53#include <asm/processor.h>
54#include <asm/runway.h>
55#include <asm/io.h> /* for __raw_read() */
56
57#include "perf_images.h"
58
59#define MAX_RDR_WORDS 24
60#define PERF_VERSION 2 /* derived from hpux's PI v2 interface */
61
62/* definition of RDR regs */
63struct rdr_tbl_ent {
64 uint16_t width;
65 uint8_t num_words;
66 uint8_t write_control;
67};
68
69static int perf_processor_interface = UNKNOWN_INTF;
70static int perf_enabled = 0;
71static spinlock_t perf_lock;
72struct parisc_device *cpu_device = NULL;
73
74/* RDRs to write for PCX-W */
75static int perf_rdrs_W[] =
76 { 0, 1, 4, 5, 6, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
77
78/* RDRs to write for PCX-U */
79static int perf_rdrs_U[] =
80 { 0, 1, 4, 5, 6, 7, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
81
82/* RDR register descriptions for PCX-W */
83static struct rdr_tbl_ent perf_rdr_tbl_W[] = {
84 { 19, 1, 8 }, /* RDR 0 */
85 { 16, 1, 16 }, /* RDR 1 */
86 { 72, 2, 0 }, /* RDR 2 */
87 { 81, 2, 0 }, /* RDR 3 */
88 { 328, 6, 0 }, /* RDR 4 */
89 { 160, 3, 0 }, /* RDR 5 */
90 { 336, 6, 0 }, /* RDR 6 */
91 { 164, 3, 0 }, /* RDR 7 */
92 { 0, 0, 0 }, /* RDR 8 */
93 { 35, 1, 0 }, /* RDR 9 */
94 { 6, 1, 0 }, /* RDR 10 */
95 { 18, 1, 0 }, /* RDR 11 */
96 { 13, 1, 0 }, /* RDR 12 */
97 { 8, 1, 0 }, /* RDR 13 */
98 { 8, 1, 0 }, /* RDR 14 */
99 { 8, 1, 0 }, /* RDR 15 */
100 { 1530, 24, 0 }, /* RDR 16 */
101 { 16, 1, 0 }, /* RDR 17 */
102 { 4, 1, 0 }, /* RDR 18 */
103 { 0, 0, 0 }, /* RDR 19 */
104 { 152, 3, 24 }, /* RDR 20 */
105 { 152, 3, 24 }, /* RDR 21 */
106 { 233, 4, 48 }, /* RDR 22 */
107 { 233, 4, 48 }, /* RDR 23 */
108 { 71, 2, 0 }, /* RDR 24 */
109 { 71, 2, 0 }, /* RDR 25 */
110 { 11, 1, 0 }, /* RDR 26 */
111 { 18, 1, 0 }, /* RDR 27 */
112 { 128, 2, 0 }, /* RDR 28 */
113 { 0, 0, 0 }, /* RDR 29 */
114 { 16, 1, 0 }, /* RDR 30 */
115 { 16, 1, 0 }, /* RDR 31 */
116};
117
118/* RDR register descriptions for PCX-U */
119static struct rdr_tbl_ent perf_rdr_tbl_U[] = {
120 { 19, 1, 8 }, /* RDR 0 */
121 { 32, 1, 16 }, /* RDR 1 */
122 { 20, 1, 0 }, /* RDR 2 */
123 { 0, 0, 0 }, /* RDR 3 */
124 { 344, 6, 0 }, /* RDR 4 */
125 { 176, 3, 0 }, /* RDR 5 */
126 { 336, 6, 0 }, /* RDR 6 */
127 { 0, 0, 0 }, /* RDR 7 */
128 { 0, 0, 0 }, /* RDR 8 */
129 { 0, 0, 0 }, /* RDR 9 */
130 { 28, 1, 0 }, /* RDR 10 */
131 { 33, 1, 0 }, /* RDR 11 */
132 { 0, 0, 0 }, /* RDR 12 */
133 { 230, 4, 0 }, /* RDR 13 */
134 { 32, 1, 0 }, /* RDR 14 */
135 { 128, 2, 0 }, /* RDR 15 */
136 { 1494, 24, 0 }, /* RDR 16 */
137 { 18, 1, 0 }, /* RDR 17 */
138 { 4, 1, 0 }, /* RDR 18 */
139 { 0, 0, 0 }, /* RDR 19 */
140 { 158, 3, 24 }, /* RDR 20 */
141 { 158, 3, 24 }, /* RDR 21 */
142 { 194, 4, 48 }, /* RDR 22 */
143 { 194, 4, 48 }, /* RDR 23 */
144 { 71, 2, 0 }, /* RDR 24 */
145 { 71, 2, 0 }, /* RDR 25 */
146 { 28, 1, 0 }, /* RDR 26 */
147 { 33, 1, 0 }, /* RDR 27 */
148 { 88, 2, 0 }, /* RDR 28 */
149 { 32, 1, 0 }, /* RDR 29 */
150 { 24, 1, 0 }, /* RDR 30 */
151 { 16, 1, 0 }, /* RDR 31 */
152};
153
154/*
155 * A non-zero write_control in the above tables is a byte offset into
156 * this array.
157 */
158static uint64_t perf_bitmasks[] = {
159 0x0000000000000000ul, /* first dbl word must be zero */
160 0xfdffe00000000000ul, /* RDR0 bitmask */
161 0x003f000000000000ul, /* RDR1 bitmask */
162 0x00fffffffffffffful, /* RDR20-RDR21 bitmask (152 bits) */
163 0xfffffffffffffffful,
164 0xfffffffc00000000ul,
165 0xfffffffffffffffful, /* RDR22-RDR23 bitmask (233 bits) */
166 0xfffffffffffffffful,
167 0xfffffffffffffffcul,
168 0xff00000000000000ul
169};
170
171/*
172 * Write control bitmasks for Pa-8700 processor given
173 * somethings have changed slightly.
174 */
175static uint64_t perf_bitmasks_piranha[] = {
176 0x0000000000000000ul, /* first dbl word must be zero */
177 0xfdffe00000000000ul, /* RDR0 bitmask */
178 0x003f000000000000ul, /* RDR1 bitmask */
179 0x00fffffffffffffful, /* RDR20-RDR21 bitmask (158 bits) */
180 0xfffffffffffffffful,
181 0xfffffffc00000000ul,
182 0xfffffffffffffffful, /* RDR22-RDR23 bitmask (210 bits) */
183 0xfffffffffffffffful,
184 0xfffffffffffffffful,
185 0xfffc000000000000ul
186};
187
188static uint64_t *bitmask_array; /* array of bitmasks to use */
189
190/******************************************************************************
191 * Function Prototypes
192 *****************************************************************************/
193static int perf_config(uint32_t *image_ptr);
194static int perf_release(struct inode *inode, struct file *file);
195static int perf_open(struct inode *inode, struct file *file);
196static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos);
197static ssize_t perf_write(struct file *file, const char __user *buf, size_t count,
198 loff_t *ppos);
199static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
200 unsigned long arg);
201static void perf_start_counters(void);
202static int perf_stop_counters(uint32_t *raddr);
203static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num);
204static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer);
205static int perf_rdr_clear(uint32_t rdr_num);
206static int perf_write_image(uint64_t *memaddr);
207static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer);
208
209/* External Assembly Routines */
210extern uint64_t perf_rdr_shift_in_W (uint32_t rdr_num, uint16_t width);
211extern uint64_t perf_rdr_shift_in_U (uint32_t rdr_num, uint16_t width);
212extern void perf_rdr_shift_out_W (uint32_t rdr_num, uint64_t buffer);
213extern void perf_rdr_shift_out_U (uint32_t rdr_num, uint64_t buffer);
214extern void perf_intrigue_enable_perf_counters (void);
215extern void perf_intrigue_disable_perf_counters (void);
216
217/******************************************************************************
218 * Function Definitions
219 *****************************************************************************/
220
221
222/*
223 * configure:
224 *
225 * Configure the cpu with a given data image. First turn off the counters,
226 * then download the image, then turn the counters back on.
227 */
228static int perf_config(uint32_t *image_ptr)
229{
230 long error;
231 uint32_t raddr[4];
232
233 /* Stop the counters*/
234 error = perf_stop_counters(raddr);
235 if (error != 0) {
236 printk("perf_config: perf_stop_counters = %ld\n", error);
237 return -EINVAL;
238 }
239
240printk("Preparing to write image\n");
241 /* Write the image to the chip */
242 error = perf_write_image((uint64_t *)image_ptr);
243 if (error != 0) {
244 printk("perf_config: DOWNLOAD = %ld\n", error);
245 return -EINVAL;
246 }
247
248printk("Preparing to start counters\n");
249
250 /* Start the counters */
251 perf_start_counters();
252
253 return sizeof(uint32_t);
254}
255
256/*
257 * Open the device and initialize all of its memory. The device is only
258 * opened once, but can be "queried" by multiple processes that know its
259 * file descriptor.
260 */
261static int perf_open(struct inode *inode, struct file *file)
262{
263 spin_lock(&perf_lock);
264 if (perf_enabled) {
265 spin_unlock(&perf_lock);
266 return -EBUSY;
267 }
268 perf_enabled = 1;
269 spin_unlock(&perf_lock);
270
271 return 0;
272}
273
274/*
275 * Close the device.
276 */
277static int perf_release(struct inode *inode, struct file *file)
278{
279 spin_lock(&perf_lock);
280 perf_enabled = 0;
281 spin_unlock(&perf_lock);
282
283 return 0;
284}
285
286/*
287 * Read does nothing for this driver
288 */
289static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos)
290{
291 return 0;
292}
293
294/*
295 * write:
296 *
297 * This routine downloads the image to the chip. It must be
298 * called on the processor that the download should happen
299 * on.
300 */
301static ssize_t perf_write(struct file *file, const char __user *buf, size_t count,
302 loff_t *ppos)
303{
304 int err;
305 size_t image_size;
306 uint32_t image_type;
307 uint32_t interface_type;
308 uint32_t test;
309
310 if (perf_processor_interface == ONYX_INTF)
311 image_size = PCXU_IMAGE_SIZE;
312 else if (perf_processor_interface == CUDA_INTF)
313 image_size = PCXW_IMAGE_SIZE;
314 else
315 return -EFAULT;
316
317 if (!capable(CAP_SYS_ADMIN))
318 return -EACCES;
319
320 if (count != sizeof(uint32_t))
321 return -EIO;
322
323 if ((err = copy_from_user(&image_type, buf, sizeof(uint32_t))) != 0)
324 return err;
325
326 /* Get the interface type and test type */
327 interface_type = (image_type >> 16) & 0xffff;
328 test = (image_type & 0xffff);
329
330 /* Make sure everything makes sense */
331
332 /* First check the machine type is correct for
333 the requested image */
334 if (((perf_processor_interface == CUDA_INTF) &&
335 (interface_type != CUDA_INTF)) ||
336 ((perf_processor_interface == ONYX_INTF) &&
337 (interface_type != ONYX_INTF)))
338 return -EINVAL;
339
340 /* Next check to make sure the requested image
341 is valid */
342 if (((interface_type == CUDA_INTF) &&
343 (test >= MAX_CUDA_IMAGES)) ||
344 ((interface_type == ONYX_INTF) &&
345 (test >= MAX_ONYX_IMAGES)))
346 return -EINVAL;
347
348 /* Copy the image into the processor */
349 if (interface_type == CUDA_INTF)
350 return perf_config(cuda_images[test]);
351 else
352 return perf_config(onyx_images[test]);
353
354 return count;
355}
356
357/*
358 * Patch the images that need to know the IVA addresses.
359 */
360static void perf_patch_images(void)
361{
362#if 0 /* FIXME!! */
363/*
364 * NOTE: this routine is VERY specific to the current TLB image.
365 * If the image is changed, this routine might also need to be changed.
366 */
367 extern void $i_itlb_miss_2_0();
368 extern void $i_dtlb_miss_2_0();
369 extern void PA2_0_iva();
370
371 /*
372 * We can only use the lower 32-bits, the upper 32-bits should be 0
373 * anyway given this is in the kernel
374 */
375 uint32_t itlb_addr = (uint32_t)&($i_itlb_miss_2_0);
376 uint32_t dtlb_addr = (uint32_t)&($i_dtlb_miss_2_0);
377 uint32_t IVAaddress = (uint32_t)&PA2_0_iva;
378
379 if (perf_processor_interface == ONYX_INTF) {
380 /* clear last 2 bytes */
381 onyx_images[TLBMISS][15] &= 0xffffff00;
382 /* set 2 bytes */
383 onyx_images[TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
384 onyx_images[TLBMISS][16] = (dtlb_addr << 8)&0xffffff00;
385 onyx_images[TLBMISS][17] = itlb_addr;
386
387 /* clear last 2 bytes */
388 onyx_images[TLBHANDMISS][15] &= 0xffffff00;
389 /* set 2 bytes */
390 onyx_images[TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
391 onyx_images[TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00;
392 onyx_images[TLBHANDMISS][17] = itlb_addr;
393
394 /* clear last 2 bytes */
395 onyx_images[BIG_CPI][15] &= 0xffffff00;
396 /* set 2 bytes */
397 onyx_images[BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24));
398 onyx_images[BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00;
399 onyx_images[BIG_CPI][17] = itlb_addr;
400
401 onyx_images[PANIC][15] &= 0xffffff00; /* clear last 2 bytes */
402 onyx_images[PANIC][15] |= (0x000000ff&((IVAaddress) >> 24)); /* set 2 bytes */
403 onyx_images[PANIC][16] = (IVAaddress << 8)&0xffffff00;
404
405
406 } else if (perf_processor_interface == CUDA_INTF) {
407 /* Cuda interface */
408 cuda_images[TLBMISS][16] =
409 (cuda_images[TLBMISS][16]&0xffff0000) |
410 ((dtlb_addr >> 8)&0x0000ffff);
411 cuda_images[TLBMISS][17] =
412 ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
413 cuda_images[TLBMISS][18] = (itlb_addr << 16)&0xffff0000;
414
415 cuda_images[TLBHANDMISS][16] =
416 (cuda_images[TLBHANDMISS][16]&0xffff0000) |
417 ((dtlb_addr >> 8)&0x0000ffff);
418 cuda_images[TLBHANDMISS][17] =
419 ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
420 cuda_images[TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000;
421
422 cuda_images[BIG_CPI][16] =
423 (cuda_images[BIG_CPI][16]&0xffff0000) |
424 ((dtlb_addr >> 8)&0x0000ffff);
425 cuda_images[BIG_CPI][17] =
426 ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
427 cuda_images[BIG_CPI][18] = (itlb_addr << 16)&0xffff0000;
428 } else {
429 /* Unknown type */
430 }
431#endif
432}
433
434
435/*
436 * ioctl routine
437 * All routines effect the processor that they are executed on. Thus you
438 * must be running on the processor that you wish to change.
439 */
440
441static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
442 unsigned long arg)
443{
444 long error_start;
445 uint32_t raddr[4];
446
447 switch (cmd) {
448
449 case PA_PERF_ON:
450 /* Start the counters */
451 perf_start_counters();
452 return 0;
453
454 case PA_PERF_OFF:
455 error_start = perf_stop_counters(raddr);
456 if (error_start != 0) {
457 printk(KERN_ERR "perf_off: perf_stop_counters = %ld\n", error_start);
458 return -EFAULT;
459 }
460
461 /* copy out the Counters */
462 if (copy_to_user((void __user *)arg, raddr,
463 sizeof (raddr)) != 0) {
464 return -EFAULT;
465 }
466 return 0;
467
468 case PA_PERF_VERSION:
469 /* Return the version # */
470 return put_user(PERF_VERSION, (int *)arg);
471
472 default:
473 break;
474 }
475 return -ENOTTY;
476}
477
478static struct file_operations perf_fops = {
479 .llseek = no_llseek,
480 .read = perf_read,
481 .write = perf_write,
482 .ioctl = perf_ioctl,
483 .open = perf_open,
484 .release = perf_release
485};
486
487static struct miscdevice perf_dev = {
488 MISC_DYNAMIC_MINOR,
489 PA_PERF_DEV,
490 &perf_fops
491};
492
493/*
494 * Initialize the module
495 */
496static int __init perf_init(void)
497{
498 int ret;
499
500 /* Determine correct processor interface to use */
501 bitmask_array = perf_bitmasks;
502
503 if (boot_cpu_data.cpu_type == pcxu ||
504 boot_cpu_data.cpu_type == pcxu_) {
505 perf_processor_interface = ONYX_INTF;
506 } else if (boot_cpu_data.cpu_type == pcxw ||
507 boot_cpu_data.cpu_type == pcxw_ ||
508 boot_cpu_data.cpu_type == pcxw2 ||
509 boot_cpu_data.cpu_type == mako) {
510 perf_processor_interface = CUDA_INTF;
511 if (boot_cpu_data.cpu_type == pcxw2 ||
512 boot_cpu_data.cpu_type == mako)
513 bitmask_array = perf_bitmasks_piranha;
514 } else {
515 perf_processor_interface = UNKNOWN_INTF;
516 printk("Performance monitoring counters not supported on this processor\n");
517 return -ENODEV;
518 }
519
520 ret = misc_register(&perf_dev);
521 if (ret) {
522 printk(KERN_ERR "Performance monitoring counters: "
523 "cannot register misc device.\n");
524 return ret;
525 }
526
527 /* Patch the images to match the system */
528 perf_patch_images();
529
530 spin_lock_init(&perf_lock);
531
532 /* TODO: this only lets us access the first cpu.. what to do for SMP? */
533 cpu_device = cpu_data[0].dev;
534 printk("Performance monitoring counters enabled for %s\n",
535 cpu_data[0].dev->name);
536
537 return 0;
538}
539
540/*
541 * perf_start_counters(void)
542 *
543 * Start the counters.
544 */
545static void perf_start_counters(void)
546{
547 /* Enable performance monitor counters */
548 perf_intrigue_enable_perf_counters();
549}
550
551/*
552 * perf_stop_counters
553 *
554 * Stop the performance counters and save counts
555 * in a per_processor array.
556 */
557static int perf_stop_counters(uint32_t *raddr)
558{
559 uint64_t userbuf[MAX_RDR_WORDS];
560
561 /* Disable performance counters */
562 perf_intrigue_disable_perf_counters();
563
564 if (perf_processor_interface == ONYX_INTF) {
565 uint64_t tmp64;
566 /*
567 * Read the counters
568 */
569 if (!perf_rdr_read_ubuf(16, userbuf))
570 return -13;
571
572 /* Counter0 is bits 1398 thru 1429 */
573 tmp64 = (userbuf[21] << 22) & 0x00000000ffc00000;
574 tmp64 |= (userbuf[22] >> 42) & 0x00000000003fffff;
575 /* OR sticky0 (bit 1430) to counter0 bit 32 */
576 tmp64 |= (userbuf[22] >> 10) & 0x0000000080000000;
577 raddr[0] = (uint32_t)tmp64;
578
579 /* Counter1 is bits 1431 thru 1462 */
580 tmp64 = (userbuf[22] >> 9) & 0x00000000ffffffff;
581 /* OR sticky1 (bit 1463) to counter1 bit 32 */
582 tmp64 |= (userbuf[22] << 23) & 0x0000000080000000;
583 raddr[1] = (uint32_t)tmp64;
584
585 /* Counter2 is bits 1464 thru 1495 */
586 tmp64 = (userbuf[22] << 24) & 0x00000000ff000000;
587 tmp64 |= (userbuf[23] >> 40) & 0x0000000000ffffff;
588 /* OR sticky2 (bit 1496) to counter2 bit 32 */
589 tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000;
590 raddr[2] = (uint32_t)tmp64;
591
592 /* Counter3 is bits 1497 thru 1528 */
593 tmp64 = (userbuf[23] >> 7) & 0x00000000ffffffff;
594 /* OR sticky3 (bit 1529) to counter3 bit 32 */
595 tmp64 |= (userbuf[23] << 25) & 0x0000000080000000;
596 raddr[3] = (uint32_t)tmp64;
597
598 /*
599 * Zero out the counters
600 */
601
602 /*
603 * The counters and sticky-bits comprise the last 132 bits
604 * (1398 - 1529) of RDR16 on a U chip. We'll zero these
605 * out the easy way: zero out last 10 bits of dword 21,
606 * all of dword 22 and 58 bits (plus 6 don't care bits) of
607 * dword 23.
608 */
609 userbuf[21] &= 0xfffffffffffffc00ul; /* 0 to last 10 bits */
610 userbuf[22] = 0;
611 userbuf[23] = 0;
612
613 /*
614 * Write back the zero'ed bytes + the image given
615 * the read was destructive.
616 */
617 perf_rdr_write(16, userbuf);
618 } else {
619
620 /*
621 * Read RDR-15 which contains the counters and sticky bits
622 */
623 if (!perf_rdr_read_ubuf(15, userbuf)) {
624 return -13;
625 }
626
627 /*
628 * Clear out the counters
629 */
630 perf_rdr_clear(15);
631
632 /*
633 * Copy the counters
634 */
635 raddr[0] = (uint32_t)((userbuf[0] >> 32) & 0x00000000ffffffffUL);
636 raddr[1] = (uint32_t)(userbuf[0] & 0x00000000ffffffffUL);
637 raddr[2] = (uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffffUL);
638 raddr[3] = (uint32_t)(userbuf[1] & 0x00000000ffffffffUL);
639 }
640
641 return 0;
642}
643
644/*
645 * perf_rdr_get_entry
646 *
647 * Retrieve a pointer to the description of what this
648 * RDR contains.
649 */
650static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num)
651{
652 if (perf_processor_interface == ONYX_INTF) {
653 return &perf_rdr_tbl_U[rdr_num];
654 } else {
655 return &perf_rdr_tbl_W[rdr_num];
656 }
657}
658
659/*
660 * perf_rdr_read_ubuf
661 *
662 * Read the RDR value into the buffer specified.
663 */
664static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer)
665{
666 uint64_t data, data_mask = 0;
667 uint32_t width, xbits, i;
668 struct rdr_tbl_ent *tentry;
669
670 tentry = perf_rdr_get_entry(rdr_num);
671 if ((width = tentry->width) == 0)
672 return 0;
673
674 /* Clear out buffer */
675 i = tentry->num_words;
676 while (i--) {
677 buffer[i] = 0;
678 }
679
680 /* Check for bits an even number of 64 */
681 if ((xbits = width & 0x03f) != 0) {
682 data_mask = 1;
683 data_mask <<= (64 - xbits);
684 data_mask--;
685 }
686
687 /* Grab all of the data */
688 i = tentry->num_words;
689 while (i--) {
690
691 if (perf_processor_interface == ONYX_INTF) {
692 data = perf_rdr_shift_in_U(rdr_num, width);
693 } else {
694 data = perf_rdr_shift_in_W(rdr_num, width);
695 }
696 if (xbits) {
697 buffer[i] |= (data << (64 - xbits));
698 if (i) {
699 buffer[i-1] |= ((data >> xbits) & data_mask);
700 }
701 } else {
702 buffer[i] = data;
703 }
704 }
705
706 return 1;
707}
708
709/*
710 * perf_rdr_clear
711 *
712 * Zero out the given RDR register
713 */
714static int perf_rdr_clear(uint32_t rdr_num)
715{
716 struct rdr_tbl_ent *tentry;
717 int32_t i;
718
719 tentry = perf_rdr_get_entry(rdr_num);
720
721 if (tentry->width == 0) {
722 return -1;
723 }
724
725 i = tentry->num_words;
726 while (i--) {
727 if (perf_processor_interface == ONYX_INTF) {
728 perf_rdr_shift_out_U(rdr_num, 0UL);
729 } else {
730 perf_rdr_shift_out_W(rdr_num, 0UL);
731 }
732 }
733
734 return 0;
735}
736
737
738/*
739 * perf_write_image
740 *
741 * Write the given image out to the processor
742 */
743static int perf_write_image(uint64_t *memaddr)
744{
745 uint64_t buffer[MAX_RDR_WORDS];
746 uint64_t *bptr;
747 uint32_t dwords;
748 uint32_t *intrigue_rdr;
749 uint64_t *intrigue_bitmask, tmp64, proc_hpa;
750 struct rdr_tbl_ent *tentry;
751 int i;
752
753 /* Clear out counters */
754 if (perf_processor_interface == ONYX_INTF) {
755
756 perf_rdr_clear(16);
757
758 /* Toggle performance monitor */
759 perf_intrigue_enable_perf_counters();
760 perf_intrigue_disable_perf_counters();
761
762 intrigue_rdr = perf_rdrs_U;
763 } else {
764 perf_rdr_clear(15);
765 intrigue_rdr = perf_rdrs_W;
766 }
767
768 /* Write all RDRs */
769 while (*intrigue_rdr != -1) {
770 tentry = perf_rdr_get_entry(*intrigue_rdr);
771 perf_rdr_read_ubuf(*intrigue_rdr, buffer);
772 bptr = &buffer[0];
773 dwords = tentry->num_words;
774 if (tentry->write_control) {
775 intrigue_bitmask = &bitmask_array[tentry->write_control >> 3];
776 while (dwords--) {
777 tmp64 = *intrigue_bitmask & *memaddr++;
778 tmp64 |= (~(*intrigue_bitmask++)) & *bptr;
779 *bptr++ = tmp64;
780 }
781 } else {
782 while (dwords--) {
783 *bptr++ = *memaddr++;
784 }
785 }
786
787 perf_rdr_write(*intrigue_rdr, buffer);
788 intrigue_rdr++;
789 }
790
791 /*
792 * Now copy out the Runway stuff which is not in RDRs
793 */
794
795 if (cpu_device == NULL)
796 {
797 printk(KERN_ERR "write_image: cpu_device not yet initialized!\n");
798 return -1;
799 }
800
801 proc_hpa = cpu_device->hpa;
802
803 /* Merge intrigue bits into Runway STATUS 0 */
804 tmp64 = __raw_readq(proc_hpa + RUNWAY_STATUS) & 0xffecfffffffffffful;
805 __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), proc_hpa + RUNWAY_STATUS);
806
807 /* Write RUNWAY DEBUG registers */
808 for (i = 0; i < 8; i++) {
809 __raw_writeq(*memaddr++, proc_hpa + RUNWAY_DEBUG + i);
810 }
811
812 return 0;
813}
814
815/*
816 * perf_rdr_write
817 *
818 * Write the given RDR register with the contents
819 * of the given buffer.
820 */
821static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer)
822{
823 struct rdr_tbl_ent *tentry;
824 int32_t i;
825
826printk("perf_rdr_write\n");
827 tentry = perf_rdr_get_entry(rdr_num);
828 if (tentry->width == 0) { return; }
829
830 i = tentry->num_words;
831 while (i--) {
832 if (perf_processor_interface == ONYX_INTF) {
833 perf_rdr_shift_out_U(rdr_num, buffer[i]);
834 } else {
835 perf_rdr_shift_out_W(rdr_num, buffer[i]);
836 }
837 }
838printk("perf_rdr_write done\n");
839}
840
841module_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 @@
1
2/* low-level asm for "intrigue" (PA8500-8700 CPU perf counters)
3 *
4 * Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org>
5 * Copyright (C) 2001 Hewlett-Packard (Grant Grundler)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/config.h>
23#include <asm/assembly.h>
24
25#ifdef CONFIG_64BIT
26 .level 2.0w
27#endif /* CONFIG_64BIT */
28
29#define MTDIAG_1(gr) .word 0x14201840 + gr*0x10000
30#define MTDIAG_2(gr) .word 0x14401840 + gr*0x10000
31#define MFDIAG_1(gr) .word 0x142008A0 + gr
32#define MFDIAG_2(gr) .word 0x144008A0 + gr
33#define STDIAG(dr) .word 0x14000AA0 + dr*0x200000
34#define SFDIAG(dr) .word 0x14000BA0 + dr*0x200000
35#define DR2_SLOW_RET 53
36
37
38;
39; Enable the performance counters
40;
41; The coprocessor only needs to be enabled when
42; starting/stopping the coprocessor with the pmenb/pmdis.
43;
44 .text
45 .align 32
46
47 .export perf_intrigue_enable_perf_counters,code
48perf_intrigue_enable_perf_counters:
49 .proc
50 .callinfo frame=0,NO_CALLS
51 .entry
52
53 ldi 0x20,%r25 ; load up perfmon bit
54 mfctl ccr,%r26 ; get coprocessor register
55 or %r25,%r26,%r26 ; set bit
56 mtctl %r26,ccr ; turn on performance coprocessor
57 pmenb ; enable performance monitor
58 ssm 0,0 ; dummy op to ensure completion
59 sync ; follow ERS
60 andcm %r26,%r25,%r26 ; clear bit now
61 mtctl %r26,ccr ; turn off performance coprocessor
62 nop ; NOPs as specified in ERS
63 nop
64 nop
65 nop
66 nop
67 nop
68 nop
69 bve (%r2)
70 nop
71 .exit
72 .procend
73
74 .export perf_intrigue_disable_perf_counters,code
75perf_intrigue_disable_perf_counters:
76 .proc
77 .callinfo frame=0,NO_CALLS
78 .entry
79 ldi 0x20,%r25 ; load up perfmon bit
80 mfctl ccr,%r26 ; get coprocessor register
81 or %r25,%r26,%r26 ; set bit
82 mtctl %r26,ccr ; turn on performance coprocessor
83 pmdis ; disable performance monitor
84 ssm 0,0 ; dummy op to ensure completion
85 andcm %r26,%r25,%r26 ; clear bit now
86 bve (%r2)
87 mtctl %r26,ccr ; turn off performance coprocessor
88 .exit
89 .procend
90
91;***********************************************************************
92;*
93;* Name: perf_rdr_shift_in_W
94;*
95;* Description:
96;* This routine shifts data in from the RDR in arg0 and returns
97;* the result in ret0. If the RDR is <= 64 bits in length, it
98;* is shifted shifted backup immediately. This is to compensate
99;* for RDR10 which has bits that preclude PDC stack operations
100;* when they are in the wrong state.
101;*
102;* Arguments:
103;* arg0 : rdr to be read
104;* arg1 : bit length of rdr
105;*
106;* Returns:
107;* ret0 = next 64 bits of rdr data from staging register
108;*
109;* Register usage:
110;* arg0 : rdr to be read
111;* arg1 : bit length of rdr
112;* %r24 - original DR2 value
113;* %r1 - scratch
114;* %r29 - scratch
115;*
116;* Returns:
117;* ret0 = RDR data (right justified)
118;*
119;***********************************************************************
120
121 .export perf_rdr_shift_in_W,code
122perf_rdr_shift_in_W:
123 .proc
124 .callinfo frame=0,NO_CALLS
125 .entry
126;
127; read(shift in) the RDR.
128;
129
130; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any
131; shifting is done, from or to, remote diagnose registers.
132;
133
134 depdi,z 1,DR2_SLOW_RET,1,%r29
135 MFDIAG_2 (24)
136 or %r24,%r29,%r29
137 MTDIAG_2 (29) ; set DR2_SLOW_RET
138
139 nop
140 nop
141 nop
142 nop
143
144;
145; Cacheline start (32-byte cacheline)
146;
147 nop
148 nop
149 nop
150 extrd,u arg1,63,6,%r1 ; setup shift amount by bits to move
151
152 mtsar %r1
153 shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number
154 blr %r1,%r0 ; branch to 8-instruction sequence
155 nop
156
157;
158; Cacheline start (32-byte cacheline)
159;
160
161 ;
162 ; RDR 0 sequence
163 ;
164 SFDIAG (0)
165 ssm 0,0
166 MFDIAG_1 (28)
167 shrpd ret0,%r0,%sar,%r1
168 MTDIAG_1 (1) ; mtdiag %dr1, %r1
169 STDIAG (0)
170 ssm 0,0
171 b,n perf_rdr_shift_in_W_leave
172
173 ;
174 ; RDR 1 sequence
175 ;
176 sync
177 ssm 0,0
178 SFDIAG (1)
179 ssm 0,0
180 MFDIAG_1 (28)
181 ssm 0,0
182 b,n perf_rdr_shift_in_W_leave
183 nop
184
185 ;
186 ; RDR 2 read sequence
187 ;
188 SFDIAG (2)
189 ssm 0,0
190 MFDIAG_1 (28)
191 shrpd ret0,%r0,%sar,%r1
192 MTDIAG_1 (1)
193 STDIAG (2)
194 ssm 0,0
195 b,n perf_rdr_shift_in_W_leave
196
197 ;
198 ; RDR 3 read sequence
199 ;
200 b,n perf_rdr_shift_in_W_leave
201 nop
202 nop
203 nop
204 nop
205 nop
206 nop
207 nop
208
209 ;
210 ; RDR 4 read sequence
211 ;
212 sync
213 ssm 0,0
214 SFDIAG (4)
215 ssm 0,0
216 MFDIAG_1 (28)
217 b,n perf_rdr_shift_in_W_leave
218 ssm 0,0
219 nop
220
221 ;
222 ; RDR 5 read sequence
223 ;
224 sync
225 ssm 0,0
226 SFDIAG (5)
227 ssm 0,0
228 MFDIAG_1 (28)
229 b,n perf_rdr_shift_in_W_leave
230 ssm 0,0
231 nop
232
233 ;
234 ; RDR 6 read sequence
235 ;
236 sync
237 ssm 0,0
238 SFDIAG (6)
239 ssm 0,0
240 MFDIAG_1 (28)
241 b,n perf_rdr_shift_in_W_leave
242 ssm 0,0
243 nop
244
245 ;
246 ; RDR 7 read sequence
247 ;
248 b,n perf_rdr_shift_in_W_leave
249 nop
250 nop
251 nop
252 nop
253 nop
254 nop
255 nop
256
257 ;
258 ; RDR 8 read sequence
259 ;
260 b,n perf_rdr_shift_in_W_leave
261 nop
262 nop
263 nop
264 nop
265 nop
266 nop
267 nop
268
269 ;
270 ; RDR 9 read sequence
271 ;
272 b,n perf_rdr_shift_in_W_leave
273 nop
274 nop
275 nop
276 nop
277 nop
278 nop
279 nop
280
281 ;
282 ; RDR 10 read sequence
283 ;
284 SFDIAG (10)
285 ssm 0,0
286 MFDIAG_1 (28)
287 shrpd ret0,%r0,%sar,%r1
288 MTDIAG_1 (1)
289 STDIAG (10)
290 ssm 0,0
291 b,n perf_rdr_shift_in_W_leave
292
293 ;
294 ; RDR 11 read sequence
295 ;
296 SFDIAG (11)
297 ssm 0,0
298 MFDIAG_1 (28)
299 shrpd ret0,%r0,%sar,%r1
300 MTDIAG_1 (1)
301 STDIAG (11)
302 ssm 0,0
303 b,n perf_rdr_shift_in_W_leave
304
305 ;
306 ; RDR 12 read sequence
307 ;
308 b,n perf_rdr_shift_in_W_leave
309 nop
310 nop
311 nop
312 nop
313 nop
314 nop
315 nop
316
317 ;
318 ; RDR 13 read sequence
319 ;
320 sync
321 ssm 0,0
322 SFDIAG (13)
323 ssm 0,0
324 MFDIAG_1 (28)
325 b,n perf_rdr_shift_in_W_leave
326 ssm 0,0
327 nop
328
329 ;
330 ; RDR 14 read sequence
331 ;
332 SFDIAG (14)
333 ssm 0,0
334 MFDIAG_1 (28)
335 shrpd ret0,%r0,%sar,%r1
336 MTDIAG_1 (1)
337 STDIAG (14)
338 ssm 0,0
339 b,n perf_rdr_shift_in_W_leave
340
341 ;
342 ; RDR 15 read sequence
343 ;
344 sync
345 ssm 0,0
346 SFDIAG (15)
347 ssm 0,0
348 MFDIAG_1 (28)
349 ssm 0,0
350 b,n perf_rdr_shift_in_W_leave
351 nop
352
353 ;
354 ; RDR 16 read sequence
355 ;
356 sync
357 ssm 0,0
358 SFDIAG (16)
359 ssm 0,0
360 MFDIAG_1 (28)
361 b,n perf_rdr_shift_in_W_leave
362 ssm 0,0
363 nop
364
365 ;
366 ; RDR 17 read sequence
367 ;
368 SFDIAG (17)
369 ssm 0,0
370 MFDIAG_1 (28)
371 shrpd ret0,%r0,%sar,%r1
372 MTDIAG_1 (1)
373 STDIAG (17)
374 ssm 0,0
375 b,n perf_rdr_shift_in_W_leave
376
377 ;
378 ; RDR 18 read sequence
379 ;
380 SFDIAG (18)
381 ssm 0,0
382 MFDIAG_1 (28)
383 shrpd ret0,%r0,%sar,%r1
384 MTDIAG_1 (1)
385 STDIAG (18)
386 ssm 0,0
387 b,n perf_rdr_shift_in_W_leave
388
389 ;
390 ; RDR 19 read sequence
391 ;
392 b,n perf_rdr_shift_in_W_leave
393 nop
394 nop
395 nop
396 nop
397 nop
398 nop
399 nop
400
401 ;
402 ; RDR 20 read sequence
403 ;
404 sync
405 ssm 0,0
406 SFDIAG (20)
407 ssm 0,0
408 MFDIAG_1 (28)
409 b,n perf_rdr_shift_in_W_leave
410 ssm 0,0
411 nop
412
413 ;
414 ; RDR 21 read sequence
415 ;
416 sync
417 ssm 0,0
418 SFDIAG (21)
419 ssm 0,0
420 MFDIAG_1 (28)
421 b,n perf_rdr_shift_in_W_leave
422 ssm 0,0
423 nop
424
425 ;
426 ; RDR 22 read sequence
427 ;
428 sync
429 ssm 0,0
430 SFDIAG (22)
431 ssm 0,0
432 MFDIAG_1 (28)
433 b,n perf_rdr_shift_in_W_leave
434 ssm 0,0
435 nop
436
437 ;
438 ; RDR 23 read sequence
439 ;
440 sync
441 ssm 0,0
442 SFDIAG (23)
443 ssm 0,0
444 MFDIAG_1 (28)
445 b,n perf_rdr_shift_in_W_leave
446 ssm 0,0
447 nop
448
449 ;
450 ; RDR 24 read sequence
451 ;
452 sync
453 ssm 0,0
454 SFDIAG (24)
455 ssm 0,0
456 MFDIAG_1 (28)
457 b,n perf_rdr_shift_in_W_leave
458 ssm 0,0
459 nop
460
461 ;
462 ; RDR 25 read sequence
463 ;
464 sync
465 ssm 0,0
466 SFDIAG (25)
467 ssm 0,0
468 MFDIAG_1 (28)
469 b,n perf_rdr_shift_in_W_leave
470 ssm 0,0
471 nop
472
473 ;
474 ; RDR 26 read sequence
475 ;
476 SFDIAG (26)
477 ssm 0,0
478 MFDIAG_1 (28)
479 shrpd ret0,%r0,%sar,%r1
480 MTDIAG_1 (1)
481 STDIAG (26)
482 ssm 0,0
483 b,n perf_rdr_shift_in_W_leave
484
485 ;
486 ; RDR 27 read sequence
487 ;
488 SFDIAG (27)
489 ssm 0,0
490 MFDIAG_1 (28)
491 shrpd ret0,%r0,%sar,%r1
492 MTDIAG_1 (1)
493 STDIAG (27)
494 ssm 0,0
495 b,n perf_rdr_shift_in_W_leave
496
497 ;
498 ; RDR 28 read sequence
499 ;
500 sync
501 ssm 0,0
502 SFDIAG (28)
503 ssm 0,0
504 MFDIAG_1 (28)
505 b,n perf_rdr_shift_in_W_leave
506 ssm 0,0
507 nop
508
509 ;
510 ; RDR 29 read sequence
511 ;
512 sync
513 ssm 0,0
514 SFDIAG (29)
515 ssm 0,0
516 MFDIAG_1 (28)
517 b,n perf_rdr_shift_in_W_leave
518 ssm 0,0
519 nop
520
521 ;
522 ; RDR 30 read sequence
523 ;
524 SFDIAG (30)
525 ssm 0,0
526 MFDIAG_1 (28)
527 shrpd ret0,%r0,%sar,%r1
528 MTDIAG_1 (1)
529 STDIAG (30)
530 ssm 0,0
531 b,n perf_rdr_shift_in_W_leave
532
533 ;
534 ; RDR 31 read sequence
535 ;
536 sync
537 ssm 0,0
538 SFDIAG (31)
539 ssm 0,0
540 MFDIAG_1 (28)
541 nop
542 ssm 0,0
543 nop
544
545 ;
546 ; Fallthrough
547 ;
548
549perf_rdr_shift_in_W_leave:
550 bve (%r2)
551 .exit
552 MTDIAG_2 (24) ; restore DR2
553 .procend
554
555
556;***********************************************************************
557;*
558;* Name: perf_rdr_shift_out_W
559;*
560;* Description:
561;* This routine moves data to the RDR's. The double-word that
562;* arg1 points to is loaded and moved into the staging register.
563;* Then the STDIAG instruction for the RDR # in arg0 is called
564;* to move the data to the RDR.
565;*
566;* Arguments:
567;* arg0 = rdr number
568;* arg1 = 64-bit value to write
569;* %r24 - DR2 | DR2_SLOW_RET
570;* %r23 - original DR2 value
571;*
572;* Returns:
573;* None
574;*
575;* Register usage:
576;*
577;***********************************************************************
578
579 .export perf_rdr_shift_out_W,code
580perf_rdr_shift_out_W:
581 .proc
582 .callinfo frame=0,NO_CALLS
583 .entry
584;
585; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any
586; shifting is done, from or to, the remote diagnose registers.
587;
588
589 depdi,z 1,DR2_SLOW_RET,1,%r24
590 MFDIAG_2 (23)
591 or %r24,%r23,%r24
592 MTDIAG_2 (24) ; set DR2_SLOW_RET
593 MTDIAG_1 (25) ; data to the staging register
594 shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number
595 blr %r1,%r0 ; branch to 8-instruction sequence
596 nop
597
598 ;
599 ; RDR 0 write sequence
600 ;
601 sync ; RDR 0 write sequence
602 ssm 0,0
603 STDIAG (0)
604 ssm 0,0
605 b,n perf_rdr_shift_out_W_leave
606 nop
607 ssm 0,0
608 nop
609
610 ;
611 ; RDR 1 write sequence
612 ;
613 sync
614 ssm 0,0
615 STDIAG (1)
616 ssm 0,0
617 b,n perf_rdr_shift_out_W_leave
618 nop
619 ssm 0,0
620 nop
621
622 ;
623 ; RDR 2 write sequence
624 ;
625 sync
626 ssm 0,0
627 STDIAG (2)
628 ssm 0,0
629 b,n perf_rdr_shift_out_W_leave
630 nop
631 ssm 0,0
632 nop
633
634 ;
635 ; RDR 3 write sequence
636 ;
637 sync
638 ssm 0,0
639 STDIAG (3)
640 ssm 0,0
641 b,n perf_rdr_shift_out_W_leave
642 nop
643 ssm 0,0
644 nop
645
646 ;
647 ; RDR 4 write sequence
648 ;
649 sync
650 ssm 0,0
651 STDIAG (4)
652 ssm 0,0
653 b,n perf_rdr_shift_out_W_leave
654 nop
655 ssm 0,0
656 nop
657
658 ;
659 ; RDR 5 write sequence
660 ;
661 sync
662 ssm 0,0
663 STDIAG (5)
664 ssm 0,0
665 b,n perf_rdr_shift_out_W_leave
666 nop
667 ssm 0,0
668 nop
669
670 ;
671 ; RDR 6 write sequence
672 ;
673 sync
674 ssm 0,0
675 STDIAG (6)
676 ssm 0,0
677 b,n perf_rdr_shift_out_W_leave
678 nop
679 ssm 0,0
680 nop
681
682 ;
683 ; RDR 7 write sequence
684 ;
685 sync
686 ssm 0,0
687 STDIAG (7)
688 ssm 0,0
689 b,n perf_rdr_shift_out_W_leave
690 nop
691 ssm 0,0
692 nop
693
694 ;
695 ; RDR 8 write sequence
696 ;
697 sync
698 ssm 0,0
699 STDIAG (8)
700 ssm 0,0
701 b,n perf_rdr_shift_out_W_leave
702 nop
703 ssm 0,0
704 nop
705
706 ;
707 ; RDR 9 write sequence
708 ;
709 sync
710 ssm 0,0
711 STDIAG (9)
712 ssm 0,0
713 b,n perf_rdr_shift_out_W_leave
714 nop
715 ssm 0,0
716 nop
717
718 ;
719 ; RDR 10 write sequence
720 ;
721 sync
722 ssm 0,0
723 STDIAG (10)
724 STDIAG (26)
725 ssm 0,0
726 b,n perf_rdr_shift_out_W_leave
727 ssm 0,0
728 nop
729
730 ;
731 ; RDR 11 write sequence
732 ;
733 sync
734 ssm 0,0
735 STDIAG (11)
736 STDIAG (27)
737 ssm 0,0
738 b,n perf_rdr_shift_out_W_leave
739 ssm 0,0
740 nop
741
742 ;
743 ; RDR 12 write sequence
744 ;
745 sync
746 ssm 0,0
747 STDIAG (12)
748 ssm 0,0
749 b,n perf_rdr_shift_out_W_leave
750 nop
751 ssm 0,0
752 nop
753
754 ;
755 ; RDR 13 write sequence
756 ;
757 sync
758 ssm 0,0
759 STDIAG (13)
760 ssm 0,0
761 b,n perf_rdr_shift_out_W_leave
762 nop
763 ssm 0,0
764 nop
765
766 ;
767 ; RDR 14 write sequence
768 ;
769 sync
770 ssm 0,0
771 STDIAG (14)
772 ssm 0,0
773 b,n perf_rdr_shift_out_W_leave
774 nop
775 ssm 0,0
776 nop
777
778 ;
779 ; RDR 15 write sequence
780 ;
781 sync
782 ssm 0,0
783 STDIAG (15)
784 ssm 0,0
785 b,n perf_rdr_shift_out_W_leave
786 nop
787 ssm 0,0
788 nop
789
790 ;
791 ; RDR 16 write sequence
792 ;
793 sync
794 ssm 0,0
795 STDIAG (16)
796 ssm 0,0
797 b,n perf_rdr_shift_out_W_leave
798 nop
799 ssm 0,0
800 nop
801
802 ;
803 ; RDR 17 write sequence
804 ;
805 sync
806 ssm 0,0
807 STDIAG (17)
808 ssm 0,0
809 b,n perf_rdr_shift_out_W_leave
810 nop
811 ssm 0,0
812 nop
813
814 ;
815 ; RDR 18 write sequence
816 ;
817 sync
818 ssm 0,0
819 STDIAG (18)
820 ssm 0,0
821 b,n perf_rdr_shift_out_W_leave
822 nop
823 ssm 0,0
824 nop
825
826 ;
827 ; RDR 19 write sequence
828 ;
829 sync
830 ssm 0,0
831 STDIAG (19)
832 ssm 0,0
833 b,n perf_rdr_shift_out_W_leave
834 nop
835 ssm 0,0
836 nop
837
838 ;
839 ; RDR 20 write sequence
840 ;
841 sync
842 ssm 0,0
843 STDIAG (20)
844 ssm 0,0
845 b,n perf_rdr_shift_out_W_leave
846 nop
847 ssm 0,0
848 nop
849
850 ;
851 ; RDR 21 write sequence
852 ;
853 sync
854 ssm 0,0
855 STDIAG (21)
856 ssm 0,0
857 b,n perf_rdr_shift_out_W_leave
858 nop
859 ssm 0,0
860 nop
861
862 ;
863 ; RDR 22 write sequence
864 ;
865 sync
866 ssm 0,0
867 STDIAG (22)
868 ssm 0,0
869 b,n perf_rdr_shift_out_W_leave
870 nop
871 ssm 0,0
872 nop
873
874 ;
875 ; RDR 23 write sequence
876 ;
877 sync
878 ssm 0,0
879 STDIAG (23)
880 ssm 0,0
881 b,n perf_rdr_shift_out_W_leave
882 nop
883 ssm 0,0
884 nop
885
886 ;
887 ; RDR 24 write sequence
888 ;
889 sync
890 ssm 0,0
891 STDIAG (24)
892 ssm 0,0
893 b,n perf_rdr_shift_out_W_leave
894 nop
895 ssm 0,0
896 nop
897
898 ;
899 ; RDR 25 write sequence
900 ;
901 sync
902 ssm 0,0
903 STDIAG (25)
904 ssm 0,0
905 b,n perf_rdr_shift_out_W_leave
906 nop
907 ssm 0,0
908 nop
909
910 ;
911 ; RDR 26 write sequence
912 ;
913 sync
914 ssm 0,0
915 STDIAG (10)
916 STDIAG (26)
917 ssm 0,0
918 b,n perf_rdr_shift_out_W_leave
919 ssm 0,0
920 nop
921
922 ;
923 ; RDR 27 write sequence
924 ;
925 sync
926 ssm 0,0
927 STDIAG (11)
928 STDIAG (27)
929 ssm 0,0
930 b,n perf_rdr_shift_out_W_leave
931 ssm 0,0
932 nop
933
934 ;
935 ; RDR 28 write sequence
936 ;
937 sync
938 ssm 0,0
939 STDIAG (28)
940 ssm 0,0
941 b,n perf_rdr_shift_out_W_leave
942 nop
943 ssm 0,0
944 nop
945
946 ;
947 ; RDR 29 write sequence
948 ;
949 sync
950 ssm 0,0
951 STDIAG (29)
952 ssm 0,0
953 b,n perf_rdr_shift_out_W_leave
954 nop
955 ssm 0,0
956 nop
957
958 ;
959 ; RDR 30 write sequence
960 ;
961 sync
962 ssm 0,0
963 STDIAG (30)
964 ssm 0,0
965 b,n perf_rdr_shift_out_W_leave
966 nop
967 ssm 0,0
968 nop
969
970 ;
971 ; RDR 31 write sequence
972 ;
973 sync
974 ssm 0,0
975 STDIAG (31)
976 ssm 0,0
977 b,n perf_rdr_shift_out_W_leave
978 nop
979 ssm 0,0
980 nop
981
982perf_rdr_shift_out_W_leave:
983 bve (%r2)
984 .exit
985 MTDIAG_2 (23) ; restore DR2
986 .procend
987
988
989;***********************************************************************
990;*
991;* Name: rdr_shift_in_U
992;*
993;* Description:
994;* This routine shifts data in from the RDR in arg0 and returns
995;* the result in ret0. If the RDR is <= 64 bits in length, it
996;* is shifted shifted backup immediately. This is to compensate
997;* for RDR10 which has bits that preclude PDC stack operations
998;* when they are in the wrong state.
999;*
1000;* Arguments:
1001;* arg0 : rdr to be read
1002;* arg1 : bit length of rdr
1003;*
1004;* Returns:
1005;* ret0 = next 64 bits of rdr data from staging register
1006;*
1007;* Register usage:
1008;* arg0 : rdr to be read
1009;* arg1 : bit length of rdr
1010;* %r24 - original DR2 value
1011;* %r23 - DR2 | DR2_SLOW_RET
1012;* %r1 - scratch
1013;*
1014;***********************************************************************
1015
1016 .export perf_rdr_shift_in_U,code
1017perf_rdr_shift_in_U:
1018 .proc
1019 .callinfo frame=0,NO_CALLS
1020 .entry
1021
1022; read(shift in) the RDR.
1023;
1024; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any
1025; shifting is done, from or to, remote diagnose registers.
1026
1027 depdi,z 1,DR2_SLOW_RET,1,%r29
1028 MFDIAG_2 (24)
1029 or %r24,%r29,%r29
1030 MTDIAG_2 (29) ; set DR2_SLOW_RET
1031
1032 nop
1033 nop
1034 nop
1035 nop
1036
1037;
1038; Start of next 32-byte cacheline
1039;
1040 nop
1041 nop
1042 nop
1043 extrd,u arg1,63,6,%r1
1044
1045 mtsar %r1
1046 shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number
1047 blr %r1,%r0 ; branch to 8-instruction sequence
1048 nop
1049
1050;
1051; Start of next 32-byte cacheline
1052;
1053 SFDIAG (0) ; RDR 0 read sequence
1054 ssm 0,0
1055 MFDIAG_1 (28)
1056 shrpd ret0,%r0,%sar,%r1
1057 MTDIAG_1 (1)
1058 STDIAG (0)
1059 ssm 0,0
1060 b,n perf_rdr_shift_in_U_leave
1061
1062 SFDIAG (1) ; RDR 1 read sequence
1063 ssm 0,0
1064 MFDIAG_1 (28)
1065 shrpd ret0,%r0,%sar,%r1
1066 MTDIAG_1 (1)
1067 STDIAG (1)
1068 ssm 0,0
1069 b,n perf_rdr_shift_in_U_leave
1070
1071 sync ; RDR 2 read sequence
1072 ssm 0,0
1073 SFDIAG (4)
1074 ssm 0,0
1075 MFDIAG_1 (28)
1076 b,n perf_rdr_shift_in_U_leave
1077 ssm 0,0
1078 nop
1079
1080 sync ; RDR 3 read sequence
1081 ssm 0,0
1082 SFDIAG (3)
1083 ssm 0,0
1084 MFDIAG_1 (28)
1085 b,n perf_rdr_shift_in_U_leave
1086 ssm 0,0
1087 nop
1088
1089 sync ; RDR 4 read sequence
1090 ssm 0,0
1091 SFDIAG (4)
1092 ssm 0,0
1093 MFDIAG_1 (28)
1094 b,n perf_rdr_shift_in_U_leave
1095 ssm 0,0
1096 nop
1097
1098 sync ; RDR 5 read sequence
1099 ssm 0,0
1100 SFDIAG (5)
1101 ssm 0,0
1102 MFDIAG_1 (28)
1103 b,n perf_rdr_shift_in_U_leave
1104 ssm 0,0
1105 nop
1106
1107 sync ; RDR 6 read sequence
1108 ssm 0,0
1109 SFDIAG (6)
1110 ssm 0,0
1111 MFDIAG_1 (28)
1112 b,n perf_rdr_shift_in_U_leave
1113 ssm 0,0
1114 nop
1115
1116 sync ; RDR 7 read sequence
1117 ssm 0,0
1118 SFDIAG (7)
1119 ssm 0,0
1120 MFDIAG_1 (28)
1121 b,n perf_rdr_shift_in_U_leave
1122 ssm 0,0
1123 nop
1124
1125 b,n perf_rdr_shift_in_U_leave
1126 nop
1127 nop
1128 nop
1129 nop
1130 nop
1131 nop
1132 nop
1133
1134 SFDIAG (9) ; RDR 9 read sequence
1135 ssm 0,0
1136 MFDIAG_1 (28)
1137 shrpd ret0,%r0,%sar,%r1
1138 MTDIAG_1 (1)
1139 STDIAG (9)
1140 ssm 0,0
1141 b,n perf_rdr_shift_in_U_leave
1142
1143 SFDIAG (10) ; RDR 10 read sequence
1144 ssm 0,0
1145 MFDIAG_1 (28)
1146 shrpd ret0,%r0,%sar,%r1
1147 MTDIAG_1 (1)
1148 STDIAG (10)
1149 ssm 0,0
1150 b,n perf_rdr_shift_in_U_leave
1151
1152 SFDIAG (11) ; RDR 11 read sequence
1153 ssm 0,0
1154 MFDIAG_1 (28)
1155 shrpd ret0,%r0,%sar,%r1
1156 MTDIAG_1 (1)
1157 STDIAG (11)
1158 ssm 0,0
1159 b,n perf_rdr_shift_in_U_leave
1160
1161 SFDIAG (12) ; RDR 12 read sequence
1162 ssm 0,0
1163 MFDIAG_1 (28)
1164 shrpd ret0,%r0,%sar,%r1
1165 MTDIAG_1 (1)
1166 STDIAG (12)
1167 ssm 0,0
1168 b,n perf_rdr_shift_in_U_leave
1169
1170 SFDIAG (13) ; RDR 13 read sequence
1171 ssm 0,0
1172 MFDIAG_1 (28)
1173 shrpd ret0,%r0,%sar,%r1
1174 MTDIAG_1 (1)
1175 STDIAG (13)
1176 ssm 0,0
1177 b,n perf_rdr_shift_in_U_leave
1178
1179 SFDIAG (14) ; RDR 14 read sequence
1180 ssm 0,0
1181 MFDIAG_1 (28)
1182 shrpd ret0,%r0,%sar,%r1
1183 MTDIAG_1 (1)
1184 STDIAG (14)
1185 ssm 0,0
1186 b,n perf_rdr_shift_in_U_leave
1187
1188 SFDIAG (15) ; RDR 15 read sequence
1189 ssm 0,0
1190 MFDIAG_1 (28)
1191 shrpd ret0,%r0,%sar,%r1
1192 MTDIAG_1 (1)
1193 STDIAG (15)
1194 ssm 0,0
1195 b,n perf_rdr_shift_in_U_leave
1196
1197 sync ; RDR 16 read sequence
1198 ssm 0,0
1199 SFDIAG (16)
1200 ssm 0,0
1201 MFDIAG_1 (28)
1202 b,n perf_rdr_shift_in_U_leave
1203 ssm 0,0
1204 nop
1205
1206 SFDIAG (17) ; RDR 17 read sequence
1207 ssm 0,0
1208 MFDIAG_1 (28)
1209 shrpd ret0,%r0,%sar,%r1
1210 MTDIAG_1 (1)
1211 STDIAG (17)
1212 ssm 0,0
1213 b,n perf_rdr_shift_in_U_leave
1214
1215 SFDIAG (18) ; RDR 18 read sequence
1216 ssm 0,0
1217 MFDIAG_1 (28)
1218 shrpd ret0,%r0,%sar,%r1
1219 MTDIAG_1 (1)
1220 STDIAG (18)
1221 ssm 0,0
1222 b,n perf_rdr_shift_in_U_leave
1223
1224 b,n perf_rdr_shift_in_U_leave
1225 nop
1226 nop
1227 nop
1228 nop
1229 nop
1230 nop
1231 nop
1232
1233 sync ; RDR 20 read sequence
1234 ssm 0,0
1235 SFDIAG (20)
1236 ssm 0,0
1237 MFDIAG_1 (28)
1238 b,n perf_rdr_shift_in_U_leave
1239 ssm 0,0
1240 nop
1241
1242 sync ; RDR 21 read sequence
1243 ssm 0,0
1244 SFDIAG (21)
1245 ssm 0,0
1246 MFDIAG_1 (28)
1247 b,n perf_rdr_shift_in_U_leave
1248 ssm 0,0
1249 nop
1250
1251 sync ; RDR 22 read sequence
1252 ssm 0,0
1253 SFDIAG (22)
1254 ssm 0,0
1255 MFDIAG_1 (28)
1256 b,n perf_rdr_shift_in_U_leave
1257 ssm 0,0
1258 nop
1259
1260 sync ; RDR 23 read sequence
1261 ssm 0,0
1262 SFDIAG (23)
1263 ssm 0,0
1264 MFDIAG_1 (28)
1265 b,n perf_rdr_shift_in_U_leave
1266 ssm 0,0
1267 nop
1268
1269 sync ; RDR 24 read sequence
1270 ssm 0,0
1271 SFDIAG (24)
1272 ssm 0,0
1273 MFDIAG_1 (28)
1274 b,n perf_rdr_shift_in_U_leave
1275 ssm 0,0
1276 nop
1277
1278 sync ; RDR 25 read sequence
1279 ssm 0,0
1280 SFDIAG (25)
1281 ssm 0,0
1282 MFDIAG_1 (28)
1283 b,n perf_rdr_shift_in_U_leave
1284 ssm 0,0
1285 nop
1286
1287 SFDIAG (26) ; RDR 26 read sequence
1288 ssm 0,0
1289 MFDIAG_1 (28)
1290 shrpd ret0,%r0,%sar,%r1
1291 MTDIAG_1 (1)
1292 STDIAG (26)
1293 ssm 0,0
1294 b,n perf_rdr_shift_in_U_leave
1295
1296 SFDIAG (27) ; RDR 27 read sequence
1297 ssm 0,0
1298 MFDIAG_1 (28)
1299 shrpd ret0,%r0,%sar,%r1
1300 MTDIAG_1 (1)
1301 STDIAG (27)
1302 ssm 0,0
1303 b,n perf_rdr_shift_in_U_leave
1304
1305 sync ; RDR 28 read sequence
1306 ssm 0,0
1307 SFDIAG (28)
1308 ssm 0,0
1309 MFDIAG_1 (28)
1310 b,n perf_rdr_shift_in_U_leave
1311 ssm 0,0
1312 nop
1313
1314 b,n perf_rdr_shift_in_U_leave
1315 nop
1316 nop
1317 nop
1318 nop
1319 nop
1320 nop
1321 nop
1322
1323 SFDIAG (30) ; RDR 30 read sequence
1324 ssm 0,0
1325 MFDIAG_1 (28)
1326 shrpd ret0,%r0,%sar,%r1
1327 MTDIAG_1 (1)
1328 STDIAG (30)
1329 ssm 0,0
1330 b,n perf_rdr_shift_in_U_leave
1331
1332 SFDIAG (31) ; RDR 31 read sequence
1333 ssm 0,0
1334 MFDIAG_1 (28)
1335 shrpd ret0,%r0,%sar,%r1
1336 MTDIAG_1 (1)
1337 STDIAG (31)
1338 ssm 0,0
1339 b,n perf_rdr_shift_in_U_leave
1340 nop
1341
1342perf_rdr_shift_in_U_leave:
1343 bve (%r2)
1344 .exit
1345 MTDIAG_2 (24) ; restore DR2
1346 .procend
1347
1348;***********************************************************************
1349;*
1350;* Name: rdr_shift_out_U
1351;*
1352;* Description:
1353;* This routine moves data to the RDR's. The double-word that
1354;* arg1 points to is loaded and moved into the staging register.
1355;* Then the STDIAG instruction for the RDR # in arg0 is called
1356;* to move the data to the RDR.
1357;*
1358;* Arguments:
1359;* arg0 = rdr target
1360;* arg1 = buffer pointer
1361;*
1362;* Returns:
1363;* None
1364;*
1365;* Register usage:
1366;* arg0 = rdr target
1367;* arg1 = buffer pointer
1368;* %r24 - DR2 | DR2_SLOW_RET
1369;* %r23 - original DR2 value
1370;*
1371;***********************************************************************
1372
1373 .export perf_rdr_shift_out_U,code
1374perf_rdr_shift_out_U:
1375 .proc
1376 .callinfo frame=0,NO_CALLS
1377 .entry
1378
1379;
1380; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any
1381; shifting is done, from or to, the remote diagnose registers.
1382;
1383
1384 depdi,z 1,DR2_SLOW_RET,1,%r24
1385 MFDIAG_2 (23)
1386 or %r24,%r23,%r24
1387 MTDIAG_2 (24) ; set DR2_SLOW_RET
1388
1389 MTDIAG_1 (25) ; data to the staging register
1390 shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number
1391 blr %r1,%r0 ; branch to 8-instruction sequence
1392 nop
1393
1394;
1395; 32-byte cachline aligned
1396;
1397
1398 sync ; RDR 0 write sequence
1399 ssm 0,0
1400 STDIAG (0)
1401 ssm 0,0
1402 b,n perf_rdr_shift_out_U_leave
1403 nop
1404 ssm 0,0
1405 nop
1406
1407 sync ; RDR 1 write sequence
1408 ssm 0,0
1409 STDIAG (1)
1410 ssm 0,0
1411 b,n perf_rdr_shift_out_U_leave
1412 nop
1413 ssm 0,0
1414 nop
1415
1416 sync ; RDR 2 write sequence
1417 ssm 0,0
1418 STDIAG (2)
1419 ssm 0,0
1420 b,n perf_rdr_shift_out_U_leave
1421 nop
1422 ssm 0,0
1423 nop
1424
1425 sync ; RDR 3 write sequence
1426 ssm 0,0
1427 STDIAG (3)
1428 ssm 0,0
1429 b,n perf_rdr_shift_out_U_leave
1430 nop
1431 ssm 0,0
1432 nop
1433
1434 sync ; RDR 4 write sequence
1435 ssm 0,0
1436 STDIAG (4)
1437 ssm 0,0
1438 b,n perf_rdr_shift_out_U_leave
1439 nop
1440 ssm 0,0
1441 nop
1442
1443 sync ; RDR 5 write sequence
1444 ssm 0,0
1445 STDIAG (5)
1446 ssm 0,0
1447 b,n perf_rdr_shift_out_U_leave
1448 nop
1449 ssm 0,0
1450 nop
1451
1452 sync ; RDR 6 write sequence
1453 ssm 0,0
1454 STDIAG (6)
1455 ssm 0,0
1456 b,n perf_rdr_shift_out_U_leave
1457 nop
1458 ssm 0,0
1459 nop
1460
1461 sync ; RDR 7 write sequence
1462 ssm 0,0
1463 STDIAG (7)
1464 ssm 0,0
1465 b,n perf_rdr_shift_out_U_leave
1466 nop
1467 ssm 0,0
1468 nop
1469
1470 sync ; RDR 8 write sequence
1471 ssm 0,0
1472 STDIAG (8)
1473 ssm 0,0
1474 b,n perf_rdr_shift_out_U_leave
1475 nop
1476 ssm 0,0
1477 nop
1478
1479 sync ; RDR 9 write sequence
1480 ssm 0,0
1481 STDIAG (9)
1482 ssm 0,0
1483 b,n perf_rdr_shift_out_U_leave
1484 nop
1485 ssm 0,0
1486 nop
1487
1488 sync ; RDR 10 write sequence
1489 ssm 0,0
1490 STDIAG (10)
1491 ssm 0,0
1492 b,n perf_rdr_shift_out_U_leave
1493 nop
1494 ssm 0,0
1495 nop
1496
1497 sync ; RDR 11 write sequence
1498 ssm 0,0
1499 STDIAG (11)
1500 ssm 0,0
1501 b,n perf_rdr_shift_out_U_leave
1502 nop
1503 ssm 0,0
1504 nop
1505
1506 sync ; RDR 12 write sequence
1507 ssm 0,0
1508 STDIAG (12)
1509 ssm 0,0
1510 b,n perf_rdr_shift_out_U_leave
1511 nop
1512 ssm 0,0
1513 nop
1514
1515 sync ; RDR 13 write sequence
1516 ssm 0,0
1517 STDIAG (13)
1518 ssm 0,0
1519 b,n perf_rdr_shift_out_U_leave
1520 nop
1521 ssm 0,0
1522 nop
1523
1524 sync ; RDR 14 write sequence
1525 ssm 0,0
1526 STDIAG (14)
1527 ssm 0,0
1528 b,n perf_rdr_shift_out_U_leave
1529 nop
1530 ssm 0,0
1531 nop
1532
1533 sync ; RDR 15 write sequence
1534 ssm 0,0
1535 STDIAG (15)
1536 ssm 0,0
1537 b,n perf_rdr_shift_out_U_leave
1538 nop
1539 ssm 0,0
1540 nop
1541
1542 sync ; RDR 16 write sequence
1543 ssm 0,0
1544 STDIAG (16)
1545 ssm 0,0
1546 b,n perf_rdr_shift_out_U_leave
1547 nop
1548 ssm 0,0
1549 nop
1550
1551 sync ; RDR 17 write sequence
1552 ssm 0,0
1553 STDIAG (17)
1554 ssm 0,0
1555 b,n perf_rdr_shift_out_U_leave
1556 nop
1557 ssm 0,0
1558 nop
1559
1560 sync ; RDR 18 write sequence
1561 ssm 0,0
1562 STDIAG (18)
1563 ssm 0,0
1564 b,n perf_rdr_shift_out_U_leave
1565 nop
1566 ssm 0,0
1567 nop
1568
1569 sync ; RDR 19 write sequence
1570 ssm 0,0
1571 STDIAG (19)
1572 ssm 0,0
1573 b,n perf_rdr_shift_out_U_leave
1574 nop
1575 ssm 0,0
1576 nop
1577
1578 sync ; RDR 20 write sequence
1579 ssm 0,0
1580 STDIAG (20)
1581 ssm 0,0
1582 b,n perf_rdr_shift_out_U_leave
1583 nop
1584 ssm 0,0
1585 nop
1586
1587 sync ; RDR 21 write sequence
1588 ssm 0,0
1589 STDIAG (21)
1590 ssm 0,0
1591 b,n perf_rdr_shift_out_U_leave
1592 nop
1593 ssm 0,0
1594 nop
1595
1596 sync ; RDR 22 write sequence
1597 ssm 0,0
1598 STDIAG (22)
1599 ssm 0,0
1600 b,n perf_rdr_shift_out_U_leave
1601 nop
1602 ssm 0,0
1603 nop
1604
1605 sync ; RDR 23 write sequence
1606 ssm 0,0
1607 STDIAG (23)
1608 ssm 0,0
1609 b,n perf_rdr_shift_out_U_leave
1610 nop
1611 ssm 0,0
1612 nop
1613
1614 sync ; RDR 24 write sequence
1615 ssm 0,0
1616 STDIAG (24)
1617 ssm 0,0
1618 b,n perf_rdr_shift_out_U_leave
1619 nop
1620 ssm 0,0
1621 nop
1622
1623 sync ; RDR 25 write sequence
1624 ssm 0,0
1625 STDIAG (25)
1626 ssm 0,0
1627 b,n perf_rdr_shift_out_U_leave
1628 nop
1629 ssm 0,0
1630 nop
1631
1632 sync ; RDR 26 write sequence
1633 ssm 0,0
1634 STDIAG (26)
1635 ssm 0,0
1636 b,n perf_rdr_shift_out_U_leave
1637 nop
1638 ssm 0,0
1639 nop
1640
1641 sync ; RDR 27 write sequence
1642 ssm 0,0
1643 STDIAG (27)
1644 ssm 0,0
1645 b,n perf_rdr_shift_out_U_leave
1646 nop
1647 ssm 0,0
1648 nop
1649
1650 sync ; RDR 28 write sequence
1651 ssm 0,0
1652 STDIAG (28)
1653 ssm 0,0
1654 b,n perf_rdr_shift_out_U_leave
1655 nop
1656 ssm 0,0
1657 nop
1658
1659 sync ; RDR 29 write sequence
1660 ssm 0,0
1661 STDIAG (29)
1662 ssm 0,0
1663 b,n perf_rdr_shift_out_U_leave
1664 nop
1665 ssm 0,0
1666 nop
1667
1668 sync ; RDR 30 write sequence
1669 ssm 0,0
1670 STDIAG (30)
1671 ssm 0,0
1672 b,n perf_rdr_shift_out_U_leave
1673 nop
1674 ssm 0,0
1675 nop
1676
1677 sync ; RDR 31 write sequence
1678 ssm 0,0
1679 STDIAG (31)
1680 ssm 0,0
1681 b,n perf_rdr_shift_out_U_leave
1682 nop
1683 ssm 0,0
1684 nop
1685
1686perf_rdr_shift_out_U_leave:
1687 bve (%r2)
1688 .exit
1689 MTDIAG_2 (23) ; restore DR2
1690 .procend
1691
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 @@
1/*
2 * Imagine for use with the Onyx (PCX-U) CPU interface
3 *
4 * Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org>
5 * Copyright (C) 2001 Hewlett-Packard (Grant Grundler)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#ifndef PERF_IMAGES_H
22#define PERF_IMAGES_H
23
24/* Magic numbers taken without modification from HPUX stuff */
25
26#define PCXU_IMAGE_SIZE 584
27
28static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] = {
29/*
30 * CPI:
31 *
32 * Counts the following:
33 *
34 * ctr0 : total cycles
35 * ctr1 : total cycles where nothing retired
36 * ctr2 : total instructions retired, including nullified
37 * ctr3 : total instructions retired, less nullified instructions
38 */
39 {
40 0x4c00c000, 0x00000000, 0x00060000, 0x00000000,
41 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
42 0x0101ffff, 0xfffff104, 0xe000c07f, 0xfffffffc,
43 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
44 0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00,
45 0x000fffff, 0x00000000, 0x00000000, 0x00ffffff,
46 0xfffff000, 0x0000000f, 0xffffffff, 0xff000000,
47 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
48 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
49 0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000,
50 0xf0000030, 0x00003c00, 0x067f080c, 0x02019fc0,
51 0x02804067, 0xf0009030, 0x19fc002c, 0x40067f08,
52 0x0c12019f, 0xc0028440, 0x67f00091, 0x3019fc00,
53 0x2fc007ff, 0xf800f001, 0xfffe003c, 0x007fff80,
54 0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00,
55 0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800,
56 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003,
57 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f,
58 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c,
59 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0,
60 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000,
61 0x00000000, 0x00000000, 0x00000000, 0x00000000,
62 0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
63 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
64 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
65 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
66 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
67 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
68 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
69 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
70 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
71 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
72 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
73 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
74 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
75 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
76 0xffffffff, 0xffffffff},
77
78/* Bus utilization image (bus_util)
79 *
80 * ctr0 : counts address valid cycles
81 * ctr1 : counts data valid cycles
82 * ctr2 : counts overflow from counter 0
83 * ctr3 : counts overflow from counter 1
84 */
85 {
86 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
87 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
88 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
89 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
90 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
91 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
92 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
93 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
94 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
95 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
96 0x0000000c, 0x00003c00, 0x07930000, 0x0041e4c0,
97 0x01002079, 0x3000800c, 0x1e4c0030, 0x00279300,
98 0x010049e4, 0xc0014022, 0x79300090, 0x0c9e4c00,
99 0x34004793, 0x00020051, 0xe4c00180, 0x24793000,
100 0xa00d1e4c, 0x00380067, 0x93000300, 0x59e4c001,
101 0xc0267930, 0x00b00d9e, 0x4c003fff, 0xffffffff,
102 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
103 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
104 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
105 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
106 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00,
107 0x00000000, 0x00000000, 0x00000000, 0x00000000,
108 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
109 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
110 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
111 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
112 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
113 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
114 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
115 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
116 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
117 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
118 0x00100000, 0x00000000, 0xffffffff, 0xffffffff,
119 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
120 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
121 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
122 0xffffffff, 0xffffffff },
123
124/*
125 * TLB counts (same as tlbStats image):
126 *
127 * Counts the following:
128 *
129 * ctr0: DTLB misses
130 * ctr1: ITLB misses
131 * ctr2: total cycles in the miss handlers
132 * ctr3: total cycles
133 */
134
135 {
136 0x0c00c000, 0x00000000, 0x00060000, 0x00000000,
137 0xe7e7e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
138 0x0101ffff, 0xfffff104, 0xe000c06a, 0xafffc85c,
139 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
140 0x01b9e000, 0x0001b8c0, 0x00000000, 0x0fffff00,
141 0x000fffff, 0x00000000, 0x00000000, 0x00400000,
142 0x00001000, 0x00000004, 0x00000000, 0x01000000,
143 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
144 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
145 0xfff55ff5, 0xffffffff, 0xffffffff, 0xf0000000,
146 0xf0000000, 0x00003c00, 0x01ff0001, 0x08007fc2,
147 0x02c1001f, 0xf0807100, 0x1bfc200c, 0x4806ff00,
148 0x03f001ff, 0xfe003c00, 0x7fff800f, 0x001fffe0,
149 0x03c007ff, 0xf800f001, 0xfffe003c, 0x007fff80,
150 0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00,
151 0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800,
152 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003,
153 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f,
154 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c,
155 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0,
156 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000,
157 0x00000000, 0x00000000, 0x00000000, 0x00000000,
158 0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
159 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
160 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
161 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
162 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
163 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
164 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
165 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
166 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
167 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
168 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
169 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
170 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
171 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
172 0xffffffff, 0xffffffff },
173
174/* tlbHandMiss
175 *
176 * ctr0: counts TLB misses
177 * ctr1: counts dmisses inside tlb miss handlers
178 * ctr2: counts cycles in the tlb miss handlers
179 * ctr3: counts overflows of ctr2
180 */
181{
1820x1c00c000,00000000,0x00060000,00000000,
1830xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380,
1840x0101ffff,0xfffff104,0xe000c06a,0xafffc85c,
1850x01380010,0x1fffffff,0xff000000,00000000,
1860x01b9e000,0x0001b8c0,00000000,0x0fffff00,
1870x000fffff,00000000,00000000,0x00400000,
1880x00001000,0x00000004,00000000,0x01000000,
1890x0000ffff,0xfffffff0,00000000,0x0fffffff,
1900xffff0000,00000000,0x6fffffff,0xffffffff,
1910xfff55ff5,0xffffffff,0xffffffff,0xf0000000,
1920xf0000000,0x00003c00,0x01fd0000,0x08007f42,
1930x0281001f,0xd080a100,0x19f42008,0x44067d08,
1940x0612019f,0x400084c0,0x67d00060,0x0047f400,
1950x042011fd,0x080b0404,0x7f4202c4,0x0167d080,
1960x311059f4,0x201c4816,0x7d000313,0x059f4001,
1970xfc007fff,0x800f001f,0xffe003c0,0x07fff800,
1980xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
1990xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
2000x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
2010x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
2020x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
20300000000,00000000,00000000,00000000,
2040x6fff0000,00000000,0x60000000,00000000,
2050xffffffff,0xffffffff,0xffffffff,0xffffffff,
2060xfffffc00,00000000,0xffffffff,0xffffffff,
2070xffffffff,0xffffffff,0xfffffc00,00000000,
2080xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
2090xfdffffff,0xffffffff,0xfe000000,00000000,
2100xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
2110xfdffffff,0xffffffff,0xfe000000,00000000,
2120xffffffff,0xfffff9ff,0xfe000000,00000000,
2130xffffffff,0xfffff9ff,0xfe000000,00000000,
2140x00030000,00000000,0xffffffff,0xffffffff,
2150xffffffff,0xffffffff,0xffffffff,0xffffffff,
2160xffffffff,0xffffffff,0xffffffff,0xffffffff,
2170xffffffff,0xffffffff,0xffffffff,0xffffffff,
2180xffffffff,0xffffffff},
219
220/* branch_taken image (ptkn image)
221 *
222 * ctr0: overflow for ctr1
223 * ctr1: predicted taken branches, actually taken
224 * ctr2: all predicted taken branches (nullfied or not)
225 * ctr3: overflow for ctr2
226 */
227
228 {
229 0xcc01e000, 0x00000000, 0x00060000, 0x00000000,
230 0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff,
231 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
232 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
233 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
234 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
235 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
236 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
237 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
238 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
239 0xf0000000, 0x00003c00, 0x04f90000, 0x02013e40,
240 0x0081004f, 0x90004060, 0x13e40018, 0x0024f900,
241 0x0802093e, 0x40028102, 0x4f9000c0, 0x6093e400,
242 0x380014f9, 0x00010205, 0x3e4000c1, 0x014f9000,
243 0x506053e4, 0x001c0034, 0xf9000902, 0x0d3e4002,
244 0xc1034f90, 0x00d060d3, 0xe4003fff, 0xffffffff,
245 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
246 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
247 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
248 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
249 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00,
250 0x00000000, 0x00000000, 0x00000000, 0x00000000,
251 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
252 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
253 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
254 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
255 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
256 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
257 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
258 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
259 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
260 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
261 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
262 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
263 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
264 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
265 0xffffffff, 0xffffffff },
266
267/* branch_nottaken (pntkn image)
268 *
269 * ctr0: overflow for ctr1
270 * ctr1: counts branches predicted not-taken, but actually taken
271 * ctr2: counts all predictable branches predicted not-taken
272 * ctr3: overflow for ctr2
273 */
274{
2750xcc01e000,00000000,0x00060000,00000000,
2760xc0c0c0e0,0xffb1fffb,0xfff7ffff,0xffffffff,
2770xffffffff,0xfffffffb,0x1fffbfff,0x7fffffff,
2780xfcc7ffff,0xffdffffa,0x5f000000,00000000,
2790xffffffff,0xffffffff,0xffffffff,0xffffffff,
2800xffffffff,00000000,0xffffffff,0xffffffff,
2810xffffffff,0xffffffff,0xffffffff,0xffffffff,
2820xffffffff,0xffffffff,0xffffffff,0xffffffff,
2830xffff0000,00000000,0xffffffff,0xffffffff,
2840xffffffff,0xffffffff,0xffffffff,0xf0000000,
2850xf0000060,0x00003c00,0x04f90000,0x02013e40,
2860x0081004f,0x90004060,0x13e40018,0x0024f900,
2870x0802093e,0x40028102,0x4f9000c0,0x6093e400,
2880x380014f9,0x00010205,0x3e4000c1,0x014f9000,
2890x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
2900xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
2910xffffffff,0xffffffff,0xffffffff,0xffffffff,
2920xffffffff,0xffffffff,0xffffffff,0xffffffff,
2930xffffffff,0xffffffff,0xffffffff,0xffffffff,
2940xffffffff,0xffffffff,0xffffffff,0xffffffff,
2950xffffffff,0xffffffff,0xffffffff,0xfffffc00,
29600000000,00000000,00000000,00000000,
2970xffff0000,00000000,0xf0000000,00000000,
2980xffffffff,0xffffffff,0xffffffff,0xffffffff,
2990xfffffc00,00000000,0xffffffff,0xffffffff,
3000xffffffff,0xffffffff,0xfffffc00,00000000,
3010xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
3020xfdffffff,0xffffffff,0xfe000000,00000000,
3030xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
3040xfdffffff,0xffffffff,0xfe000000,00000000,
3050xffffffff,0xfffff9ff,0xfe000000,00000000,
3060xffffffff,0xfffff9ff,0xfe000000,00000000,
3070x00030000,00000000,0xffffffff,0xffffffff,
3080xffffffff,0xffffffff,0xffffffff,0xffffffff,
3090xffffffff,0xffffffff,0xffffffff,0xffffffff,
3100xffffffff,0xffffffff,0xffffffff,0xffffffff,
3110xffffffff,0xffffffff},
312
313
314/* imiss image
315 *
316 * ctr0 : counts imiss aligned on 0
317 * ctr1 : counts imiss aligned on 4
318 * ctr2 : counts imiss aligned on 8
319 * ctr3 : counts imiss aligned on C
320 */
321 {
322 0x0c00c000, 0x00000000, 0x00010000, 0x00000000,
323 0xe7ebedee, 0xffffffff, 0xffffffff, 0xffffffff,
324 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
325 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
326 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
327 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
328 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
329 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
330 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
331 0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000,
332 0xf0000000, 0x00003c00, 0x007f0000, 0x01001fc0,
333 0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00,
334 0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00,
335 0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000,
336 0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003,
337 0x438007f0, 0x00e0f001, 0xfc003fff, 0xfffff800,
338 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003,
339 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f,
340 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f,
341 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff,
342 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000,
343 0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
345 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
346 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
347 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
348 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
349 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
350 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
351 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
352 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
353 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
354 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
355 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
356 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
357 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
358 0xffffffff, 0xffffffff},
359
360/* dmiss image
361 *
362 * ctr0 : counts cycles
363 * ctr1 : counts cycles where something retired
364 * ctr2 : counts dmisses
365 * ctr3 : (same as ctr2)
366 */
367 {
368 0x3c00c000, 0x00000000, 0x00060000, 0x00000000,
369 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff,
370 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
371 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
372 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
373 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
374 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
375 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
376 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
377 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
378 0xf0000000, 0x00003c04, 0x007f0009, 0x02001fc0,
379 0x0280c007, 0xf000b040, 0x01fc0030, 0x14007f00,
380 0x0d06001f, 0xc00381c0, 0x07f000f0, 0x8001fc00,
381 0x2024007f, 0x00090a00, 0x1fc00282, 0xc007f000,
382 0xb0c001fc, 0x00303400, 0x7f000d0e, 0x001fc003,
383 0x83c007f0, 0x00f00001, 0xfc0023ff, 0xfffff800,
384 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003,
385 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f,
386 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f,
387 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff,
388 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000,
389 0x00000000, 0x00000000, 0x00000000, 0x00000000,
390 0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
391 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
392 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
393 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
394 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
395 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
396 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
397 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
398 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
399 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
400 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
401 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
402 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
403 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
404 0xffffffff, 0xffffffff },
405
406/* dcmiss
407 *
408 * ctr0: counts store instructions retired
409 * ctr1: counts load instructions retired
410 * ctr2: counts dmisses
411 * ctr3: counts READ_SHARED_OR_PRIV and READ_PRIVATE transactions on Runway
412 */
413{
4140x2c90c000,00000000,0x00060000,00000000,
4150xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
4160xffffffff,0xffffffff,0xffffffff,0xffffffff,
4170xffffffff,0xffffffff,0xff000000,00000000,
4180xffffffff,0xffffffff,0xffffffff,0xffffffff,
4190xffffffff,00000000,0xffffffff,0xffffffff,
4200xffffffff,0xffffffff,0xffffffff,0xffffffff,
4210xffffffff,0xffffffff,0xffffffff,0xffffffff,
4220xffff0000,00000000,0x6fffffff,0xffffffff,
4230xffffffff,0xffffffff,0xffffffff,0xf0000000,
4240xf00000e8,0x00003c02,0x00bf0001,0x02002fc0,
4250x0080a00b,0xf0003040,0x02fc0010,0x1200bf00,
4260x0506002f,0xc00181a0,0x0bf00070,0x8002fc00,
4270x202200bf,0x00090a00,0x2fc00282,0xa00bf000,
4280xb0c002fc,0x00303200,0xbf000d0e,0x002fc003,
4290x83a00bf0,0x00ffffff,0xffffffff,0xffffffff,
4300xffffffff,0xffffffff,0xffffffff,0xffffffff,
4310xffffffff,0xffffffff,0xffffffff,0xffffffff,
4320xffffffff,0xffffffff,0xffffffff,0xffffffff,
4330xffffffff,0xffffffff,0xffffffff,0xffffffff,
4340xffffffff,0xffffffff,0xffffffff,0xfffffc00,
43500000000,00000000,00000000,00000000,
4360x6fff0000,00000000,0x60000000,00000000,
4370xffffffff,0xffffffff,0xffffffff,0xffffffff,
4380xfffffc00,00000000,0x55555555,0xd5555555,
4390x55555555,0x75555555,0x5e1ffc00,00000000,
4400xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
4410xfdffffff,0xffffffff,0xfe000000,00000000,
4420xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
4430xfdffffff,0xffffffff,0xfe000000,00000000,
4440xffffffff,0xfffff9ff,0xfe000000,00000000,
4450xffffffff,0xfffff9ff,0xfe000000,00000000,
4460x00100000,00000000,0xf8000000,00000000,
44700000000,00000000,0xf4000000,00000000,
4480xffffffff,0xffffffff,0x00ffffff,0xffffffff,
44900000000,00000000,0x00ffffff,0xffffffff,
4500xffffffff,0xffffffff },
451
452/* big_cpi
453 *
454 * ctr0: counts total cycles
455 * ctr1: counts overflows of ctr0 (for greater than 32-bit values)
456 * ctr2: counts overflows of ctr3 (for greater than 32-bit values)
457 * ctr3: counts unnullified instructions retired
458 */
459{
4600x0c00c000,00000000,0x00060000,00000000,
4610xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380,
4620x0101ffff,0xfffff104,0xe000c06a,0xafffc85c,
4630x01380010,0x1fffffff,0xff000000,00000000,
4640x01b9e000,0x0001b8c0,00000000,0x0fffff00,
4650x000fffff,00000000,00000000,0x00400000,
4660x00001000,0x00000004,00000000,0x01000000,
4670x0000ffff,0xfffffff0,00000000,0x0fffffff,
4680xffff0000,00000000,0x6fffffff,0xffffffff,
4690xfff55ff5,0xffffffff,0xffffffff,0xf0000000,
4700xf0000010,0x00003c00,0x01760008,0x00025d80,
4710x02800417,0x6000c001,0x25d80038,0x04017600,
4720x0901025d,0x8002c044,0x176000d0,0x1125d800,
4730x3c2001f6,0x08080400,0x7d820203,0x001f6080,
4740x804027d8,0x20282009,0xf6080a0c,0x027d8202,
4750x81041f60,0x80c08107,0xd8203030,0x41f6080c,
4760x04127d82,0x0382049f,0x6080e0c1,0x27d82038,
4770x4006f608,0x081011bd,0x82030400,0xef6080a1,
4780x013bd820,0x384806f6,0x00081211,0xbd800304,
4790x80ef6000,0xa1213bd8,0x003bc007,0xfff800f0,
4800x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
48100000000,00000000,00000000,00000000,
4820x6fff0000,00000000,0x60000000,00000000,
4830xffffffff,0xffffffff,0xffffffff,0xffffffff,
4840xfffffc00,00000000,0xffffffff,0xffffffff,
4850xffffffff,0xffffffff,0xfffffc00,00000000,
4860xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
4870xfdffffff,0xffffffff,0xfe000000,00000000,
4880xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
4890xfdffffff,0xffffffff,0xfe000000,00000000,
4900xffffffff,0xfffff9ff,0xfe000000,00000000,
4910xffffffff,0xfffff9ff,0xfe000000,00000000,
4920x00030000,00000000,0xffffffff,0xffffffff,
4930xffffffff,0xffffffff,0xffffffff,0xffffffff,
4940xffffffff,0xffffffff,0xffffffff,0xffffffff,
4950xffffffff,0xffffffff,0xffffffff,0xffffffff,
4960xffffffff,0xffffffff },
497
498/* big_ls
499 *
500 * ctr0:counts the total number of cycles for which local_stall_A1 is asserted.
501 * ctr1: is the overflow for counter 0.
502 * ctr2: counts IFLUSH_AV
503 * ctr3: is the overflow for counter 2.
504 */
505{
5060x0c000000,00000000,0x00060000,00000000,
5070xefefefef,0xffffffff,0xffffffff,0xffffffff,
5080xffffffff,0xffffffff,0xffffffff,0xffffffff,
5090xffffffff,0xffffffff,0xff000000,00000000,
5100xffffffff,0xffffffff,0xffffffff,0xffffffff,
5110xffffffff,00000000,0xffffffff,0xffffffff,
5120xffffffff,0xffffffff,0xffffffff,0xffffffff,
5130xffffffff,0xffffffff,0xffffffff,0xffffffff,
5140xffff0000,00000000,0x0fffffff,0xffffffff,
5150xffffffff,0xffffffff,0xffffffff,0xf0000000,
51600000000,0x00029408,0x02f50002,0x0800bd40,
5170x0202802f,0x5000a000,0x4bd40004,0x0812f500,
5180x030804bd,0x40024281,0x2f5000b0,0x010bd400,
5190x100842f5,0x00060810,0xbd400302,0x842f5000,
5200xe0014bd4,0x00140852,0xf5000708,0x14bd4003,
5210x42852f50,0x00ff001f,0xffe003c0,0x07fff800,
5220xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
5230xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
5240x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
5250x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
5260x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
52700000000,00000000,00000000,00000000,
5280x0df70000,00000000,00000000,00000000,
5290xffffffff,0xffffffff,0xffffffff,0xffffffff,
5300xfffffc00,00000000,0xffffffff,0xffffffff,
5310xffffffff,0xffffffff,0xfffffc00,00000000,
5320xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
5330xfdffffff,0xffffffff,0xfe000000,00000000,
5340xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
5350xfdffffff,0xffffffff,0xfe000000,00000000,
5360xffffffff,0xfffff9ff,0xfe000000,00000000,
5370xffffffff,0xfffff9ff,0xfe000000,00000000,
5380x00030000,00000000,0xffffffff,0xffffffff,
5390xffffffff,0xffffffff,0xffffffff,0xffffffff,
5400xffffffff,0xffffffff,0xffffffff,0xffffffff,
5410xffffffff,0xffffffff,0xffffffff,0xffffffff,
5420xffffffff,0xffffffff },
543
544/* br_abort
545 *
546 * ctr0: counts BRAD_STALLH
547 * ctr1: counts ONE_QUAD
548 * ctr2: counts BR0_ABRT
549 * ctr3: counts BR1_ABRT
550 */
551{
5520x0c002000,00000000,0x00060000,00000000,
5530xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
5540xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
5550xffffffff,0xffffffff,0xff000000,00000000,
5560xffffffff,0xffffffff,0xffffffff,0xffffffff,
5570xffffffff,00000000,0xffffffff,0xffffffff,
5580xffffffff,0xffffffff,0xffffffff,0xffffffff,
5590xffffffff,0xffffffff,0xffffffff,0xffffffff,
5600xffff0000,00000000,0x1fffffff,0xffffffff,
5610xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
56200000000,0x0003f800,0x007f000e,0x01001fc0,
5630x03c08007,0xf000c030,0x01fc0034,0x10007f00,
5640x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
5650x2420007f,0x00060900,0x1fc001c2,0x8007f000,
5660x40b001fc,0x00143000,0x7f00020d,0x001fc000,
5670xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
5680xfffffffe,0x003fffff,0xff800fff,0xffffe003,
5690xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
5700xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
5710xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
5720xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
57300000000,00000000,00000000,00000000,
5740x1a250000,00000000,0x10000000,00000000,
5750xffffffff,0xffffffff,0xffffffff,0xffffffff,
5760xfffffc00,00000000,0xffffffff,0xffffffff,
5770xffffffff,0xffffffff,0xfffffc00,00000000,
5780xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
5790xfdffffff,0xffffffff,0xfe000000,00000000,
5800xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
5810xfdffffff,0xffffffff,0xfe000000,00000000,
5820xffffffff,0xfffff9ff,0xfe000000,00000000,
5830xffffffff,0xfffff9ff,0xfe000000,00000000,
5840x00030000,00000000,0xffffffff,0xffffffff,
5850xffffffff,0xffffffff,0xffffffff,0xffffffff,
5860xffffffff,0xffffffff,0xffffffff,0xffffffff,
5870xffffffff,0xffffffff,0xffffffff,0xffffffff,
5880xffffffff,0xffffffff},
589
590/* isnt
591 *
592 * ctr0: counts the total number of cycles for which iside_notrans is asserted
593 * ctr1: counts the number of times iside_notrans is asserted for 1-4 cycles
594 * ctr2: counts the number of times iside_notrans is asserted for 5-7 cycles
595 * ctr3: counts the number of times iside_notrans is asserted for > 7 cycles
596 */
597{
5980x0c018000,00000000,0x00060000,00000000,
5990xefefefef,0xffffffff,0xffffffff,0xffffffff,
6000xffffffff,0xffffffff,0xffffffff,0xffffffff,
6010xffffffff,0xffffffff,0xff000000,00000000,
6020xffffffff,0xffffffff,0xffffffff,0xffffffff,
6030xffffffff,00000000,0xffffffff,0xffffffff,
6040xffffffff,0xffffffff,0xffffffff,0xffffffff,
6050xffffffff,0xffffffff,0xffffffff,0xffffffff,
6060xffff0000,00000000,0xcfffffff,0xffffffff,
6070xffffffff,0xffffffff,0xffffffff,0xf0000000,
60800000000,0x00021c20,0x03ff0808,0x1800ffc4,
6090x0204003f,0xf0004280,0x0ffc6020,0x8003ff00,
6100x043800ff,0xc8020c00,0x3ff00044,0x800ffca0,
6110x210003ff,0x00045800,0xffcc0214,0x003ff000,
6120x26800ffc,0xe0218003,0xff000278,0x00ffd002,
6130x1c003ff0,0x0028800f,0xfd002200,0x03ff0001,
6140xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
6150xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
6160x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
6170x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
6180x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
61900000000,00000000,00000000,00000000,
6200xcdff0000,00000000,0xc0000000,00000000,
6210xffffffff,0xffffffff,0xffffffff,0xffffffff,
6220xfffffc00,00000000,0xffffffff,0xffffffff,
6230xffffffff,0xffffffff,0xfffffc00,00000000,
6240xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
6250xfdffffff,0xffffffff,0xfe000000,00000000,
6260xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
6270xfdffffff,0xffffffff,0xfe000000,00000000,
6280xffffffff,0xfffff9ff,0xfe000000,00000000,
6290xffffffff,0xfffff9ff,0xfe000000,00000000,
6300x00030000,00000000,0xffffffff,0xffffffff,
6310xffffffff,0xffffffff,0xffffffff,0xffffffff,
6320xffffffff,0xffffffff,0xffffffff,0xffffffff,
6330xffffffff,0xffffffff,0xffffffff,0xffffffff,
6340xffffffff,0xffffffff},
635
636/* quadrant
637 *
638 * ctr0: Total number of instructions in quadrant 0
639 * ctr1: Total number of instructions in quadrant 1
640 * ctr2: Total number of instructions in quadrant 2
641 * ctr3: Total number of instructions in quadrant 3
642 * Works only with 32-bit
643 */
644
645 {
646 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
647 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
648 0x0101ffff, 0xfffff004, 0xe000407f, 0xfffffffc,
649 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
650 0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00,
651 0x000fffff, 0x00000000, 0x00000000, 0x00ffffff,
652 0xffcff000, 0x0000040f, 0xfffffffc, 0xff000000,
653 0x0080ffff, 0xffffcff0, 0x0000000c, 0x0fffffff,
654 0xfcff0000, 0x00000000, 0xffffffff, 0xffffffff,
655 0xfff55ff5, 0x5fffffff, 0xffffffff, 0xf0000000,
656 0xf00000f0, 0x00003c00, 0x007f0000, 0x01001fc0,
657 0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00,
658 0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00,
659 0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000,
660 0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003,
661 0x438007f0, 0x00e0f001, 0xfc003fff, 0xffffffff,
662 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
663 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
664 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
665 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
666 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00,
667 0x00000000, 0x00000000, 0x00000000, 0x00000000,
668 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
669 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
670 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
671 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
672 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
673 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
674 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
675 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
676 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
677 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
678 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
679 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
680 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
681 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
682 0xffffffff, 0xffffffff},
683
684/* rw_pdfet (READ_PRIV transactions)
685 *
686 * ctr0: counts address valid cycles
687 * ctr1: counts *all* data valid cycles
688 * ctr2: is the overflow from counter 0
689 * ctr3: is the overflow from counter 1
690 */
691{
6920x0c01e000,00000000,0x00060000,00000000,
6930xefefefef,0xffffffff,0xffffffff,0xffffffff,
6940xffffffff,0xffffffff,0xffffffff,0xffffffff,
6950xffffffff,0xffffffff,0xff000000,00000000,
6960xffffffff,0xffffffff,0xffffffff,0xffffffff,
6970xffffffff,00000000,0xffffffff,0xffffffff,
6980xffffffff,0xffffffff,0xffffffff,0xffffffff,
6990xffffffff,0xffffffff,0xffffffff,0xffffffff,
7000xffff0000,00000000,0xffffffff,0xffffffff,
7010xffffffff,0xffffffff,0xffffffff,0xf0000000,
7020x0000000c,0x00003c00,0x07930000,0x0041e4c0,
7030x01002079,0x3000800c,0x1e4c0030,0x00279300,
7040x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
7050x34004793,0x00020051,0xe4c00180,0x24793000,
7060xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
7070xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
7080xffffffff,0xffffffff,0xffffffff,0xffffffff,
7090xffffffff,0xffffffff,0xffffffff,0xffffffff,
7100xffffffff,0xffffffff,0xffffffff,0xffffffff,
7110xffffffff,0xffffffff,0xffffffff,0xffffffff,
7120xffffffff,0xffffffff,0xffffffff,0xfffffc00,
71300000000,00000000,00000000,00000000,
7140xffff0000,00000000,0xf0000000,00000000,
7150xffffffff,0xffffffff,0xffffffff,0xffffffff,
7160xfffffc00,00000000,0xffffffff,0xffffffff,
7170xffffffff,0xffffffff,0xfffffc00,00000000,
7180xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
7190xfdffffff,0xffffffff,0xfe000000,00000000,
7200xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
7210xfdffffff,0xffffffff,0xfe000000,00000000,
7220xffffffff,0xfffff9ff,0xfe000000,00000000,
7230xffffffff,0xfffff9ff,0xfe000000,00000000,
7240x00100000,00000000,0xf8000000,00000000,
72500000000,00000000,00000000,00000000,
7260xffffffff,0xffffffff,0x00ffffff,0xffffffff,
72700000000,00000000,00000000,00000000,
7280xffffffff,0xffffffff},
729
730/* rw_wdfet (WRITEBACKS)
731 *
732 * ctr0: counts address valid cycles
733 * ctr1: counts *all* data valid cycles
734 * ctr2: is the overflow from counter 0
735 * ctr3: is the overflow from counter 1
736 */
737{
7380x0c01e000,00000000,0x00060000,00000000,
7390xefefefef,0xffffffff,0xffffffff,0xffffffff,
7400xffffffff,0xffffffff,0xffffffff,0xffffffff,
7410xffffffff,0xffffffff,0xff000000,00000000,
7420xffffffff,0xffffffff,0xffffffff,0xffffffff,
7430xffffffff,00000000,0xffffffff,0xffffffff,
7440xffffffff,0xffffffff,0xffffffff,0xffffffff,
7450xffffffff,0xffffffff,0xffffffff,0xffffffff,
7460xffff0000,00000000,0xffffffff,0xffffffff,
7470xffffffff,0xffffffff,0xffffffff,0xf0000000,
7480x0000000c,0x00003c00,0x07930000,0x0041e4c0,
7490x01002079,0x3000800c,0x1e4c0030,0x00279300,
7500x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
7510x34004793,0x00020051,0xe4c00180,0x24793000,
7520xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
7530xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
7540xffffffff,0xffffffff,0xffffffff,0xffffffff,
7550xffffffff,0xffffffff,0xffffffff,0xffffffff,
7560xffffffff,0xffffffff,0xffffffff,0xffffffff,
7570xffffffff,0xffffffff,0xffffffff,0xffffffff,
7580xffffffff,0xffffffff,0xffffffff,0xfffffc00,
75900000000,00000000,00000000,00000000,
7600xffff0000,00000000,0xf0000000,00000000,
7610xffffffff,0xffffffff,0xffffffff,0xffffffff,
7620xfffffc00,00000000,0xffffffff,0xffffffff,
7630xffffffff,0xffffffff,0xfffffc00,00000000,
7640xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
7650xfdffffff,0xffffffff,0xfe000000,00000000,
7660xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
7670xfdffffff,0xffffffff,0xfe000000,00000000,
7680xffffffff,0xfffff9ff,0xfe000000,00000000,
7690xffffffff,0xfffff9ff,0xfe000000,00000000,
7700x00100000,00000000,0x98000000,00000000,
77100000000,00000000,00000000,00000000,
7720xffffffff,0xffffffff,0x00ffffff,0xffffffff,
77300000000,00000000,00000000,00000000,
7740xffffffff,0xffffffff},
775
776/* shlib_cpi
777 *
778 * ctr0: Total number of instructions in quad 0
779 * ctr1: Total number of CPU clock cycles in quad 0
780 * ctr2: total instructions without nullified
781 * ctr3: total number of CPU clock cycles
782 */
783 {
784 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
785 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
786 0x0101ffff, 0xfffff004, 0xe000407f, 0xfffffffc,
787 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
788 0x00000fff, 0xff00000f, 0xffffffff, 0xffffffff,
789 0xffffffff, 0x00000000, 0x00000000, 0x00ffffff,
790 0xffcff000, 0x0000000f, 0xfffffffc, 0xffffffff,
791 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
792 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
793 0xfff77ff5, 0x7fffffff, 0xffffffff, 0xf0000000,
794 0xf00000a0, 0x00003c00, 0x01ff0005, 0x08007fc0,
795 0x03c1001f, 0xf08030c0, 0x07fc203c, 0x4001ff08,
796 0x0118007f, 0xc003c500, 0x1ff08031, 0xc007fc00,
797 0x3fffffff, 0xf800ffff, 0xfffe003f, 0xffffff80,
798 0x0fffffff, 0xe003ffff, 0xfff800ff, 0xfffffe00,
799 0x3fffffff, 0x800fffff, 0xffe003ff, 0xfffff800,
800 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003,
801 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f,
802 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f,
803 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff,
804 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000,
805 0x00000000, 0x00000000, 0x00000000, 0x00000000,
806 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
807 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
808 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
809 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
810 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
811 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
812 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
813 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
814 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
815 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
816 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
817 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
818 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
819 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
820 0xffffffff, 0xffffffff},
821
822
823/* addr_inv_abort_alu
824 *
825 * ctr0: counts ABORT_ALU0L
826 * ctr1: counts ABORT_ALU1L
827 * ctr2: counts ADDR0_INVALID
828 * ctr3: counts ADDR1_INVALID
829 */
830
831{
8320x0c00c000,00000000,0x00060000,00000000,
8330xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
8340xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
8350xffffffff,0xffffffff,0xff000000,00000000,
8360xffffffff,0xffffffff,0xffffffff,0xffffffff,
8370xffffffff,00000000,0xffffffff,0xffffffff,
8380xffffffff,0xffffffff,0xffffffff,0xffffffff,
8390xffffffff,0xffffffff,0xffffffff,0xffffffff,
8400xffff0000,00000000,0x6fffffff,0xffffffff,
8410xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
84200000000,0x0003f800,0x007f000d,0x01001fc0,
8430x03008007,0xf000f030,0x01fc0038,0x10007f00,
8440x0905001f,0xc0020180,0x07f000b0,0x7001fc00,
8450x2820007f,0x00050900,0x1fc00102,0x8007f000,
8460x70b001fc,0x00183000,0x7f00010d,0x001fc000,
8470x038007f0,0x0030f001,0xfc000bff,0xfffff800,
8480xfffffffe,0x003fffff,0xff800fff,0xffffe003,
8490xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
8500xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
8510xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
8520xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
85300000000,00000000,00000000,00000000,
8540x65380000,00000000,0x60000000,00000000,
8550xffffffff,0xffffffff,0xffffffff,0xffffffff,
8560xfffffc00,00000000,0xffffffff,0xffffffff,
8570xffffffff,0xffffffff,0xfffffc00,00000000,
8580xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
8590xfdffffff,0xffffffff,0xfe000000,00000000,
8600xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
8610xfdffffff,0xffffffff,0xfe000000,00000000,
8620xffffffff,0xfffff9ff,0xfe000000,00000000,
8630xffffffff,0xfffff9ff,0xfe000000,00000000,
8640x00030000,00000000,0xffffffff,0xffffffff,
8650xffffffff,0xffffffff,0xffffffff,0xffffffff,
8660xffffffff,0xffffffff,0xffffffff,0xffffffff,
8670xffffffff,0xffffffff,0xffffffff,0xffffffff,
8680xffffffff,0xffffffff },
869
870
871
872/* brad_stall
873 *
874 * ctr0: counts the total number of cycles for which brad_stall is asserted
875 * ctr1: counts the number of times brad_stall is asserted for 1-4 cycles
876 * ctr2: counts the number of times brad_stall is asserted for 5-7 cycles
877 * ctr3: counts the number of times brad_stall is asserted for > 7 cycles
878 */
879{
8800x0c002000,00000000,0x00060000,00000000,
8810xefefefef,0xffffffff,0xffffffff,0xffffffff,
8820xffffffff,0xffffffff,0xffffffff,0xffffffff,
8830xffffffff,0xffffffff,0xff000000,00000000,
8840xffffffff,0xffffffff,0xffffffff,0xffffffff,
8850xffffffff,00000000,0xffffffff,0xffffffff,
8860xffffffff,0xffffffff,0xffffffff,0xffffffff,
8870xffffffff,0xffffffff,0xffffffff,0xffffffff,
8880xffff0000,00000000,0x1fffffff,0xffffffff,
8890xffffffff,0xffffffff,0xffffffff,0xf0000000,
89000000000,0x00021c20,0x03ff0808,0x1800ffc4,
8910x0204003f,0xf0004280,0x0ffc6020,0x8003ff00,
8920x043800ff,0xc8020c00,0x3ff00044,0x800ffca0,
8930x210003ff,0x00045800,0xffcc0214,0x003ff000,
8940x26800ffc,0xe0218003,0xff000278,0x00ffd002,
8950x1c003ff0,0x0028800f,0xfd002200,0x03ff0001,
8960xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
8970xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
8980x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
8990x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
9000x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
90100000000,00000000,00000000,00000000,
9020x1bff0000,00000000,0x10000000,00000000,
9030xffffffff,0xffffffff,0xffffffff,0xffffffff,
9040xfffffc00,00000000,0xffffffff,0xffffffff,
9050xffffffff,0xffffffff,0xfffffc00,00000000,
9060xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
9070xfdffffff,0xffffffff,0xfe000000,00000000,
9080xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
9090xfdffffff,0xffffffff,0xfe000000,00000000,
9100xffffffff,0xfffff9ff,0xfe000000,00000000,
9110xffffffff,0xfffff9ff,0xfe000000,00000000,
9120x00030000,00000000,0xffffffff,0xffffffff,
9130xffffffff,0xffffffff,0xffffffff,0xffffffff,
9140xffffffff,0xffffffff,0xffffffff,0xffffffff,
9150xffffffff,0xffffffff,0xffffffff,0xffffffff,
9160xffffffff,0xffffffff},
917
918/* cntl_in_pipel
919 *
920 * ctr0: counts the total number of cycles for which cntl_in_pipel is asserted
921 * ctr1: counts the number of times cntl_in_pipel is asserted for 1-4 cycles
922 * ctr2: counts the number of times cntl_in_pipel is asserted for 5-7 cycles
923 * ctr3: counts the number of times cntl_in_pipel is asserted for > 7 cycles
924 */
925{
9260x0c006000,00000000,0x00060000,00000000,
9270xefefefef,0xffffffff,0xffffffff,0xffffffff,
9280xffffffff,0xffffffff,0xffffffff,0xffffffff,
9290xffffffff,0xffffffff,0xff000000,00000000,
9300xffffffff,0xffffffff,0xffffffff,0xffffffff,
9310xffffffff,00000000,0xffffffff,0xffffffff,
9320xffffffff,0xffffffff,0xffffffff,0xffffffff,
9330xffffffff,0xffffffff,0xffffffff,0xffffffff,
9340xffff0000,00000000,0x3fffffff,0xffffffff,
9350xffffffff,0xffffffff,0xffffffff,0xf0000000,
93600000000,0x00021c00,0x03ff0808,0x1000ffc4,
9370x0206003f,0xf0004200,0x0ffc6020,0xa003ff00,
9380x043000ff,0xc8020e00,0x3ff00044,0x000ffca0,
9390x212003ff,0x00045000,0xffcc0216,0x003ff000,
9400x26000ffc,0xe021a003,0xff000270,0x00ffd002,
9410x1e003ff0,0x0028000f,0xfd002220,0x03ff0001,
9420xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
9430xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
9440x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
9450x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
9460x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
94700000000,00000000,00000000,00000000,
9480x3fff0000,00000000,0x30000000,00000000,
9490xffffffff,0xffffffff,0xffffffff,0xffffffff,
9500xfffffc00,00000000,0xffffffff,0xffffffff,
9510xffffffff,0xffffffff,0xfffffc00,00000000,
9520xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
9530xfdffffff,0xffffffff,0xfe000000,00000000,
9540xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
9550xfdffffff,0xffffffff,0xfe000000,00000000,
9560xffffffff,0xfffff9ff,0xfe000000,00000000,
9570xffffffff,0xfffff9ff,0xfe000000,00000000,
9580x00030000,00000000,0xffffffff,0xffffffff,
9590xffffffff,0xffffffff,0xffffffff,0xffffffff,
9600xffffffff,0xffffffff,0xffffffff,0xffffffff,
9610xffffffff,0xffffffff,0xffffffff,0xffffffff,
9620xffffffff,0xffffffff },
963
964
965/* dsnt_xfh
966 *
967 * ctr0: counts dside_notrans
968 * ctr1: counts xfhang
969 * ctr2: is the overflow for ctr0
970 * ctr3: is the overflow for ctr1
971 */
972{
9730x0c018000,00000000,0x00060000,00000000,
9740xefefefef,0xffffffff,0xffffffff,0xffffffff,
9750xffffffff,0xffffffff,0xffffffff,0xffffffff,
9760xffffffff,0xffffffff,0xff000000,00000000,
9770xffffffff,0xffffffff,0xffffffff,0xffffffff,
9780xffffffff,00000000,0xffffffff,0xffffffff,
9790xffffffff,0xffffffff,0xffffffff,0xffffffff,
9800xffffffff,0xffffffff,0xffffffff,0xffffffff,
9810xffff0000,00000000,0xcfffffff,0xffffffff,
9820xffffffff,0xffffffff,0xffffffff,0xf0000000,
98300000000,0x00030000,0x01f30000,0x00087cc0,
9840x0040041f,0x30002001,0x87cc000c,0x1001f300,
9850x0404087c,0xc0014104,0x1f300060,0x4187cc00,
9860x1c2001f3,0x00080808,0x7cc00242,0x041f3000,
9870xa08187cc,0x002c3001,0xf3000c0c,0x087cc003,
9880x43041f30,0x00e0c187,0xcc003fc0,0x07fff800,
9890xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
9900xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
9910x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
9920x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
9930x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
99400000000,00000000,00000000,00000000,
9950xcb3f0000,00000000,0xc0000000,00000000,
9960xffffffff,0xffffffff,0xffffffff,0xffffffff,
9970xfffffc00,00000000,0xffffffff,0xffffffff,
9980xffffffff,0xffffffff,0xfffffc00,00000000,
9990xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
10000xfdffffff,0xffffffff,0xfe000000,00000000,
10010xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
10020xfdffffff,0xffffffff,0xfe000000,00000000,
10030xffffffff,0xfffff9ff,0xfe000000,00000000,
10040xffffffff,0xfffff9ff,0xfe000000,00000000,
10050x00030000,00000000,0xffffffff,0xffffffff,
10060xffffffff,0xffffffff,0xffffffff,0xffffffff,
10070xffffffff,0xffffffff,0xffffffff,0xffffffff,
10080xffffffff,0xffffffff,0xffffffff,0xffffffff,
10090xffffffff,0xffffffff },
1010
1011/* fet_sig1
1012 *
1013 * ctr0: counts ICORE_AV
1014 * ctr1: counts ITRANS_STALL
1015 * ctr2: counts SEL_PCQH
1016 * ctr3: counts OUT_OF_CONTEXT
1017 */
1018{
10190x0c000000,00000000,0x00060000,00000000,
10200xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
10210xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
10220xffffffff,0xffffffff,0xff000000,00000000,
10230xffffffff,0xffffffff,0xffffffff,0xffffffff,
10240xffffffff,00000000,0xffffffff,0xffffffff,
10250xffffffff,0xffffffff,0xffffffff,0xffffffff,
10260xffffffff,0xffffffff,0xffffffff,0xffffffff,
10270xffff0000,00000000,0x0fffffff,0xffffffff,
10280xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
102900000000,0x0003f800,0x007f000e,0x01001fc0,
10300x03c08007,0xf000c030,0x01fc0034,0x10007f00,
10310x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
10320x2420007f,0x00060900,0x1fc001c2,0x8007f000,
10330x40b001fc,0x00143000,0x7f00020d,0x001fc000,
10340xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
10350xfffffffe,0x003fffff,0xff800fff,0xffffe003,
10360xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
10370xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
10380xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
10390xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
104000000000,00000000,00000000,00000000,
10410x07c10000,00000000,00000000,00000000,
10420xffffffff,0xffffffff,0xffffffff,0xffffffff,
10430xfffffc00,00000000,0xffffffff,0xffffffff,
10440xffffffff,0xffffffff,0xfffffc00,00000000,
10450xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
10460xfdffffff,0xffffffff,0xfe000000,00000000,
10470xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
10480xfdffffff,0xffffffff,0xfe000000,00000000,
10490xffffffff,0xfffff9ff,0xfe000000,00000000,
10500xffffffff,0xfffff9ff,0xfe000000,00000000,
10510x00030000,00000000,0xffffffff,0xffffffff,
10520xffffffff,0xffffffff,0xffffffff,0xffffffff,
10530xffffffff,0xffffffff,0xffffffff,0xffffffff,
10540xffffffff,0xffffffff,0xffffffff,0xffffffff,
10550xffffffff,0xffffffff},
1056
1057/* fet_sig2
1058 *
1059 * ctr0: counts ICORE_AV
1060 * ctr1: counts IRTN_AV
1061 * ctr2: counts ADDRESS_INC
1062 * ctr3: counts ADDRESS_DEC
1063 */
1064{
10650x0c000000,00000000,0x00060000,00000000,
10660xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
10670xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
10680xffffffff,0xffffffff,0xff000000,00000000,
10690xffffffff,0xffffffff,0xffffffff,0xffffffff,
10700xffffffff,00000000,0xffffffff,0xffffffff,
10710xffffffff,0xffffffff,0xffffffff,0xffffffff,
10720xffffffff,0xffffffff,0xffffffff,0xffffffff,
10730xffff0000,00000000,0x0fffffff,0xffffffff,
10740xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
107500000000,0x0003f800,0x007f000e,0x01001fc0,
10760x03c08007,0xf000c030,0x01fc0034,0x10007f00,
10770x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
10780x2420007f,0x00060900,0x1fc001c2,0x8007f000,
10790x40b001fc,0x00143000,0x7f00020d,0x001fc000,
10800xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
10810xfffffffe,0x003fffff,0xff800fff,0xffffe003,
10820xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
10830xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
10840xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
10850xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
108600000000,00000000,00000000,00000000,
10870x06930000,00000000,00000000,00000000,
10880xffffffff,0xffffffff,0xffffffff,0xffffffff,
10890xfffffc00,00000000,0xffffffff,0xffffffff,
10900xffffffff,0xffffffff,0xfffffc00,00000000,
10910xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
10920xfdffffff,0xffffffff,0xfe000000,00000000,
10930xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
10940xfdffffff,0xffffffff,0xfe000000,00000000,
10950xffffffff,0xfffff9ff,0xfe000000,00000000,
10960xffffffff,0xfffff9ff,0xfe000000,00000000,
10970x00030000,00000000,0xffffffff,0xffffffff,
10980xffffffff,0xffffffff,0xffffffff,0xffffffff,
10990xffffffff,0xffffffff,0xffffffff,0xffffffff,
11000xffffffff,0xffffffff,0xffffffff,0xffffffff,
11010xffffffff,0xffffffff },
1102
1103/* g7_1
1104 *
1105 * ctr0: counts HIT_RETRY0
1106 * ctr1: counts HIT_RETRY1
1107 * ctr2: counts GO_TAG_E
1108 * ctr3: counts GO_TAG_O
1109 */
1110{
11110x0c00e000,00000000,0x00060000,00000000,
11120xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
11130xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
11140xffffffff,0xffffffff,0xff000000,00000000,
11150xffffffff,0xffffffff,0xffffffff,0xffffffff,
11160xffffffff,00000000,0xffffffff,0xffffffff,
11170xffffffff,0xffffffff,0xffffffff,0xffffffff,
11180xffffffff,0xffffffff,0xffffffff,0xffffffff,
11190xffff0000,00000000,0x7fffffff,0xffffffff,
11200xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
112100000000,0x0003f800,0x007f000e,0x01001fc0,
11220x03c08007,0xf000c030,0x01fc0034,0x10007f00,
11230x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
11240x2420007f,0x00060900,0x1fc001c2,0x8007f000,
11250x40b001fc,0x00143000,0x7f00020d,0x001fc000,
11260xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
11270xfffffffe,0x003fffff,0xff800fff,0xffffe003,
11280xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
11290xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
11300xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
11310xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
113200000000,00000000,00000000,00000000,
11330x71c10000,00000000,0x70000000,00000000,
11340xffffffff,0xffffffff,0xffffffff,0xffffffff,
11350xfffffc00,00000000,0xffffffff,0xffffffff,
11360xffffffff,0xffffffff,0xfffffc00,00000000,
11370xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
11380xfdffffff,0xffffffff,0xfe000000,00000000,
11390xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
11400xfdffffff,0xffffffff,0xfe000000,00000000,
11410xffffffff,0xfffff9ff,0xfe000000,00000000,
11420xffffffff,0xfffff9ff,0xfe000000,00000000,
11430x00030000,00000000,0xffffffff,0xffffffff,
11440xffffffff,0xffffffff,0xffffffff,0xffffffff,
11450xffffffff,0xffffffff,0xffffffff,0xffffffff,
11460xffffffff,0xffffffff,0xffffffff,0xffffffff,
11470xffffffff,0xffffffff },
1148
1149/* g7_2
1150 *
1151 * ctr0: counts HIT_DM0
1152 * ctr1: counts HIT_DM1
1153 * ctr2: counts GO_STORE_E
1154 * ctr3: counts GO_STORE_O
1155 */
1156{
11570x0c00e000,00000000,0x00060000,00000000,
11580xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
11590xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
11600xffffffff,0xffffffff,0xff000000,00000000,
11610xffffffff,0xffffffff,0xffffffff,0xffffffff,
11620xffffffff,00000000,0xffffffff,0xffffffff,
11630xffffffff,0xffffffff,0xffffffff,0xffffffff,
11640xffffffff,0xffffffff,0xffffffff,0xffffffff,
11650xffff0000,00000000,0x7fffffff,0xffffffff,
11660xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
116700000000,0x0003f800,0x007f000e,0x01001fc0,
11680x03c08007,0xf000c030,0x01fc0034,0x10007f00,
11690x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
11700x2420007f,0x00060900,0x1fc001c2,0x8007f000,
11710x40b001fc,0x00143000,0x7f00020d,0x001fc000,
11720xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
11730xfffffffe,0x003fffff,0xff800fff,0xffffe003,
11740xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
11750xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
11760xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
11770xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
117800000000,00000000,00000000,00000000,
11790x72930000,00000000,0x70000000,00000000,
11800xffffffff,0xffffffff,0xffffffff,0xffffffff,
11810xfffffc00,00000000,0xffffffff,0xffffffff,
11820xffffffff,0xffffffff,0xfffffc00,00000000,
11830xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
11840xfdffffff,0xffffffff,0xfe000000,00000000,
11850xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
11860xfdffffff,0xffffffff,0xfe000000,00000000,
11870xffffffff,0xfffff9ff,0xfe000000,00000000,
11880xffffffff,0xfffff9ff,0xfe000000,00000000,
11890x00030000,00000000,0xffffffff,0xffffffff,
11900xffffffff,0xffffffff,0xffffffff,0xffffffff,
11910xffffffff,0xffffffff,0xffffffff,0xffffffff,
11920xffffffff,0xffffffff,0xffffffff,0xffffffff,
11930xffffffff,0xffffffff },
1194
1195/* g7_3
1196 *
1197 * ctr0: counts HIT_DV0
1198 * ctr1: counts HIT_DV1
1199 * ctr2: counts STBYPT_E (load bypasses from store queue)
1200 * ctr3: counts STBYPT_O
1201 */
1202{
12030x0c00e000,00000000,0x00060000,00000000,
12040xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
12050xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
12060xffffffff,0xffffffff,0xff000000,00000000,
12070xffffffff,0xffffffff,0xffffffff,0xffffffff,
12080xffffffff,00000000,0xffffffff,0xffffffff,
12090xffffffff,0xffffffff,0xffffffff,0xffffffff,
12100xffffffff,0xffffffff,0xffffffff,0xffffffff,
12110xffff0000,00000000,0x7fffffff,0xffffffff,
12120xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
121300000000,0x0003f800,0x007f0002,0x01001fc0,
12140x00c08007,0xf0000030,0x01fc0004,0x10007f00,
12150x0605001f,0xc001c180,0x07f00040,0x7001fc00,
12160x1420007f,0x000a0900,0x1fc002c2,0x8007f000,
12170x80b001fc,0x00243000,0x7f000e0d,0x001fc003,
12180xc38007f0,0x00c0f001,0xfc0037ff,0xfffff800,
12190xfffffffe,0x003fffff,0xff800fff,0xffffe003,
12200xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
12210xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
12220xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
12230xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
122400000000,00000000,00000000,00000000,
12250x77250000,00000000,0x70000000,00000000,
12260xffffffff,0xffffffff,0xffffffff,0xffffffff,
12270xfffffc00,00000000,0xffffffff,0xffffffff,
12280xffffffff,0xffffffff,0xfffffc00,00000000,
12290xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
12300xfdffffff,0xffffffff,0xfe000000,00000000,
12310xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
12320xfdffffff,0xffffffff,0xfe000000,00000000,
12330xffffffff,0xfffff9ff,0xfe000000,00000000,
12340xffffffff,0xfffff9ff,0xfe000000,00000000,
12350x00030000,00000000,0xffffffff,0xffffffff,
12360xffffffff,0xffffffff,0xffffffff,0xffffffff,
12370xffffffff,0xffffffff,0xffffffff,0xffffffff,
12380xffffffff,0xffffffff,0xffffffff,0xffffffff,
12390xffffffff,0xffffffff },
1240
1241/* g7_4
1242 *
1243 * ctr0: counts HIT_DIRTY0
1244 * ctr1: counts HIT_DIRTY1
1245 * ctr2: counts CA_BYP_E (quick launch)
1246 * ctr3: counts CA_BYP_O
1247 */
1248{
12490x0c00e000,00000000,0x00060000,00000000,
12500xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
12510xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
12520xffffffff,0xffffffff,0xff000000,00000000,
12530xffffffff,0xffffffff,0xffffffff,0xffffffff,
12540xffffffff,00000000,0xffffffff,0xffffffff,
12550xffffffff,0xffffffff,0xffffffff,0xffffffff,
12560xffffffff,0xffffffff,0xffffffff,0xffffffff,
12570xffff0000,00000000,0x7fffffff,0xffffffff,
12580xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
125900000000,0x0003f800,0x007f000e,0x01001fc0,
12600x03c08007,0xf000c030,0x01fc0034,0x10007f00,
12610x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
12620x2420007f,0x00060900,0x1fc001c2,0x8007f000,
12630x40b001fc,0x00143000,0x7f00020d,0x001fc000,
12640xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
12650xfffffffe,0x003fffff,0xff800fff,0xffffe003,
12660xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
12670xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
12680xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
12690xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
127000000000,00000000,00000000,00000000,
12710x7bb70000,00000000,0x70000000,00000000,
12720xffffffff,0xffffffff,0xffffffff,0xffffffff,
12730xfffffc00,00000000,0xffffffff,0xffffffff,
12740xffffffff,0xffffffff,0xfffffc00,00000000,
12750xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
12760xfdffffff,0xffffffff,0xfe000000,00000000,
12770xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
12780xfdffffff,0xffffffff,0xfe000000,00000000,
12790xffffffff,0xfffff9ff,0xfe000000,00000000,
12800xffffffff,0xfffff9ff,0xfe000000,00000000,
12810x00030000,00000000,0xffffffff,0xffffffff,
12820xffffffff,0xffffffff,0xffffffff,0xffffffff,
12830xffffffff,0xffffffff,0xffffffff,0xffffffff,
12840xffffffff,0xffffffff,0xffffffff,0xffffffff,
12850xffffffff,0xffffffff },
1286
1287
1288/* mpb_labort
1289 *
1290 * ctr0: counts L_ABORT_ALU0L
1291 * ctr1: counts L_ABORT_ALU1L
1292 * ctr2: counts MPB0H
1293 * ctr3: counts MPB1H
1294 */
1295{
12960x0c00c000,00000000,0x00060000,00000000,
12970xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
12980xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
12990xffffffff,0xffffffff,0xff000000,00000000,
13000xffffffff,0xffffffff,0xffffffff,0xffffffff,
13010xffffffff,00000000,0xffffffff,0xffffffff,
13020xffffffff,0xffffffff,0xffffffff,0xffffffff,
13030xffffffff,0xffffffff,0xffffffff,0xffffffff,
13040xffff0000,00000000,0x6fffffff,0xffffffff,
13050xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
130600000000,0x0003f800,0x007f000e,0x01001fc0,
13070x03c08007,0xf000c030,0x01fc0034,0x10007f00,
13080x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
13090x2420007f,0x00060900,0x1fc001c2,0x8007f000,
13100x40b001fc,0x00143000,0x7f00020d,0x001fc000,
13110xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
13120xfffffffe,0x003fffff,0xff800fff,0xffffe003,
13130xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
13140xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
13150xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
13160xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
131700000000,00000000,00000000,00000000,
13180x605c0000,00000000,0x60000000,00000000,
13190xffffffff,0xffffffff,0xffffffff,0xffffffff,
13200xfffffc00,00000000,0xffffffff,0xffffffff,
13210xffffffff,0xffffffff,0xfffffc00,00000000,
13220xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
13230xfdffffff,0xffffffff,0xfe000000,00000000,
13240xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
13250xfdffffff,0xffffffff,0xfe000000,00000000,
13260xffffffff,0xfffff9ff,0xfe000000,00000000,
13270xffffffff,0xfffff9ff,0xfe000000,00000000,
13280x00030000,00000000,0xffffffff,0xffffffff,
13290xffffffff,0xffffffff,0xffffffff,0xffffffff,
13300xffffffff,0xffffffff,0xffffffff,0xffffffff,
13310xffffffff,0xffffffff,0xffffffff,0xffffffff,
13320xffffffff,0xffffffff },
1333
1334/* panic
1335 *
1336 * ctr0: is the overflow for counter 1
1337 * ctr1: counts traps and RFI's
1338 * ctr2: counts panic traps
1339 * ctr3: is the overflow for counter 2
1340 */
1341{
13420x0c002000,00000000,0x00060000,00000000,
13430xe7efe0e0,0xffffffff,0xffffffff,0xffffffff,
13440xffffffff,0xffffffff,0xffffffff,0xfffffffc,
13450x41380030,0x1aabfff2,0x17000000,00000000,
13460x01b80000,0x3effffff,0xffffffff,0xffffffff,
13470xffffffff,00000000,00000000,0x00400000,
13480x00001fff,0xffffffff,0xffffffff,0xffffffff,
13490xffffffff,0xffffffff,0xffffffff,0xffffffff,
13500xffff0000,00000000,0x1fffffff,0xffffffff,
13510xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
13520xb0000000,0x00012c04,0x05790804,0x14013e44,
13530x0008004f,0x90000040,0x15e46000,0xc0047920,
13540x004a003e,0x40011080,0x0f900024,0x4003e460,
13550x00c80479,0x00023301,0x1e400100,0x4157d080,
13560x514053f4,0x40048014,0xfd000104,0x055f4600,
13570x4c0147d2,0x0014a043,0xf4001508,0x10fd0003,
13580x44043f46,0x004c8147,0xd0003330,0x51f40014,
13590x04257908,0x0c14093e,0x44020802,0x4f900080,
13600x4095e460,0x20c02479,0x20084a08,0x3e400310,
13610x820f9000,0xa44083e4,0x6020c824,0x79000a33,
13620x091e4003,0x3c007fff,0x800f001f,0xffe00000,
136300000000,00000000,00000000,00000000,
13640x10400000,00000000,0x10000000,00000000,
13650xffffffff,0xffffffff,0xffffffff,0xffffffff,
13660xfffffc00,00000000,0xffffffff,0xffffffff,
13670xffffffff,0xffffffff,0xfffffc00,00000000,
13680xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
13690xfdffffff,0xffffffff,0xfe000000,00000000,
13700xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
13710xfdffffff,0xffffffff,0xfe000000,00000000,
13720xffffffff,0xfffff9ff,0xfe000000,00000000,
13730xffffffff,0xfffff9ff,0xfe000000,00000000,
13740x00030000,00000000,0xffffffff,0xffffffff,
13750xffffffff,0xffffffff,0xffffffff,0xffffffff,
13760xffffffff,0xffffffff,0xffffffff,0xffffffff,
13770xffffffff,0xffffffff,0xffffffff,0xffffffff,
13780xffffffff,0xffffffff },
1379
1380/* rare_inst
1381 *
1382 * ctr0: counts sync and syncdma instructions
1383 * ctr1: counts pxtlbx,x instructions
1384 * ctr2: counts ixtlbt instructions
1385 * ctr3: counts cycles
1386 */
1387{
13880x0c01e000,00000000,0x00060000,00000000,
13890xe0e0e0e0,0x004e000c,0x000843fc,0x85c09380,
13900x0121ebfd,0xff217124,0xe0004000,0x943fc85f,
13910xffffffff,0xffffffff,0xff000000,00000000,
13920xffffffff,0xffffffff,0xffffffff,0xffffffff,
13930xffffffff,00000000,0xffffffff,0xffffffff,
13940xffffffff,0xffffffff,0xffffffff,0xffffffff,
13950xffffffff,0xffffffff,0xffffffff,0xffffffff,
13960xffff0000,00000000,0xffffffff,0xffffffff,
13970xffffffff,0xffffffff,0xffffffff,0xf0000000,
13980xe00000e0,0x00003c00,0x007f0001,0x01001fc0,
13990x00408007,0xf0003030,0x01fc000c,0x10007f00,
14000x0505001f,0xc0014180,0x07f00070,0x7001fc00,
14010x1c20007f,0x00090900,0x1fc00242,0x8007f000,
14020xb0b001fc,0x002c3000,0x7f000d0d,0x001fc003,
14030x438007f0,0x00f0f001,0xfc003fff,0xfffff800,
14040xfffffffe,0x003fffff,0xff800fff,0xffffe003,
14050xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
14060xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
14070xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
14080xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
140900000000,00000000,00000000,00000000,
14100xffff0000,00000000,0xf0000000,00000000,
14110xffffffff,0xffffffff,0xffffffff,0xffffffff,
14120xfffffc00,00000000,0xffffffff,0xffffffff,
14130xffffffff,0xffffffff,0xfffffc00,00000000,
14140xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
14150xfdffffff,0xffffffff,0xfe000000,00000000,
14160xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
14170xfdffffff,0xffffffff,0xfe000000,00000000,
14180xffffffff,0xfffff9ff,0xfe000000,00000000,
14190xffffffff,0xfffff9ff,0xfe000000,00000000,
14200x00030000,00000000,0xffffffff,0xffffffff,
14210xffffffff,0xffffffff,0xffffffff,0xffffffff,
14220xffffffff,0xffffffff,0xffffffff,0xffffffff,
14230xffffffff,0xffffffff,0xffffffff,0xffffffff,
14240xffffffff,0xffffffff },
1425
1426/* rw_dfet (for D-cache misses and writebacks)
1427 *
1428 * ctr0: counts address valid cycles
1429 * ctr1: counts *all* data valid cycles
1430 * ctr2: is the overflow from counter 0
1431 * ctr3: is the overflow from counter 1
1432 */
1433{
14340x0c01e000,00000000,0x00060000,00000000,
14350xefefefef,0xffffffff,0xffffffff,0xffffffff,
14360xffffffff,0xffffffff,0xffffffff,0xffffffff,
14370xffffffff,0xffffffff,0xff000000,00000000,
14380xffffffff,0xffffffff,0xffffffff,0xffffffff,
14390xffffffff,00000000,0xffffffff,0xffffffff,
14400xffffffff,0xffffffff,0xffffffff,0xffffffff,
14410xffffffff,0xffffffff,0xffffffff,0xffffffff,
14420xffff0000,00000000,0xffffffff,0xffffffff,
14430xffffffff,0xffffffff,0xffffffff,0xf0000000,
14440x0000000c,0x00003c00,0x07930000,0x0041e4c0,
14450x01002079,0x3000800c,0x1e4c0030,0x00279300,
14460x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
14470x34004793,0x00020051,0xe4c00180,0x24793000,
14480xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
14490xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
14500xffffffff,0xffffffff,0xffffffff,0xffffffff,
14510xffffffff,0xffffffff,0xffffffff,0xffffffff,
14520xffffffff,0xffffffff,0xffffffff,0xffffffff,
14530xffffffff,0xffffffff,0xffffffff,0xffffffff,
14540xffffffff,0xffffffff,0xffffffff,0xfffffc00,
145500000000,00000000,00000000,00000000,
14560xffff0000,00000000,0xf0000000,00000000,
14570xffffffff,0xffffffff,0xffffffff,0xffffffff,
14580xfffffc00,00000000,0xffffffff,0xffffffff,
14590xffffffff,0xffffffff,0xfffffc00,00000000,
14600xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
14610xfdffffff,0xffffffff,0xfe000000,00000000,
14620xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
14630xfdffffff,0xffffffff,0xfe000000,00000000,
14640xffffffff,0xfffff9ff,0xfe000000,00000000,
14650xffffffff,0xfffff9ff,0xfe000000,00000000,
14660x00100000,00000000,0xf0000000,00000000,
146700000000,00000000,0x98000000,00000000,
14680xffffffff,0xffffffff,0x0fffffff,0xffffffff,
146900000000,00000000,0x00ffffff,0xffffffff,
14700xffffffff,0xffffffff },
1471
1472/* rw_ifet (I-cache misses -- actually dumb READ transactions)
1473 *
1474 * ctr0: counts address valid cycles
1475 * ctr1: counts *all* data valid cycles
1476 * ctr2: is the overflow from counter 0
1477 * ctr3: is the overflow from counter 1
1478 */
1479{
14800x0c01e000,00000000,0x00060000,00000000,
14810xefefefef,0xffffffff,0xffffffff,0xffffffff,
14820xffffffff,0xffffffff,0xffffffff,0xffffffff,
14830xffffffff,0xffffffff,0xff000000,00000000,
14840xffffffff,0xffffffff,0xffffffff,0xffffffff,
14850xffffffff,00000000,0xffffffff,0xffffffff,
14860xffffffff,0xffffffff,0xffffffff,0xffffffff,
14870xffffffff,0xffffffff,0xffffffff,0xffffffff,
14880xffff0000,00000000,0xffffffff,0xffffffff,
14890xffffffff,0xffffffff,0xffffffff,0xf0000000,
14900x0000000c,0x00003c00,0x07930000,0x0041e4c0,
14910x01002079,0x3000800c,0x1e4c0030,0x00279300,
14920x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
14930x34004793,0x00020051,0xe4c00180,0x24793000,
14940xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
14950xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
14960xffffffff,0xffffffff,0xffffffff,0xffffffff,
14970xffffffff,0xffffffff,0xffffffff,0xffffffff,
14980xffffffff,0xffffffff,0xffffffff,0xffffffff,
14990xffffffff,0xffffffff,0xffffffff,0xffffffff,
15000xffffffff,0xffffffff,0xffffffff,0xfffffc00,
150100000000,00000000,00000000,00000000,
15020xffff0000,00000000,0xf0000000,00000000,
15030xffffffff,0xffffffff,0xffffffff,0xffffffff,
15040xfffffc00,00000000,0xffffffff,0xffffffff,
15050xffffffff,0xffffffff,0xfffffc00,00000000,
15060xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
15070xfdffffff,0xffffffff,0xfe000000,00000000,
15080xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
15090xfdffffff,0xffffffff,0xfe000000,00000000,
15100xffffffff,0xfffff9ff,0xfe000000,00000000,
15110xffffffff,0xfffff9ff,0xfe000000,00000000,
15120x00100000,00000000,0xd0000000,00000000,
15130xffffffff,0xffffffff,0xffffffff,0xffffffff,
15140xffffffff,0xffffffff,0x00ffffff,0xffffffff,
15150xffffffff,0xffffffff,00000000,00000000,
15160xffffffff,0xffffffff },
1517
1518
1519/* rw_sdfet (READ_SHARED_OR_PRIVATE transactions)
1520 *
1521 * ctr0: counts address valid cycles
1522 * ctr1: counts *all* data valid cycles
1523 * ctr2: is the overflow from counter 0
1524 * ctr3: is the overflow from counter 1
1525 */
1526{
15270x0c01e000,00000000,0x00060000,00000000,
15280xefefefef,0xffffffff,0xffffffff,0xffffffff,
15290xffffffff,0xffffffff,0xffffffff,0xffffffff,
15300xffffffff,0xffffffff,0xff000000,00000000,
15310xffffffff,0xffffffff,0xffffffff,0xffffffff,
15320xffffffff,00000000,0xffffffff,0xffffffff,
15330xffffffff,0xffffffff,0xffffffff,0xffffffff,
15340xffffffff,0xffffffff,0xffffffff,0xffffffff,
15350xffff0000,00000000,0xffffffff,0xffffffff,
15360xffffffff,0xffffffff,0xffffffff,0xf0000000,
15370x0000000c,0x00003c00,0x07930000,0x0041e4c0,
15380x01002079,0x3000800c,0x1e4c0030,0x00279300,
15390x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
15400x34004793,0x00020051,0xe4c00180,0x24793000,
15410xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
15420xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
15430xffffffff,0xffffffff,0xffffffff,0xffffffff,
15440xffffffff,0xffffffff,0xffffffff,0xffffffff,
15450xffffffff,0xffffffff,0xffffffff,0xffffffff,
15460xffffffff,0xffffffff,0xffffffff,0xffffffff,
15470xffffffff,0xffffffff,0xffffffff,0xfffffc00,
154800000000,00000000,00000000,00000000,
15490xffff0000,00000000,0xf0000000,00000000,
15500xffffffff,0xffffffff,0xffffffff,0xffffffff,
15510xfffffc00,00000000,0xffffffff,0xffffffff,
15520xffffffff,0xffffffff,0xfffffc00,00000000,
15530xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
15540xfdffffff,0xffffffff,0xfe000000,00000000,
15550xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
15560xfdffffff,0xffffffff,0xfe000000,00000000,
15570xffffffff,0xfffff9ff,0xfe000000,00000000,
15580xffffffff,0xfffff9ff,0xfe000000,00000000,
15590x00100000,00000000,0xf4000000,00000000,
156000000000,00000000,00000000,00000000,
15610xffffffff,0xffffffff,0x00ffffff,0xffffffff,
156200000000,00000000,00000000,00000000,
15630xffffffff,0xffffffff },
1564
1565
1566/* spec_ifet
1567 *
1568 * ICORE_AV fires for every request which the Instruction Fetch Unit sends
1569 * to the Runway Interface Block. Hence, this counts all I-misses, speculative
1570 * or not, but does *not* include I-cache prefetches, which are generated by
1571 * RIB.
1572 * IRTN_AV fires twice for every I-cache miss returning from RIB to the IFU.
1573 * It will not fire if a second I-cache miss is issued from the IFU to RIB
1574 * before the first returns. Therefore, if the IRTN_AV count is much less
1575 * than 2x the ICORE_AV count, many speculative I-cache misses are occurring
1576 * which are "discovered" to be incorrect fairly quickly.
1577 * The ratio of I-cache miss transactions on Runway to the ICORE_AV count is
1578 * a measure of the effectiveness of instruction prefetching. This ratio
1579 * should be between 1 and 2. If it is close to 1, most prefetches are
1580 * eventually called for by the IFU; if it is close to 2, almost no prefetches
1581 * are useful and they are wasted bus traffic.
1582 *
1583 * ctr0: counts ICORE_AV
1584 * ctr1: counts IRTN_AV
1585 * ctr2: counts all non-coherent READ transactions on Runway. (TTYPE D0)
1586 * This should be just I-cache miss and I-prefetch transactions.
1587 * ctr3: counts total processor cycles
1588 */
1589{
15900x0c000000,00000000,0x00060000,00000000,
15910xefefefef,0xffffffff,0xffffffff,0xffffffff,
15920xffffffff,0xffffffff,0xffffffff,0xffffffff,
15930xffffffff,0xffffffff,0xff000000,00000000,
15940xffffffff,0xffffffff,0xffffffff,0xffffffff,
15950xffffffff,00000000,0xffffffff,0xffffffff,
15960xffffffff,0xffffffff,0xffffffff,0xffffffff,
15970xffffffff,0xffffffff,0xffffffff,0xffffffff,
15980xffff0000,00000000,0x0fffffff,0xffffffff,
15990xffffffff,0xffffffff,0xffffffff,0xf0000000,
16000x00000008,0x00030c00,0x01bf0001,0x00806fc0,
16010x00c1001b,0xf0005048,0x06fc001c,0x2001bf00,
16020x0908806f,0xc002c300,0x1bf000d0,0xc806fc00,
16030x3fffffff,0xffffffff,0xffffffff,0xffffffff,
16040xffffffff,0xffffffff,0xffffffff,0xffffffff,
16050xffffffff,0xffffffff,0xffffffff,0xffffffff,
16060xffffffff,0xffffffff,0xffffffff,0xffffffff,
16070xffffffff,0xffffffff,0xffffffff,0xffffffff,
16080xffffffff,0xffffffff,0xffffffff,0xffffffff,
16090xffffffff,0xffffffff,0xffffffff,0xffffffff,
16100xffffffff,0xffffffff,0xffffffff,0xfffffc00,
161100000000,00000000,00000000,00000000,
16120x06bf0000,00000000,00000000,00000000,
16130xffffffff,0xffffffff,0xffffffff,0xffffffff,
16140xfffffc00,00000000,0xffffffff,0xffffffff,
16150xffffffff,0xffffffff,0xfffffc00,00000000,
16160xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
16170xfdffffff,0xffffffff,0xfe000000,00000000,
16180xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
16190xfdffffff,0xffffffff,0xfe000000,00000000,
16200xffffffff,0xfffff9ff,0xfe000000,00000000,
16210xffffffff,0xfffff9ff,0xfe000000,00000000,
16220x00110000,00000000,0xd0ffffff,0xffffffff,
16230xffffffff,0xffffffff,0xffffffff,0xffffffff,
16240xffffffff,0xffffffff,0x00ffffff,0xffffffff,
16250xffffffff,0xffffffff,00000000,00000000,
16260xffffffff,0xffffffff },
1627
1628/* st_cond0
1629 *
1630 * ctr0: is the overflow for ctr1
1631 * ctr1: counts major ops 0C and 0E (fp ops, not fmac or fmpyadd)
1632 * ctr2: counts B,L (including long and push) and GATE (including nullified),
1633 * predicted not-taken
1634 * ctr3: is the overflow for ctr2
1635 */
1636{
16370x4c01e000,00000000,0x00060000,00000000,
16380xe0e0c0e0,0xffffffff,0xffffffff,0xffc13380,
16390x0101ffff,0xffa1f057,0xe000407f,0xdfffc87f,
16400xffffffff,0xffffffff,0xff000000,00000000,
16410xffffffff,0xffffffff,0xffffffff,0xffffffff,
16420xffffffff,00000000,0xffffffff,0xffffffff,
16430xffffffff,0xffffffff,0xffffffff,0xffffffff,
16440xffffffff,0xffffffff,0xffffffff,0xffffffff,
16450xffff0000,00000000,0xffffffff,0xffffffff,
16460xffffffff,0xffffffff,0xffffffff,0xf0000000,
16470xf0000060,0x00003c00,0x04f90000,0x02013e40,
16480x0081004f,0x90004060,0x13e40018,0x0024f900,
16490x0802093e,0x40028102,0x4f9000c0,0x6093e400,
16500x380014f9,0x00010205,0x3e4000c1,0x014f9000,
16510x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
16520xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
16530xffffffff,0xffffffff,0xffffffff,0xffffffff,
16540xffffffff,0xffffffff,0xffffffff,0xffffffff,
16550xffffffff,0xffffffff,0xffffffff,0xffffffff,
16560xffffffff,0xffffffff,0xffffffff,0xffffffff,
16570xffffffff,0xffffffff,0xffffffff,0xfffffc00,
165800000000,00000000,00000000,00000000,
16590xffff0000,00000000,0xf0000000,00000000,
16600xffffffff,0xffffffff,0xffffffff,0xffffffff,
16610xfffffc00,00000000,0xffffffff,0xffffffff,
16620xffffffff,0xffffffff,0xfffffc00,00000000,
16630xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
16640xfdffffff,0xffffffff,0xfe000000,00000000,
16650xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
16660xfdffffff,0xffffffff,0xfe000000,00000000,
16670xffffffff,0xfffff9ff,0xfe000000,00000000,
16680xffffffff,0xfffff9ff,0xfe000000,00000000,
16690x00030000,00000000,0xffffffff,0xffffffff,
16700xffffffff,0xffffffff,0xffffffff,0xffffffff,
16710xffffffff,0xffffffff,0xffffffff,0xffffffff,
16720xffffffff,0xffffffff,0xffffffff,0xffffffff,
16730xffffffff,0xffffffff },
1674
1675/* st_cond1
1676 *
1677 * ctr0: is the overflow for ctr1
1678 * ctr1: counts major ops 1x (most of the load/stores)
1679 * ctr2: counts CMPB (dw) predicted not-taken
1680 * ctr3: is the overflow for ctr2
1681 */
1682{
16830x4c01e000,00000000,0x00060000,00000000,
16840xe0e0c0e0,0xffffffff,0xffffffff,0xffc01b80,
16850x0101ffff,0xffb7f03d,0xe000407f,0xffffc8ff,
16860xffffffff,0xffffffff,0xff000000,00000000,
16870xffffffff,0xffffffff,0xffffffff,0xffffffff,
16880xffffffff,00000000,0xffffffff,0xffffffff,
16890xffffffff,0xffffffff,0xffffffff,0xffffffff,
16900xffffffff,0xffffffff,0xffffffff,0xffffffff,
16910xffff0000,00000000,0xffffffff,0xffffffff,
16920xffffffff,0xffffffff,0xffffffff,0xf0000000,
16930xf0000060,0x00003c00,0x04f90000,0x02013e40,
16940x0081004f,0x90004060,0x13e40018,0x0024f900,
16950x0802093e,0x40028102,0x4f9000c0,0x6093e400,
16960x380014f9,0x00010205,0x3e4000c1,0x014f9000,
16970x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
16980xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
16990xffffffff,0xffffffff,0xffffffff,0xffffffff,
17000xffffffff,0xffffffff,0xffffffff,0xffffffff,
17010xffffffff,0xffffffff,0xffffffff,0xffffffff,
17020xffffffff,0xffffffff,0xffffffff,0xffffffff,
17030xffffffff,0xffffffff,0xffffffff,0xfffffc00,
170400000000,00000000,00000000,00000000,
17050xffff0000,00000000,0xf0000000,00000000,
17060xffffffff,0xffffffff,0xffffffff,0xffffffff,
17070xfffffc00,00000000,0xffffffff,0xffffffff,
17080xffffffff,0xffffffff,0xfffffc00,00000000,
17090xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
17100xfdffffff,0xffffffff,0xfe000000,00000000,
17110xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
17120xfdffffff,0xffffffff,0xfe000000,00000000,
17130xffffffff,0xfffff9ff,0xfe000000,00000000,
17140xffffffff,0xfffff9ff,0xfe000000,00000000,
17150x00030000,00000000,0xffffffff,0xffffffff,
17160xffffffff,0xffffffff,0xffffffff,0xffffffff,
17170xffffffff,0xffffffff,0xffffffff,0xffffffff,
17180xffffffff,0xffffffff,0xffffffff,0xffffffff,
17190xffffffff,0xffffffff },
1720
1721/* st_cond2
1722 *
1723 * ctr0: is the overflow for ctr1
1724 * ctr1: counts major op 03
1725 * ctr2: counts CMPIB (dw) predicted not taken.
1726 * ctr3: is the overflow for ctr2
1727 */
1728{
17290x4c01e000,00000000,0x00060000,00000000,
17300xe0e0c0e0,0xffffffff,0xffffffff,0xffc09780,
17310x0101ffff,0xff21f077,0xe000407f,0xffffc87f,
17320xffffffff,0xffffffff,0xff000000,00000000,
17330xffffffff,0xffffffff,0xffffffff,0xffffffff,
17340xffffffff,00000000,0xffffffff,0xffffffff,
17350xffffffff,0xffffffff,0xffffffff,0xffffffff,
17360xffffffff,0xffffffff,0xffffffff,0xffffffff,
17370xffff0000,00000000,0xffffffff,0xffffffff,
17380xffffffff,0xffffffff,0xffffffff,0xf0000000,
17390xf0000060,0x00003c00,0x04f90000,0x02013e40,
17400x0081004f,0x90004060,0x13e40018,0x0024f900,
17410x0802093e,0x40028102,0x4f9000c0,0x6093e400,
17420x380014f9,0x00010205,0x3e4000c1,0x014f9000,
17430x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
17440xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
17450xffffffff,0xffffffff,0xffffffff,0xffffffff,
17460xffffffff,0xffffffff,0xffffffff,0xffffffff,
17470xffffffff,0xffffffff,0xffffffff,0xffffffff,
17480xffffffff,0xffffffff,0xffffffff,0xffffffff,
17490xffffffff,0xffffffff,0xffffffff,0xfffffc00,
175000000000,00000000,00000000,00000000,
17510xffff0000,00000000,0xf0000000,00000000,
17520xffffffff,0xffffffff,0xffffffff,0xffffffff,
17530xfffffc00,00000000,0xffffffff,0xffffffff,
17540xffffffff,0xffffffff,0xfffffc00,00000000,
17550xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
17560xfdffffff,0xffffffff,0xfe000000,00000000,
17570xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
17580xfdffffff,0xffffffff,0xfe000000,00000000,
17590xffffffff,0xfffff9ff,0xfe000000,00000000,
17600xffffffff,0xfffff9ff,0xfe000000,00000000,
17610x00030000,00000000,0xffffffff,0xffffffff,
17620xffffffff,0xffffffff,0xffffffff,0xffffffff,
17630xffffffff,0xffffffff,0xffffffff,0xffffffff,
17640xffffffff,0xffffffff,0xffffffff,0xffffffff,
17650xffffffff,0xffffffff },
1766
1767/* st_cond3
1768 *
1769 * ctr0: is the overflow for ctr1
1770 * ctr1: counts major ops 06 & 26
1771 * ctr2: counts BB, BVB, MOVB, MOVIB (incl. nullified) predicted not-taken
1772 * ctr3: is the overflow for ctr2
1773 */
1774{
17750x4c01e000,00000000,0x00060000,00000000,
17760xe0e0c0e0,0xffffffff,0xffffffff,0xffc03780,
17770x0101ffff,0xff29f016,0xe000407f,0xffffe97f,
17780xffffffff,0xffffffff,0xff000000,00000000,
17790xffffffff,0xffffffff,0xffffffff,0xffffffff,
17800xffffffff,00000000,0xffffffff,0xffffffff,
17810xffffffff,0xffffffff,0xffffffff,0xffffffff,
17820xffffffff,0xffffffff,0xffffffff,0xffffffff,
17830xffff0000,00000000,0xffffffff,0xffffffff,
17840xffffffff,0xffffffff,0xffffffff,0xf0000000,
17850xf0000060,0x00003c00,0x04f90000,0x02013e40,
17860x0081004f,0x90004060,0x13e40018,0x0024f900,
17870x0802093e,0x40028102,0x4f9000c0,0x6093e400,
17880x380014f9,0x00010205,0x3e4000c1,0x014f9000,
17890x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
17900xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
17910xffffffff,0xffffffff,0xffffffff,0xffffffff,
17920xffffffff,0xffffffff,0xffffffff,0xffffffff,
17930xffffffff,0xffffffff,0xffffffff,0xffffffff,
17940xffffffff,0xffffffff,0xffffffff,0xffffffff,
17950xffffffff,0xffffffff,0xffffffff,0xfffffc00,
179600000000,00000000,00000000,00000000,
17970xffff0000,00000000,0xf0000000,00000000,
17980xffffffff,0xffffffff,0xffffffff,0xffffffff,
17990xfffffc00,00000000,0xffffffff,0xffffffff,
18000xffffffff,0xffffffff,0xfffffc00,00000000,
18010xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
18020xfdffffff,0xffffffff,0xfe000000,00000000,
18030xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
18040xfdffffff,0xffffffff,0xfe000000,00000000,
18050xffffffff,0xfffff9ff,0xfe000000,00000000,
18060xffffffff,0xfffff9ff,0xfe000000,00000000,
18070x00030000,00000000,0xffffffff,0xffffffff,
18080xffffffff,0xffffffff,0xffffffff,0xffffffff,
18090xffffffff,0xffffffff,0xffffffff,0xffffffff,
18100xffffffff,0xffffffff,0xffffffff,0xffffffff,
18110xffffffff,0xffffffff },
1812
1813/* st_cond4
1814 *
1815 * ctr0: is the overflow for ctr1
1816 * ctr1: counts major op 2E
1817 * ctr2: counts CMPB, CMPIB, ADDB, ADDIB (incl. nullified) predicted not-taken
1818 * ctr3: is the overflow for ctr2
1819 */
1820{
18210x4c01e000,00000000,0x00060000,00000000,
18220xe0e0c0e0,0xffffffff,0xffffffff,0xffc17780,
18230x0101ffff,0xff21f014,0xe000407f,0xffffe9ff,
18240xffffffff,0xffffffff,0xff000000,00000000,
18250xffffffff,0xffffffff,0xffffffff,0xffffffff,
18260xffffffff,00000000,0xffffffff,0xffffffff,
18270xffffffff,0xffffffff,0xffffffff,0xffffffff,
18280xffffffff,0xffffffff,0xffffffff,0xffffffff,
18290xffff0000,00000000,0xffffffff,0xffffffff,
18300xffffffff,0xffffffff,0xffffffff,0xf0000000,
18310xf0000060,0x00003c00,0x04f90000,0x02013e40,
18320x0081004f,0x90004060,0x13e40018,0x0024f900,
18330x0802093e,0x40028102,0x4f9000c0,0x6093e400,
18340x380014f9,0x00010205,0x3e4000c1,0x014f9000,
18350x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
18360xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
18370xffffffff,0xffffffff,0xffffffff,0xffffffff,
18380xffffffff,0xffffffff,0xffffffff,0xffffffff,
18390xffffffff,0xffffffff,0xffffffff,0xffffffff,
18400xffffffff,0xffffffff,0xffffffff,0xffffffff,
18410xffffffff,0xffffffff,0xffffffff,0xfffffc00,
184200000000,00000000,00000000,00000000,
18430xffff0000,00000000,0xf0000000,00000000,
18440xffffffff,0xffffffff,0xffffffff,0xffffffff,
18450xfffffc00,00000000,0xffffffff,0xffffffff,
18460xffffffff,0xffffffff,0xfffffc00,00000000,
18470xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
18480xfdffffff,0xffffffff,0xfe000000,00000000,
18490xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
18500xfdffffff,0xffffffff,0xfe000000,00000000,
18510xffffffff,0xfffff9ff,0xfe000000,00000000,
18520xffffffff,0xfffff9ff,0xfe000000,00000000,
18530x00030000,00000000,0xffffffff,0xffffffff,
18540xffffffff,0xffffffff,0xffffffff,0xffffffff,
18550xffffffff,0xffffffff,0xffffffff,0xffffffff,
18560xffffffff,0xffffffff,0xffffffff,0xffffffff,
18570xffffffff,0xffffffff },
1858
1859/* st_unpred0
1860 *
1861 * ctr0: is the overflow for ctr1
1862 * ctr1: counts BE and BE,L
1863 * ctr2: counts BE and BE,L including nullified
1864 * ctr3: is the overflow for ctr2
1865 */
1866{
18670x4c01e000,00000000,0x00060000,00000000,
18680xe0c0c0e0,0xffffffff,0xffffffff,0xffdf5bbf,
18690xffffffff,0xff25f7d6,0xefffffff,0xffffc97f,
18700xffffffff,0xffffffff,0xff000000,00000000,
18710xffffffff,0xffffffff,0xffffffff,0xffffffff,
18720xffffffff,00000000,0xffffffff,0xffffffff,
18730xffffffff,0xffffffff,0xffffffff,0xffffffff,
18740xffffffff,0xffffffff,0xffffffff,0xffffffff,
18750xffff0000,00000000,0xffffffff,0xffffffff,
18760xffffffff,0xffffffff,0xffffffff,0xf0000000,
18770xf0000060,0x00003c00,0x04f90000,0x02013e40,
18780x0081004f,0x90004060,0x13e40018,0x0024f900,
18790x0802093e,0x40028102,0x4f9000c0,0x6093e400,
18800x380014f9,0x00010205,0x3e4000c1,0x014f9000,
18810x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
18820xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
18830xffffffff,0xffffffff,0xffffffff,0xffffffff,
18840xffffffff,0xffffffff,0xffffffff,0xffffffff,
18850xffffffff,0xffffffff,0xffffffff,0xffffffff,
18860xffffffff,0xffffffff,0xffffffff,0xffffffff,
18870xffffffff,0xffffffff,0xffffffff,0xfffffc00,
188800000000,00000000,00000000,00000000,
18890xffff0000,00000000,0xf0000000,00000000,
18900xffffffff,0xffffffff,0xffffffff,0xffffffff,
18910xfffffc00,00000000,0xffffffff,0xffffffff,
18920xffffffff,0xffffffff,0xfffffc00,00000000,
18930xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
18940xfdffffff,0xffffffff,0xfe000000,00000000,
18950xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
18960xfdffffff,0xffffffff,0xfe000000,00000000,
18970xffffffff,0xfffff9ff,0xfe000000,00000000,
18980xffffffff,0xfffff9ff,0xfe000000,00000000,
18990x00030000,00000000,0xffffffff,0xffffffff,
19000xffffffff,0xffffffff,0xffffffff,0xffffffff,
19010xffffffff,0xffffffff,0xffffffff,0xffffffff,
19020xffffffff,0xffffffff,0xffffffff,0xffffffff,
19030xffffffff,0xffffffff },
1904
1905/* st_unpred1
1906 *
1907 * ctr0: is the overflow for ctr1
1908 * ctr1: counts BLR, BV, BVE, BVE,L
1909 * ctr2: counts BLR, BV, BVE, BVE,L including nullified
1910 * ctr3: is the overflow for ctr2
1911 */
1912{
19130x4c01e000,00000000,0x00060000,00000000,
19140xe0c0c0e0,0xffffffff,0xffffffff,0xffc15f80,
19150x0501ff7f,0xff21f057,0xe001407f,0xdfffc87f,
19160xffffffff,0xffffffff,0xff000000,00000000,
19170xffffffff,0xffffffff,0xffffffff,0xffffffff,
19180xffffffff,00000000,0xffffffff,0xffffffff,
19190xffffffff,0xffffffff,0xffffffff,0xffffffff,
19200xffffffff,0xffffffff,0xffffffff,0xffffffff,
19210xffff0000,00000000,0xffffffff,0xffffffff,
19220xffffffff,0xffffffff,0xffffffff,0xf0000000,
19230xf0000060,0x00003c00,0x04f90000,0x02013e40,
19240x0081004f,0x90004060,0x13e40018,0x0024f900,
19250x0802093e,0x40028102,0x4f9000c0,0x6093e400,
19260x380014f9,0x00010205,0x3e4000c1,0x014f9000,
19270x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
19280xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
19290xffffffff,0xffffffff,0xffffffff,0xffffffff,
19300xffffffff,0xffffffff,0xffffffff,0xffffffff,
19310xffffffff,0xffffffff,0xffffffff,0xffffffff,
19320xffffffff,0xffffffff,0xffffffff,0xffffffff,
19330xffffffff,0xffffffff,0xffffffff,0xfffffc00,
193400000000,00000000,00000000,00000000,
19350xffff0000,00000000,0xf0000000,00000000,
19360xffffffff,0xffffffff,0xffffffff,0xffffffff,
19370xfffffc00,00000000,0xffffffff,0xffffffff,
19380xffffffff,0xffffffff,0xfffffc00,00000000,
19390xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
19400xfdffffff,0xffffffff,0xfe000000,00000000,
19410xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
19420xfdffffff,0xffffffff,0xfe000000,00000000,
19430xffffffff,0xfffff9ff,0xfe000000,00000000,
19440xffffffff,0xfffff9ff,0xfe000000,00000000,
19450x00030000,00000000,0xffffffff,0xffffffff,
19460xffffffff,0xffffffff,0xffffffff,0xffffffff,
19470xffffffff,0xffffffff,0xffffffff,0xffffffff,
19480xffffffff,0xffffffff,0xffffffff,0xffffffff,
19490xffffffff,0xffffffff },
1950
1951/* unpred
1952 *
1953 * ctr0: counts non-nullified unpredictable branches
1954 * ctr1: is the overflow for ctr0
1955 * ctr2: counts all unpredictable branches (nullified or not)
1956 * ctr3: is the overflow for ctr2
1957 */
1958{
19590xcc01e000,00000000,0x00060000,00000000,
19600x20202020,0xff31ffff,0xfff7fffe,0x97ffcc7f,
19610xfffffdff,0xffa5fff3,0x1fffffff,0x7fffe97f,
19620xffffffff,0xffffffff,0xff000000,00000000,
19630xffffffff,0xffffffff,0xffffffff,0xffffffff,
19640xffffffff,00000000,0xffffffff,0xffffffff,
19650xffffffff,0xffffffff,0xffffffff,0xffffffff,
19660xffffffff,0xffffffff,0xffffffff,0xffffffff,
19670xffff0000,00000000,0xffffffff,0xffffffff,
19680xffffffff,0xffffffff,0xffffffff,0xf0000000,
19690xf00000a0,0x00003c00,0x02f50000,0x0004bd40,
19700x0040802f,0x50002020,0x4bd4000c,0x0042f500,
19710x040014bd,0x40014084,0x2f500060,0x214bd400,
19720x1c2002f5,0x00080804,0xbd400242,0x802f5000,
19730xa0a04bd4,0x002c2042,0xf5000c08,0x14bd4003,
19740x42842f50,0x00e0a14b,0xd4003fff,0xffffffff,
19750xffffffff,0xffffffff,0xffffffff,0xffffffff,
19760xffffffff,0xffffffff,0xffffffff,0xffffffff,
19770xffffffff,0xffffffff,0xffffffff,0xffffffff,
19780xffffffff,0xffffffff,0xffffffff,0xffffffff,
19790xffffffff,0xffffffff,0xffffffff,0xfffffc00,
198000000000,00000000,00000000,00000000,
19810xffff0000,00000000,0xf0000000,00000000,
19820xffffffff,0xffffffff,0xffffffff,0xffffffff,
19830xfffffc00,00000000,0xffffffff,0xffffffff,
19840xffffffff,0xffffffff,0xfffffc00,00000000,
19850xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
19860xfdffffff,0xffffffff,0xfe000000,00000000,
19870xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
19880xfdffffff,0xffffffff,0xfe000000,00000000,
19890xffffffff,0xfffff9ff,0xfe000000,00000000,
19900xffffffff,0xfffff9ff,0xfe000000,00000000,
19910x00030000,00000000,0xffffffff,0xffffffff,
19920xffffffff,0xffffffff,0xffffffff,0xffffffff,
19930xffffffff,0xffffffff,0xffffffff,0xffffffff,
19940xffffffff,0xffffffff,0xffffffff,0xffffffff,
19950xffffffff,0xffffffff },
1996
1997
1998/* go_store
1999 *
2000 * ctr0: Overflow for counter 2
2001 * ctr1: Overflow for counter 3
2002 * ctr2: count of GO_STORE_E signal
2003 * ctr3: count of GO_STORE_O signal
2004 */
2005
2006 {
2007 0x0c00e000, 0x00000000, 0x00060000, 0x00000000,
2008 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff,
2009 0xffffffff, 0xffa5ffff, 0xffffffff, 0xffffffff,
2010 0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
2011 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2012 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
2013 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2014 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2015 0xffff0000, 0x00000000, 0x7fffffff, 0xffffffff,
2016 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
2017 0x00000000, 0x0000c000, 0x067c0000, 0x01019f00,
2018 0x00408067, 0xc0002030, 0x19f0000c, 0x000e7c00,
2019 0x0401039f, 0x00014080, 0xe7c00060, 0x3039f000,
2020 0x1c00167c, 0x00080105, 0x9f000240, 0x8167c000,
2021 0xa03059f0, 0x002c001e, 0x7c000c01, 0x079f0003,
2022 0x4081e7c0, 0x00e03079, 0xf0003fc0, 0x07fff800,
2023 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003,
2024 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f,
2025 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c,
2026 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0,
2027 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000,
2028 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2029 0x70130000, 0x00000000, 0x70000000, 0x00000000,
2030 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2031 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
2032 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
2033 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
2034 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
2035 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
2036 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
2037 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
2038 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
2039 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
2040 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2041 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2042 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2043 0xffffffff, 0xffffffff
2044 },
2045
2046
2047/* shlib_call
2048 *
2049 * ctr0: SharedLib call Depth1
2050 * ctr1: SharedLib call Depth2
2051 * ctr2: SharedLib call Depth3
2052 * ctr3: SharedLib call Depth>3
2053 */
2054 {
2055 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
2056 0xe0e0e0e0, 0xc76fa005, 0x07dd7e9c, 0x87115b80,
2057 0x01100200, 0x07200004, 0xe000407f, 0xfffffffc,
2058 0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
2059 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2060 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
2061 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2062 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2063 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
2064 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
2065 0xf0000000, 0x00003c20, 0x01ff0808, 0x04007fc0,
2066 0x0003001f, 0xf0000180, 0x07fc4010, 0x5001ff00,
2067 0x001c007f, 0xc2000a00, 0x1ff18022, 0x4007fc20,
2068 0x00b001ff, 0x10003800, 0x7fc8004d, 0x001ff100,
2069 0x03c007fc, 0x60012001, 0xff280144, 0x007fc600,
2070 0x13001ff2, 0x00058007, 0xfcc00550, 0x01ff2000,
2071 0x5c007fca, 0x001a001f, 0xf3801640, 0x07fca001,
2072 0xb001ff30, 0x0078007f, 0xd0005d00, 0x1ff30007,
2073 0xc007fce0, 0x022001ff, 0x48018400, 0x7fce0023,
2074 0x001ff400, 0x098007fd, 0x20065001, 0xff40009c,
2075 0x007fd200, 0x3fffffff, 0x800fffff, 0xffe00000,
2076 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2077 0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
2078 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2079 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
2080 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
2081 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
2082 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
2083 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
2084 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
2085 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
2086 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
2087 0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
2088 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2089 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2090 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2091 0xffffffff, 0xffffffff
2092 }
2093};
2094#define PCXW_IMAGE_SIZE 576
2095
2096static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] = {
2097/*
2098 * CPI: FROM CPI.IDF (Image 0)
2099 *
2100 * Counts the following:
2101 *
2102 * ctr0 : total cycles
2103 * ctr1 : total cycles where nothing retired
2104 * ctr2 : total instructions retired, including nullified
2105 * ctr3 : total instructions retired, less nullified instructions
2106 */
2107 {
2108 0x4c00c000, 0x00000000, 0x00060000, 0x00000000,
2109 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
2110 0xffffc000, 0x07ffff00, 0x07ffffff, 0x6007ffff,
2111 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000,
2112 0x60f00000, 0x0fffff00, 0x000fffff, 0x00000fff,
2113 0xff00000f, 0xffff0000, 0x00000000, 0x00ffffff,
2114 0xfffff000, 0x0000000f, 0xffffffff, 0xff000000,
2115 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
2116 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2117 0x00000000, 0x00000000, 0x00270000, 0x00000055,
2118 0x0200000e, 0x4d300000, 0x00000000, 0x0ff00002,
2119 0x70000000, 0x00000020, 0x0000e400, 0x00000ff0,
2120 0x00000000, 0x00000000, 0x00000055, 0xffffff00,
2121 0x00000000, 0x0000ff00, 0x00000000, 0x0f000000,
2122 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
2123 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
2124 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000,
2125 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
2126 0x00000000, 0x00000000, 0x00055fff, 0xfff00000,
2127 0x00000000, 0x0ff00000, 0x00000030, 0x00000000,
2128 0x00157fff, 0xffc00000, 0x034c0000, 0x00000000,
2129 0x03fc0000, 0x00000000, 0x6fff0000, 0x00000000,
2130 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2131 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2132 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2133 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
2134 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2135 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
2136 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2137 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2138 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2139 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2140 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2141 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2142 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2143 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2144 },
2145
2146/* Bus utilization image FROM BUS_UTIL.IDF (Image 1)
2147 *
2148 * ctr0 : counts address valid cycles
2149 * ctr1 : counts data valid cycles
2150 * ctr2 : counts overflow from counter 0
2151 * ctr3 : counts overflow from counter 1
2152 */
2153 {
2154 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
2155 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
2156 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2157 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2158 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2159 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2160 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2161 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2162 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2163 0x00000000, 0x00000000, 0x00001b00, 0xaa000000,
2164 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000,
2165 0x01b00000, 0x00000000, 0x00001037, 0x00000000,
2166 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000,
2167 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
2168 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
2169 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
2170 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff,
2171 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
2172 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
2173 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5,
2174 0x40000000, 0x00000000, 0x731c0000, 0x000156ab,
2175 0xfc000000, 0x00000000, 0xffff0000, 0x00000000,
2176 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2177 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2178 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2179 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2180 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2181 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2182 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2183 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2184 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2185 0xfe000000, 0x00000000, 0x00100000, 0x00000000,
2186 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2187 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2188 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2189 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2190 },
2191
2192/*
2193 * TLB counts: FROM TLBSTATS.IDF (Image 2)
2194 *
2195 * Counts the following:
2196 *
2197 * ctr0: DTLB misses
2198 * ctr1: ITLB misses
2199 * ctr2: total cycles in the miss handlers
2200 * ctr3: total cycles
2201 */
2202
2203 {
2204 0x0c00c000, 0x00000000, 0x00060000, 0x00000000,
2205 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
2206 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff,
2207 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000,
2208 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff,
2209 0xff00000f, 0xffff0000, 0x00000000, 0x00400000,
2210 0x00001000, 0x00000004, 0x00000000, 0x01000000,
2211 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
2212 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2213 0x00000000, 0x00000000, 0x00800000, 0x00153f7f,
2214 0x55000000, 0xaf800000, 0xc0000000, 0x0403f240,
2215 0x00000000, 0x00001010, 0x00004700, 0x00000ff0,
2216 0x00000000, 0x00000000, 0x00000055, 0xffffff00,
2217 0x00000000, 0x0000ff00, 0x00000000, 0x0f000000,
2218 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
2219 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
2220 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000,
2221 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
2222 0x00000000, 0x00000000, 0x00055fff, 0xfff00000,
2223 0x00000000, 0x0ff00000, 0x00000000, 0x00000000,
2224 0x00157fff, 0xffc00000, 0x00000000, 0x3fc00000,
2225 0x00040000, 0x00000000, 0x6fff0000, 0x00000000,
2226 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2227 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2228 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2229 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
2230 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2231 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
2232 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2233 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2234 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2235 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2236 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2237 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2238 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2239 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2240 },
2241
2242/* tlbhandler FROM tlbHandMiss.idf (Image 3)
2243 *
2244 * ctr0: TLB misses
2245 * ctr1: dmisses inside the TLB miss handler
2246 * ctr2: cycles in the TLB miss handler
2247 * ctr3: overflow of ctr2
2248 */
2249 {
2250 0x1c00c000, 0x00000000, 0x00060000, 0x00000000,
2251 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
2252 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff,
2253 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000,
2254 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff,
2255 0xff00000f, 0xffff0000, 0x00000000, 0x00400000,
2256 0x00001000, 0x00000004, 0x00000000, 0x01000000,
2257 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
2258 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2259 0x00000000, 0x00000000, 0x006c0000, 0x01000054,
2260 0x02000002, 0xc3200000, 0xc00aa000, 0x0c03f240,
2261 0x00000000, 0x00001010, 0x000044f4, 0x00000c00,
2262 0xaa0000f0, 0x0f0000b0, 0x00005005, 0x0f5f0000,
2263 0x0001f000, 0x0000ff00, 0x00000000, 0x0f000000,
2264 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
2265 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
2266 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000,
2267 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
2268 0x00000000, 0x00000000, 0x00055fff, 0xfff00000,
2269 0x00000000, 0x0ff00a00, 0x000f0000, 0x24004000,
2270 0x15400001, 0x40c00003, 0x3da00000, 0x0002a800,
2271 0x00ff0000, 0x00000000, 0x6fff0000, 0x00000000,
2272 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2273 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2274 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2275 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
2276 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2277 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
2278 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2279 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2280 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2281 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2282 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2283 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2284 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2285 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2286 },
2287
2288/* branch_taken image FROM PTKN.IDF (Image 4)
2289 *
2290 * ctr0: mispredicted branches
2291 * ctr1: predicted taken branches, actually taken
2292 * ctr2: predicted taken branches (includes nullfied)
2293 * ctr3: all branches
2294 */
2295
2296 {
2297 0xcc01e000, 0x00000000, 0x00000000, 0x00000000,
2298 0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff,
2299 0xffffffff, 0xfffffeff, 0xfffeffff, 0xffffffff,
2300 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2301 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2302 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2303 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2304 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2305 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2306 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
2307 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
2308 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
2309 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
2310 0x000dbfff, 0xffffff00, 0x00000000, 0x0f0fffff,
2311 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
2312 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
2313 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
2314 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
2315 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
2316 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
2317 0x00000000, 0x00000002, 0x67840000, 0x00000000,
2318 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
2319 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2320 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2321 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2322 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2323 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2324 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2325 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2326 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2327 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2328 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2329 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2330 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2331 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2332 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2333 },
2334
2335/* branch_nottaken FROM PNTKN.IDF (Image 5)
2336 *
2337 * ctr0: mispredicted branches
2338 * ctr1: branches predicted not-taken, but actually taken
2339 * ctr2: branches predicted not-taken (includes nullified)
2340 * ctr3: all branches
2341 */
2342 {
2343 0xcc01e000, 0x00000000, 0x00000000, 0x00000000,
2344 0xe0c0c0e0, 0xffffffff, 0xffffffff, 0xffefffff,
2345 0xffffbfff, 0xfffffeff, 0xfffeffff, 0xfffffeff,
2346 0xfffffffe, 0xffffffff, 0xffffff00, 0x00000000,
2347 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2348 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2349 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2350 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2351 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2352 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
2353 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
2354 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
2355 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
2356 0x000dbfff, 0xffffff00, 0x00000000, 0x0f0fffff,
2357 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
2358 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
2359 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
2360 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
2361 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
2362 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
2363 0x00000000, 0x00000002, 0x67840000, 0x00000000,
2364 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
2365 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2366 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2367 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2368 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2369 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2370 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2371 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2372 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2373 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2374 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2375 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2376 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2377 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2378 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2379 },
2380
2381/* IMISS image (Image 6)
2382 *
2383 * ctr0 : icache misses for retired instructions
2384 * ctr1 : total cycles
2385 * ctr2 : dcache misses for retired instructions
2386 * ctr3 : number of retired instructions
2387 */
2388 {
2389 0x2801e000, 0x00000000, 0x00010000, 0x00000000,
2390 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff,
2391 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff,
2392 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2393 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2394 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2395 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2396 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2397 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2398 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0,
2399 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800,
2400 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0,
2401 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555,
2402 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff,
2403 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
2404 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
2405 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
2406 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
2407 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
2408 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf,
2409 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000,
2410 0x03c14000, 0x00000000, 0xffff0000, 0x00000000,
2411 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2412 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
2413 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2414 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
2415 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2416 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
2417 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2418 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2419 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2420 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
2421 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2422 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2423 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2424 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2425 },
2426
2427/* DMISS image (Image 7)
2428 *
2429 * ctr0 : icache misses for retired instructions
2430 * ctr1 : total cycles
2431 * ctr2 : dcache misses for retired instructions
2432 * ctr3 : number of retired instructions
2433 */
2434 {
2435 0x2801e000, 0x00000000, 0x00010000, 0x00000000,
2436 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff,
2437 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff,
2438 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2439 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2440 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2441 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2442 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2443 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2444 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0,
2445 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800,
2446 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0,
2447 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555,
2448 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff,
2449 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
2450 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
2451 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
2452 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
2453 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
2454 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf,
2455 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000,
2456 0x03c14000, 0x00000000, 0xffff0000, 0x00000000,
2457 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2458 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
2459 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2460 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
2461 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2462 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
2463 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2464 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2465 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2466 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
2467 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2468 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2469 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2470 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2471 },
2472
2473/* dmiss_access image FROM DMISS_RATIO.IDF (Image 8)
2474 *
2475 * ctr0 : all loads and stores that retire (even lines)
2476 * ctr1 : all loads and stores that retire (odd lines)
2477 * ctr2 : dcache misses of retired loads/stores
2478 * ctr3 : all READ_PRIV and READ_SHAR_OR_PRIV on Runway
2479 * (Speculative and Non-Speculative)
2480 */
2481 {
2482 0x2d81e000, 0x00000000, 0x00000000, 0x00000000,
2483 0x10101010, 0x00ffffff, 0xa003ffff, 0xfe800fff,
2484 0xfffa003f, 0xffffe8ff, 0xffffffff, 0xffffffff,
2485 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2486 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2487 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2488 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2489 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2490 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2491 0x00000000, 0x00000000, 0xd2280a00, 0x00000000,
2492 0x0000000b, 0x46000000, 0x00000005, 0x555ff900,
2493 0x80200000, 0x00000000, 0x0000907e, 0x00000000,
2494 0x00005555, 0xff80bf8b, 0xab030303, 0x03030000,
2495 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
2496 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
2497 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
2498 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
2499 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
2500 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
2501 0xffff5555, 0x55500000, 0x15153fe0, 0x27628880,
2502 0x00000000, 0x00000002, 0x67840000, 0x00000001,
2503 0x5557fc00, 0x00000000, 0xffff0000, 0x00000000,
2504 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2505 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
2506 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2507 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
2508 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2509 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
2510 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2511 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2512 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2513 0xfe000000, 0x00000000, 0x00110000, 0x00000000,
2514 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2515 0xf8ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2516 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2517 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2518 },
2519
2520
2521/* big_cpi image (Image 9)
2522 *
2523 * ctr0 : Total number of CPU clock cycles.
2524 * ctr1 : Unused
2525 * ctr2 : Unused
2526 * ctr3 : Total number of Non-Nullified instructions retired.
2527 */
2528 {
2529 0x0c00c000, 0x00000000, 0x00060000, 0x00000000,
2530 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
2531 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff,
2532 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000,
2533 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff,
2534 0xff00000f, 0xffff0000, 0x00000000, 0x00400000,
2535 0x00001000, 0x00000004, 0x00000000, 0x01000000,
2536 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
2537 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2538 0x00000000, 0x00000000, 0x00550005, 0x00220000,
2539 0x0000000c, 0x71f00000, 0x00f00aa0, 0x0aaff000,
2540 0x00005002, 0x20000000, 0x0000c413, 0x00000c0f,
2541 0x00aa0000, 0xff00b600, 0x000500a0, 0x00000300,
2542 0x000cc3f0, 0x0000c0f0, 0x0aa0000f, 0xff000000,
2543 0x011000a0, 0x05503000, 0x00d03700, 0x00000f00,
2544 0xaa005500, 0x00000000, 0x000055ff, 0xffff0000,
2545 0x00000000, 0x00ff0000, 0x00000000, 0xf000aa00,
2546 0x11000a00, 0x55000000, 0x0d037000, 0x00c0f00a,
2547 0xa0055000, 0x0db00005, 0x5002a000, 0x00300000,
2548 0xf40f0000, 0x0c0f00aa, 0x0000ff10, 0x27400000,
2549 0x00008000, 0x00c00003, 0x037c0000, 0x003c02a8,
2550 0x02abfc00, 0x00000000, 0x6fff0000, 0x00000000,
2551 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2552 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2553 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2554 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
2555 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2556 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
2557 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2558 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2559 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2560 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2561 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2562 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2563 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2564 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2565 },
2566
2567/* big_ls image (Image 10)
2568 *
2569 * ctr0 : Total number of CPU clock cycles during which local_stall_A1 is asserted
2570 * ctr1 : Overflow of Counter 0
2571 * ctr2 : Total number of IFLUSH_AV
2572 * ctr3 : Overflow of Counter 2
2573 */
2574 {
2575 0x0c000000, 0x00000000, 0x00060000, 0x00000000,
2576 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
2577 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2578 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2579 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2580 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2581 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2582 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2583 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2584 0x00000000, 0x00000000, 0x28880001, 0x54000000,
2585 0x00000004, 0xb6200000, 0x000aaaa0, 0x05555288,
2586 0x80000010, 0x00000000, 0x0000486e, 0x00000000,
2587 0xaaaa0055, 0x55002888, 0x00545401, 0x03030000,
2588 0x0007b000, 0x0000ff00, 0x00000000, 0x05000000,
2589 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
2590 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
2591 0x00000000, 0x00ff0000, 0x00000000, 0x00000000,
2592 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
2593 0x00000000, 0xa0000000, 0x00055fff, 0xfff00000,
2594 0x00aa0000, 0x05502a2a, 0x00151500, 0x0a220015,
2595 0x40400000, 0x00000001, 0xe2980000, 0x0002aaa8,
2596 0x01555400, 0x00000000, 0x0df70000, 0x00000000,
2597 0x00000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2598 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2599 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2600 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2601 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2602 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2603 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2604 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2605 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2606 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2607 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2608 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2609 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2610 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2611 },
2612
2613/* br_abort image (Image 12)
2614 *
2615 * ctr0 : Total number of BRAD_STALLH
2616 * ctr1 : Total number of ONE_QUAD
2617 * ctr2 : Total number of BR0_ABRT
2618 * ctr3 : Total number of BR1_ABRT
2619 */
2620
2621 {
2622 0x0c002000, 0x00000000, 0x00060000, 0x00000000,
2623 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xff0fffff,
2624 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2625 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2626 0x1077ffff, 0xffffffff, 0xffffffff, 0xffffffff,
2627 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2628 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2629 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2630 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2631 0x00000000, 0x00000000, 0x551b0000, 0x00000000,
2632 0x0000000c, 0xd4f00000, 0x00000000, 0x0ffff001,
2633 0xb0000000, 0x00000000, 0x0000fd4c, 0x00000000,
2634 0x000000ff, 0xff00ff1b, 0x00000000, 0x00000000,
2635 0x0000d000, 0x0000ff00, 0x00000000, 0x0e0fffff,
2636 0xffffffff, 0xfffff000, 0x00000000, 0x000ff000,
2637 0x00000000, 0x00ffffff, 0xffffffff, 0xffff0000,
2638 0x00000000, 0x00ff0000, 0x00000000, 0x00ffffff,
2639 0xffffffff, 0xffff0000, 0x00000000, 0x00ff0000,
2640 0x00000000, 0xffffffff, 0xffffffff, 0xfff00000,
2641 0x00400000, 0x00000000, 0x00ffff00, 0x2a86c000,
2642 0x00000000, 0x00000000, 0xf50c0000, 0x00000000,
2643 0x03fffc00, 0x00000000, 0x1a250000, 0x00000000,
2644 0x10000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2645 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2646 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2647 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f,
2648 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2649 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f,
2650 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2651 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2652 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2653 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2654 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2655 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2656 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2657 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2658 },
2659
2660
2661/* isnt image (Image 13)
2662 *
2663 * ctr0 : Total number of cycles for which iside_notrans is asserted.
2664 * ctr1 : Total number of times iside_notrans is asserted for 1-4 cycles.
2665 * ctr2 : Total number of times iside_notrans is asserted for 5-7 cycles.
2666 * ctr3 : Total number of times iside_notrans is asserted for > 7 cycles.
2667 */
2668
2669 {
2670 0x0c018000, 0x00000000, 0x00060000, 0x00000000,
2671 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
2672 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2673 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2674 0xc0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2675 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2676 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2677 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2678 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2679 0x00000000, 0x00000000, 0x22000000, 0x000001bc,
2680 0x10000006, 0x00900000, 0x50000000, 0x00055a20,
2681 0x00000000, 0x00016060, 0x0000c021, 0x00000540,
2682 0x00000000, 0x55002200, 0x00000000, 0x56bc4000,
2683 0x00048000, 0x0000ff00, 0x00000000, 0x17000000,
2684 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000,
2685 0x00000000, 0x00000000, 0x000055ff, 0xffff0000,
2686 0x00000000, 0x00ff0000, 0x00000000, 0x00000000,
2687 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000,
2688 0x00000000, 0x80000000, 0x00015bf3, 0xf5500000,
2689 0x02210000, 0x00100000, 0x00005500, 0x08800000,
2690 0x00001545, 0x85000001, 0x80240000, 0x11000000,
2691 0x00015400, 0x00000000, 0xcdff0000, 0x00000000,
2692 0xc0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2693 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2694 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2695 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2696 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2697 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2698 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2699 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2700 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2701 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2702 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2703 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2704 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2705 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2706 },
2707
2708/* quadrant image (image 14)
2709 *
2710 * ctr0 : Total number of instructions in quadrant 0.
2711 * ctr1 : Total number of instructions in quadrant 1.
2712 * ctr2 : Total number of instructions in quadrant 2.
2713 * ctr3 : Total number of instructions in quadrant 3.
2714 *
2715 * Only works for 32-bit applications.
2716 */
2717
2718 {
2719 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
2720 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
2721 0xffffc000, 0x07ffff00, 0x07ffffff, 0x0007ffff,
2722 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000,
2723 0xf0000000, 0x0fffff00, 0x000fffff, 0x00000fff,
2724 0xff00000f, 0xffff0000, 0x00000000, 0x00ffffff,
2725 0xffcff000, 0x0000040f, 0xfffffffc, 0xff000000,
2726 0x0080ffff, 0xffffcff0, 0x0000000c, 0x0fffffff,
2727 0xfcff0000, 0x00000000, 0x00000000, 0x00000000,
2728 0x00000000, 0x00000000, 0x551b0000, 0x00000000,
2729 0x00000003, 0x17000000, 0x00000000, 0x0ffff001,
2730 0xb0000000, 0x00000000, 0x00000173, 0x00000000,
2731 0x000000ff, 0xff00ff1b, 0x00000000, 0x00000000,
2732 0x000f1ff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
2733 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
2734 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
2735 0x0ffff0cf, 0xffff0000, 0x00000000, 0xf0ffffff,
2736 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
2737 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
2738 0xff7f0000, 0x00000000, 0x00fffff0, 0x2a86c000,
2739 0x00000000, 0x00000003, 0x05f00000, 0x00000000,
2740 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
2741 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2742 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2743 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2744 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2745 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2746 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2747 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2748 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2749 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2750 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2751 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2752 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2753 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2754 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2755 },
2756
2757/* rw_pdfet image (Image 15)
2758 *
2759 * ctr0 : Total of all READ_PRIV address valid cycles.
2760 * ctr1 : Total of all READ_PRIV data valid cycles.
2761 * ctr2 : Overflow of Counter 0.
2762 * ctr3 : Overflow of Counter 1.
2763 */
2764
2765 {
2766 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
2767 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
2768 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2769 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2770 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2771 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2772 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2773 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2774 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2775 0x00000000, 0x00000000, 0x00001b00, 0xaa000000,
2776 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000,
2777 0x01b00000, 0x00000000, 0x00001037, 0x00000000,
2778 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000,
2779 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
2780 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
2781 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
2782 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff,
2783 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
2784 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
2785 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5,
2786 0x40000000, 0x00000000, 0x731c0000, 0x000156ab,
2787 0xfc000000, 0x00000000, 0xffff0000, 0x00000000,
2788 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2789 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2790 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2791 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2792 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2793 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2794 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2795 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2796 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2797 0xfe000000, 0x00000000, 0x00100000, 0x00000000,
2798 0xf8000000, 0x00000000, 0x00000000, 0x00000000,
2799 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
2800 0x00ffffff, 0xffffffff, 0x00000000, 0x00000000,
2801 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
2802 },
2803
2804
2805/* rw_wdfet image (Image 16)
2806 *
2807 * ctr0 : Counts total number of writeback transactions.
2808 * ctr1 : Total number of data valid Runway cycles.
2809 * ctr2 : Overflow of Counter 0.
2810 * ctr3 : Overflow of Counter 1.
2811 */
2812
2813 {
2814 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
2815 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
2816 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2817 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2818 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2819 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2820 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2821 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2822 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2823 0x00000000, 0x00000000, 0x00001b00, 0xaa000000,
2824 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000,
2825 0x01b00000, 0x00000000, 0x00001037, 0x00000000,
2826 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000,
2827 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
2828 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
2829 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
2830 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff,
2831 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
2832 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
2833 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5,
2834 0x40000000, 0x00000000, 0x731c0000, 0x000156ab,
2835 0xfc000000, 0x00000000, 0xffff0000, 0x00000000,
2836 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2837 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2838 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2839 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2840 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2841 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2842 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2843 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2844 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2845 0xfe000000, 0x00000000, 0x00100000, 0x00000000,
2846 0x98000000, 0x00000000, 0x00000000, 0x00000000,
2847 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
2848 0x00ffffff, 0xffffffff, 0x00000000, 0x00000000,
2849 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
2850 },
2851
2852/* shlib_cpi image (Image 17)
2853 *
2854 * ctr0 : Total number of instructions in quadrant 0.
2855 * ctr1 : Total number of CPU clock cycles in quadrant 0.
2856 * ctr2 : Total number of Non-Nullified instructions retired.
2857 * ctr3 : Total number of CPU clock cycles.
2858 *
2859 * Only works for 32-bit shared libraries.
2860 */
2861
2862 {
2863 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
2864 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001,
2865 0xffffc000, 0x07ffff00, 0x07ffffff, 0x0007ffff,
2866 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000,
2867 0xf0150000, 0x0fffff00, 0x000fffff, 0xffffffff,
2868 0xffffffff, 0xffff0000, 0x00000000, 0x00ffffff,
2869 0xffcff000, 0x0000000f, 0xfffffffc, 0xffffffff,
2870 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2871 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2872 0x00000000, 0x00000000, 0x27000000, 0x00000055,
2873 0x02000005, 0x7f500000, 0xc0000000, 0x000ff270,
2874 0x00000000, 0x00000000, 0x00007700, 0x00000ff0,
2875 0x00000000, 0x0000ffff, 0xffffffff, 0xffffff00,
2876 0x00000000, 0x0000ff00, 0x00000000, 0x0f0fffff,
2877 0xffffffff, 0xfffff000, 0x00000000, 0x000ff000,
2878 0x00000000, 0x00ffffff, 0xffffffff, 0xffff0000,
2879 0x00000000, 0x00ff0000, 0x00000000, 0xf0ffffff,
2880 0xffffffff, 0xffff0000, 0x00000000, 0x00ff0000,
2881 0x00000000, 0x0fffffff, 0xffffffff, 0xfff00000,
2882 0x00000000, 0x0ff00000, 0x000000a0, 0x3fffffff,
2883 0xffffffff, 0xffc00000, 0x03d40000, 0x20000000,
2884 0x0003fc00, 0x00000000, 0xffff0000, 0x00000000,
2885 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2886 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
2887 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2888 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
2889 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2890 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
2891 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2892 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2893 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2894 0xfe000000, 0x00000000, 0x00030000, 0x00000000,
2895 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2896 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2897 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2898 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2899 },
2900
2901/* flop image (Image 18)
2902 *
2903 * ctr0 : Total number of floating point instructions (opcode = 0xc).
2904 * ctr1 : Total number of floating point instructions (opcode = 0xe, 0x6, 0x2e, 0x26).
2905 * ctr2 : Unused
2906 * ctr3 : Unused
2907 */
2908
2909 {
2910 0x0001e000, 0x00000000, 0x00000000, 0x00000000,
2911 0x00001010, 0x33ffffff, 0x006fffff, 0xfc5fffff,
2912 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2913 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2914 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2915 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2916 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2917 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2918 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2919 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
2920 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
2921 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
2922 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
2923 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
2924 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
2925 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
2926 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
2927 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
2928 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
2929 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
2930 0x00000000, 0x00000002, 0x67840000, 0x00000000,
2931 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
2932 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2933 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
2934 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2935 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
2936 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2937 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
2938 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2939 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2940 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2941 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
2942 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2943 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2944 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2945 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2946 },
2947
2948/* cachemiss image FROM I_D_MISSES.IDF (Image 19)
2949 *
2950 * ctr0 : icache misses for retired instructions
2951 * ctr1 : total cycles
2952 * ctr2 : dcache misses for retired instructions
2953 * ctr3 : number of retired instructions
2954 */
2955 {
2956 0x2801e000, 0x00000000, 0x00010000, 0x00000000,
2957 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff,
2958 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff,
2959 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
2960 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2961 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
2962 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2963 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2964 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
2965 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0,
2966 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800,
2967 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0,
2968 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555,
2969 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff,
2970 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
2971 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
2972 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
2973 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
2974 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
2975 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf,
2976 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000,
2977 0x03c14000, 0x00000000, 0xffff0000, 0x00000000,
2978 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
2979 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
2980 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
2981 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
2982 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2983 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
2984 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
2985 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2986 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
2987 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
2988 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2989 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2990 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2991 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2992 },
2993
2994/* branch FROM br_report3.idf
2995 *
2996 * ctr0 : Total number of mispredicted branches.
2997 * ctr1 : Some Non-Nullified unpredictable branches.
2998 * ctr2 : Total number of branches (Nullified + Non-Nullified)
2999 * (Unpredicted+ Predicted Taken +Predicted Not Taken).
3000 * Total of All Branches.
3001 * ctr3 : Remaining Non-Nullified unpredictable branches.
3002 */
3003 {
3004 0x4001e000, 0x00000000, 0x00000000, 0x00000000,
3005 0x00000000, 0xffffffff, 0xff9fffff, 0xfe0fffff,
3006 0xffffbaff, 0xfdffc0ff, 0xfffdffff, 0xfffffeff,
3007 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
3008 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3009 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
3010 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3011 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3012 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
3013 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
3014 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
3015 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
3016 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
3017 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
3018 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
3019 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
3020 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
3021 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
3022 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
3023 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
3024 0x00000000, 0x00000002, 0x67840000, 0x00000000,
3025 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
3026 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
3027 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
3028 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
3029 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
3030 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
3031 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
3032 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
3033 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
3034 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
3035 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
3036 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3037 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3038 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3039 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3040 },
3041
3042/* crstack FROM crs_report.idf
3043 *
3044 * ctr0: correctly predicted branches by the pop_latch
3045 * ctr1: some procedure returns
3046 * ctr2: all branches, (includes nullified)
3047 * ctr3: remaining procedure returns
3048 */
3049 {
3050 0x4001e000, 0x00000000, 0x00000000, 0x00000000,
3051 0x00000000, 0xffffffff, 0xffa10300, 0x000fffff,
3052 0xffffbaf8, 0x3000007f, 0xffffffff, 0xfffffeff,
3053 0xff7fffff, 0xffffffff, 0xffffff00, 0x00000000,
3054 0xf2ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3055 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
3056 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3057 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3058 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
3059 0x00000000, 0x00000000, 0xd22d0000, 0x00000000,
3060 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900,
3061 0x90000000, 0x00000000, 0x0000907e, 0x00000000,
3062 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000,
3063 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
3064 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
3065 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
3066 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff,
3067 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
3068 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff,
3069 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000,
3070 0x00000000, 0x00000002, 0x67840000, 0x00000000,
3071 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000,
3072 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
3073 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
3074 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
3075 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
3076 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
3077 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
3078 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
3079 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
3080 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
3081 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
3082 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3083 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3084 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3085 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3086 },
3087
3088/* icache_report image
3089 *
3090 * ctr0 : Icache misses actually used by the core.
3091 * ctr1 : ICORE_AV (Icache misses the core THINKS it needs, including fetching down speculative paths).
3092 * ctr2 : READs on Runway (Icache misses that made it out to Runway, including
3093 * prefetches).
3094 * ctr3 : Prefetch returns (1x and 2x).
3095 */
3096 {
3097 0x00000000, 0x00000000, 0x00010000, 0x00000000,
3098 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
3099 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3100 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
3101 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3102 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
3103 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3104 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3105 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
3106 0x00000000, 0x00000000, 0xd2002d00, 0x00000000,
3107 0x0000000b, 0x46000000, 0x0000000f, 0xf00ff900,
3108 0x00900000, 0x00000000, 0x0000907e, 0x00000000,
3109 0x0000ff00, 0xff83bf03, 0xdf030303, 0x03030000,
3110 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff,
3111 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000,
3112 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff,
3113 0xffffffff, 0xffff0000, 0x00000000, 0x80ffffff,
3114 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000,
3115 0x00000000, 0x4fffffff, 0xffffffff, 0xffffffff,
3116 0xffff5555, 0x55500000, 0x3f003f80, 0x274026c0,
3117 0x00000000, 0x00000002, 0x67840000, 0x00000003,
3118 0xfc03fc00, 0x00000000, 0x0eff0000, 0x00000000,
3119 0x00000000, 0x00000000, 0x00ffffff, 0xff3fffff,
3120 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000,
3121 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
3122 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f,
3123 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
3124 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f,
3125 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
3126 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
3127 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
3128 0xfe000000, 0x00000000, 0x00130000, 0x00000000,
3129 0xd0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3130 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3131 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3132 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
3133
3134 }
3135
3136};
3137
3138#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 @@
1/*
2 * PARISC Architecture-dependent parts of process handling
3 * based on the work for i386
4 *
5 * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
6 * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
7 * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
8 * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org>
9 * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
10 * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
11 * Copyright (C) 2000 David Kennedy <dkennedy with linuxcare.com>
12 * Copyright (C) 2000 Richard Hirst <rhirst with parisc-lixux.org>
13 * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
14 * Copyright (C) 2001 Alan Modra <amodra at parisc-linux.org>
15 * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
16 * Copyright (C) 2001-2002 Helge Deller <deller at parisc-linux.org>
17 * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
18 *
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 */
34
35#include <stdarg.h>
36
37#include <linux/elf.h>
38#include <linux/errno.h>
39#include <linux/kernel.h>
40#include <linux/mm.h>
41#include <linux/module.h>
42#include <linux/personality.h>
43#include <linux/ptrace.h>
44#include <linux/sched.h>
45#include <linux/stddef.h>
46#include <linux/unistd.h>
47#include <linux/kallsyms.h>
48
49#include <asm/io.h>
50#include <asm/offsets.h>
51#include <asm/pdc.h>
52#include <asm/pdc_chassis.h>
53#include <asm/pgalloc.h>
54#include <asm/uaccess.h>
55#include <asm/unwind.h>
56
57static int hlt_counter;
58
59/*
60 * Power off function, if any
61 */
62void (*pm_power_off)(void);
63
64void disable_hlt(void)
65{
66 hlt_counter++;
67}
68
69EXPORT_SYMBOL(disable_hlt);
70
71void enable_hlt(void)
72{
73 hlt_counter--;
74}
75
76EXPORT_SYMBOL(enable_hlt);
77
78void default_idle(void)
79{
80 barrier();
81}
82
83/*
84 * The idle thread. There's no useful work to be
85 * done, so just try to conserve power and have a
86 * low exit latency (ie sit in a loop waiting for
87 * somebody to say that they'd like to reschedule)
88 */
89void cpu_idle(void)
90{
91 /* endless idle loop with no priority at all */
92 while (1) {
93 while (!need_resched())
94 barrier();
95 schedule();
96 check_pgt_cache();
97 }
98}
99
100
101#ifdef __LP64__
102#define COMMAND_GLOBAL 0xfffffffffffe0030UL
103#else
104#define COMMAND_GLOBAL 0xfffe0030
105#endif
106
107#define CMD_RESET 5 /* reset any module */
108
109/*
110** The Wright Brothers and Gecko systems have a H/W problem
111** (Lasi...'nuf said) may cause a broadcast reset to lockup
112** the system. An HVERSION dependent PDC call was developed
113** to perform a "safe", platform specific broadcast reset instead
114** of kludging up all the code.
115**
116** Older machines which do not implement PDC_BROADCAST_RESET will
117** return (with an error) and the regular broadcast reset can be
118** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET
119** the PDC call will not return (the system will be reset).
120*/
121void machine_restart(char *cmd)
122{
123#ifdef FASTBOOT_SELFTEST_SUPPORT
124 /*
125 ** If user has modified the Firmware Selftest Bitmap,
126 ** run the tests specified in the bitmap after the
127 ** system is rebooted w/PDC_DO_RESET.
128 **
129 ** ftc_bitmap = 0x1AUL "Skip destructive memory tests"
130 **
131 ** Using "directed resets" at each processor with the MEM_TOC
132 ** vector cleared will also avoid running destructive
133 ** memory self tests. (Not implemented yet)
134 */
135 if (ftc_bitmap) {
136 pdc_do_firm_test_reset(ftc_bitmap);
137 }
138#endif
139 /* set up a new led state on systems shipped with a LED State panel */
140 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
141
142 /* "Normal" system reset */
143 pdc_do_reset();
144
145 /* Nope...box should reset with just CMD_RESET now */
146 gsc_writel(CMD_RESET, COMMAND_GLOBAL);
147
148 /* Wait for RESET to lay us to rest. */
149 while (1) ;
150
151}
152
153EXPORT_SYMBOL(machine_restart);
154
155void machine_halt(void)
156{
157 /*
158 ** The LED/ChassisCodes are updated by the led_halt()
159 ** function, called by the reboot notifier chain.
160 */
161}
162
163EXPORT_SYMBOL(machine_halt);
164
165
166/*
167 * This routine is called from sys_reboot to actually turn off the
168 * machine
169 */
170void machine_power_off(void)
171{
172 /* If there is a registered power off handler, call it. */
173 if(pm_power_off)
174 pm_power_off();
175
176 /* Put the soft power button back under hardware control.
177 * If the user had already pressed the power button, the
178 * following call will immediately power off. */
179 pdc_soft_power_button(0);
180
181 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
182
183 /* It seems we have no way to power the system off via
184 * software. The user has to press the button himself. */
185
186 printk(KERN_EMERG "System shut down completed.\n"
187 KERN_EMERG "Please power this system off now.");
188}
189
190EXPORT_SYMBOL(machine_power_off);
191
192
193/*
194 * Create a kernel thread
195 */
196
197extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
198pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
199{
200
201 /*
202 * FIXME: Once we are sure we don't need any debug here,
203 * kernel_thread can become a #define.
204 */
205
206 return __kernel_thread(fn, arg, flags);
207}
208EXPORT_SYMBOL(kernel_thread);
209
210/*
211 * Free current thread data structures etc..
212 */
213void exit_thread(void)
214{
215}
216
217void flush_thread(void)
218{
219 /* Only needs to handle fpu stuff or perf monitors.
220 ** REVISIT: several arches implement a "lazy fpu state".
221 */
222 set_fs(USER_DS);
223}
224
225void release_thread(struct task_struct *dead_task)
226{
227}
228
229/*
230 * Fill in the FPU structure for a core dump.
231 */
232
233int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
234{
235 if (regs == NULL)
236 return 0;
237
238 memcpy(r, regs->fr, sizeof *r);
239 return 1;
240}
241
242int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
243{
244 memcpy(r, tsk->thread.regs.fr, sizeof(*r));
245 return 1;
246}
247
248/* Note that "fork()" is implemented in terms of clone, with
249 parameters (SIGCHLD, regs->gr[30], regs). */
250int
251sys_clone(unsigned long clone_flags, unsigned long usp,
252 struct pt_regs *regs)
253{
254 int __user *user_tid = (int __user *)regs->gr[26];
255
256 /* usp must be word aligned. This also prevents users from
257 * passing in the value 1 (which is the signal for a special
258 * return for a kernel thread) */
259 usp = ALIGN(usp, 4);
260
261 /* A zero value for usp means use the current stack */
262 if(usp == 0)
263 usp = regs->gr[30];
264
265 return do_fork(clone_flags, usp, regs, 0, user_tid, NULL);
266}
267
268int
269sys_vfork(struct pt_regs *regs)
270{
271 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL);
272}
273
274int
275copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
276 unsigned long unused, /* in ia64 this is "user_stack_size" */
277 struct task_struct * p, struct pt_regs * pregs)
278{
279 struct pt_regs * cregs = &(p->thread.regs);
280 struct thread_info *ti = p->thread_info;
281
282 /* We have to use void * instead of a function pointer, because
283 * function pointers aren't a pointer to the function on 64-bit.
284 * Make them const so the compiler knows they live in .text */
285 extern void * const ret_from_kernel_thread;
286 extern void * const child_return;
287#ifdef CONFIG_HPUX
288 extern void * const hpux_child_return;
289#endif
290
291 *cregs = *pregs;
292
293 /* Set the return value for the child. Note that this is not
294 actually restored by the syscall exit path, but we put it
295 here for consistency in case of signals. */
296 cregs->gr[28] = 0; /* child */
297
298 /*
299 * We need to differentiate between a user fork and a
300 * kernel fork. We can't use user_mode, because the
301 * the syscall path doesn't save iaoq. Right now
302 * We rely on the fact that kernel_thread passes
303 * in zero for usp.
304 */
305 if (usp == 1) {
306 /* kernel thread */
307 cregs->ksp = (((unsigned long)(ti)) + THREAD_SZ_ALGN);
308 /* Must exit via ret_from_kernel_thread in order
309 * to call schedule_tail()
310 */
311 cregs->kpc = (unsigned long) &ret_from_kernel_thread;
312 /*
313 * Copy function and argument to be called from
314 * ret_from_kernel_thread.
315 */
316#ifdef __LP64__
317 cregs->gr[27] = pregs->gr[27];
318#endif
319 cregs->gr[26] = pregs->gr[26];
320 cregs->gr[25] = pregs->gr[25];
321 } else {
322 /* user thread */
323 /*
324 * Note that the fork wrappers are responsible
325 * for setting gr[21].
326 */
327
328 /* Use same stack depth as parent */
329 cregs->ksp = ((unsigned long)(ti))
330 + (pregs->gr[21] & (THREAD_SIZE - 1));
331 cregs->gr[30] = usp;
332 if (p->personality == PER_HPUX) {
333#ifdef CONFIG_HPUX
334 cregs->kpc = (unsigned long) &hpux_child_return;
335#else
336 BUG();
337#endif
338 } else {
339 cregs->kpc = (unsigned long) &child_return;
340 }
341 }
342
343 return 0;
344}
345
346unsigned long thread_saved_pc(struct task_struct *t)
347{
348 return t->thread.regs.kpc;
349}
350
351/*
352 * sys_execve() executes a new program.
353 */
354
355asmlinkage int sys_execve(struct pt_regs *regs)
356{
357 int error;
358 char *filename;
359
360 filename = getname((const char __user *) regs->gr[26]);
361 error = PTR_ERR(filename);
362 if (IS_ERR(filename))
363 goto out;
364 error = do_execve(filename, (char __user **) regs->gr[25],
365 (char __user **) regs->gr[24], regs);
366 if (error == 0) {
367 task_lock(current);
368 current->ptrace &= ~PT_DTRACE;
369 task_unlock(current);
370 }
371 putname(filename);
372out:
373
374 return error;
375}
376
377unsigned long
378get_wchan(struct task_struct *p)
379{
380 struct unwind_frame_info info;
381 unsigned long ip;
382 int count = 0;
383 /*
384 * These bracket the sleeping functions..
385 */
386
387 unwind_frame_init_from_blocked_task(&info, p);
388 do {
389 if (unwind_once(&info) < 0)
390 return 0;
391 ip = info.ip;
392 if (!in_sched_functions(ip))
393 return ip;
394 } while (count++ < 16);
395 return 0;
396}
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 @@
1/* $Id: processor.c,v 1.1 2002/07/20 16:27:06 rhirst Exp $
2 *
3 * Initial setup-routines for HP 9000 based hardware.
4 *
5 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
6 * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
7 * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
8 * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
9 * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
10 * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
11 *
12 * Initial PA-RISC Version: 04-23-1999 by Helge Deller
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 */
29#include <linux/config.h>
30#include <linux/delay.h>
31#include <linux/init.h>
32#include <linux/mm.h>
33#include <linux/module.h>
34#include <linux/seq_file.h>
35#include <linux/slab.h>
36#include <linux/cpu.h>
37
38#include <asm/cache.h>
39#include <asm/hardware.h> /* for register_parisc_driver() stuff */
40#include <asm/processor.h>
41#include <asm/page.h>
42#include <asm/pdc.h>
43#include <asm/pdcpat.h>
44#include <asm/irq.h> /* for struct irq_region */
45#include <asm/parisc-device.h>
46
47struct system_cpuinfo_parisc boot_cpu_data;
48EXPORT_SYMBOL(boot_cpu_data);
49
50struct cpuinfo_parisc cpu_data[NR_CPUS];
51
52/*
53** PARISC CPU driver - claim "device" and initialize CPU data structures.
54**
55** Consolidate per CPU initialization into (mostly) one module.
56** Monarch CPU will initialize boot_cpu_data which shouldn't
57** change once the system has booted.
58**
59** The callback *should* do per-instance initialization of
60** everything including the monarch. "Per CPU" init code in
61** setup.c:start_parisc() has migrated here and start_parisc()
62** will call register_parisc_driver(&cpu_driver) before calling do_inventory().
63**
64** The goal of consolidating CPU initialization into one place is
65** to make sure all CPU's get initialized the same way.
66** The code path not shared is how PDC hands control of the CPU to the OS.
67** The initialization of OS data structures is the same (done below).
68*/
69
70/**
71 * processor_probe - Determine if processor driver should claim this device.
72 * @dev: The device which has been found.
73 *
74 * Determine if processor driver should claim this chip (return 0) or not
75 * (return 1). If so, initialize the chip and tell other partners in crime
76 * they have work to do.
77 */
78static int __init processor_probe(struct parisc_device *dev)
79{
80 unsigned long txn_addr;
81 unsigned long cpuid;
82 struct cpuinfo_parisc *p;
83
84#ifndef CONFIG_SMP
85 if (boot_cpu_data.cpu_count > 0) {
86 printk(KERN_INFO "CONFIG_SMP=n ignoring additional CPUs\n");
87 return 1;
88 }
89#endif
90
91 /* logical CPU ID and update global counter
92 * May get overwritten by PAT code.
93 */
94 cpuid = boot_cpu_data.cpu_count;
95 txn_addr = dev->hpa; /* for legacy PDC */
96
97#ifdef __LP64__
98 if (is_pdc_pat()) {
99 ulong status;
100 unsigned long bytecnt;
101 pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
102#undef USE_PAT_CPUID
103#ifdef USE_PAT_CPUID
104 struct pdc_pat_cpu_num cpu_info;
105#endif
106
107 status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc,
108 dev->mod_index, PA_VIEW, &pa_pdc_cell);
109
110 BUG_ON(PDC_OK != status);
111
112 /* verify it's the same as what do_pat_inventory() found */
113 BUG_ON(dev->mod_info != pa_pdc_cell.mod_info);
114 BUG_ON(dev->pmod_loc != pa_pdc_cell.mod_location);
115
116 txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */
117
118#ifdef USE_PAT_CPUID
119/* We need contiguous numbers for cpuid. Firmware's notion
120 * of cpuid is for physical CPUs and we just don't care yet.
121 * We'll care when we need to query PAT PDC about a CPU *after*
122 * boot time (ie shutdown a CPU from an OS perspective).
123 */
124 /* get the cpu number */
125 status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa);
126
127 BUG_ON(PDC_OK != status);
128
129 if (cpu_info.cpu_num >= NR_CPUS) {
130 printk(KERN_WARNING "IGNORING CPU at 0x%x,"
131 " cpu_slot_id > NR_CPUS"
132 " (%ld > %d)\n",
133 dev->hpa, cpu_info.cpu_num, NR_CPUS);
134 /* Ignore CPU since it will only crash */
135 boot_cpu_data.cpu_count--;
136 return 1;
137 } else {
138 cpuid = cpu_info.cpu_num;
139 }
140#endif
141 }
142#endif
143
144 p = &cpu_data[cpuid];
145 boot_cpu_data.cpu_count++;
146
147 /* initialize counters */
148 memset(p, 0, sizeof(struct cpuinfo_parisc));
149
150 p->loops_per_jiffy = loops_per_jiffy;
151 p->dev = dev; /* Save IODC data in case we need it */
152 p->hpa = dev->hpa; /* save CPU hpa */
153 p->cpuid = cpuid; /* save CPU id */
154 p->txn_addr = txn_addr; /* save CPU IRQ address */
155#ifdef CONFIG_SMP
156 spin_lock_init(&p->lock);
157
158 /*
159 ** FIXME: review if any other initialization is clobbered
160 ** for boot_cpu by the above memset().
161 */
162
163 /* stolen from init_percpu_prof() */
164 cpu_data[cpuid].prof_counter = 1;
165 cpu_data[cpuid].prof_multiplier = 1;
166#endif
167
168 /*
169 ** CONFIG_SMP: init_smp_config() will attempt to get CPU's into
170 ** OS control. RENDEZVOUS is the default state - see mem_set above.
171 ** p->state = STATE_RENDEZVOUS;
172 */
173
174#if 0
175 /* CPU 0 IRQ table is statically allocated/initialized */
176 if (cpuid) {
177 struct irqaction actions[];
178
179 /*
180 ** itimer and ipi IRQ handlers are statically initialized in
181 ** arch/parisc/kernel/irq.c. ie Don't need to register them.
182 */
183 actions = kmalloc(sizeof(struct irqaction)*MAX_CPU_IRQ, GFP_ATOMIC);
184 if (!actions) {
185 /* not getting it's own table, share with monarch */
186 actions = cpu_irq_actions[0];
187 }
188
189 cpu_irq_actions[cpuid] = actions;
190 }
191#endif
192
193 /*
194 * Bring this CPU up now! (ignore bootstrap cpuid == 0)
195 */
196#ifdef CONFIG_SMP
197 if (cpuid) {
198 cpu_set(cpuid, cpu_present_map);
199 cpu_up(cpuid);
200 }
201#endif
202
203 return 0;
204}
205
206/**
207 * collect_boot_cpu_data - Fill the boot_cpu_data structure.
208 *
209 * This function collects and stores the generic processor information
210 * in the boot_cpu_data structure.
211 */
212void __init collect_boot_cpu_data(void)
213{
214 memset(&boot_cpu_data, 0, sizeof(boot_cpu_data));
215
216 boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */
217
218 /* get CPU-Model Information... */
219#define p ((unsigned long *)&boot_cpu_data.pdc.model)
220 if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK)
221 printk(KERN_INFO
222 "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
223 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
224#undef p
225
226 if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK)
227 printk(KERN_INFO "vers %08lx\n",
228 boot_cpu_data.pdc.versions);
229
230 if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK)
231 printk(KERN_INFO "CPUID vers %ld rev %ld (0x%08lx)\n",
232 (boot_cpu_data.pdc.cpuid >> 5) & 127,
233 boot_cpu_data.pdc.cpuid & 31,
234 boot_cpu_data.pdc.cpuid);
235
236 if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK)
237 printk(KERN_INFO "capabilities 0x%lx\n",
238 boot_cpu_data.pdc.capabilities);
239
240 if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name) == PDC_OK)
241 printk(KERN_INFO "model %s\n",
242 boot_cpu_data.pdc.sys_model_name);
243
244 boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion;
245 boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion;
246
247 boot_cpu_data.cpu_type = parisc_get_cpu_type(boot_cpu_data.hversion);
248 boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0];
249 boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1];
250}
251
252
253/**
254 * init_cpu_profiler - enable/setup per cpu profiling hooks.
255 * @cpunum: The processor instance.
256 *
257 * FIXME: doesn't do much yet...
258 */
259static inline void __init
260init_percpu_prof(int cpunum)
261{
262 cpu_data[cpunum].prof_counter = 1;
263 cpu_data[cpunum].prof_multiplier = 1;
264}
265
266
267/**
268 * init_per_cpu - Handle individual processor initializations.
269 * @cpunum: logical processor number.
270 *
271 * This function handles initialization for *every* CPU
272 * in the system:
273 *
274 * o Set "default" CPU width for trap handlers
275 *
276 * o Enable FP coprocessor
277 * REVISIT: this could be done in the "code 22" trap handler.
278 * (frowands idea - that way we know which processes need FP
279 * registers saved on the interrupt stack.)
280 * NEWS FLASH: wide kernels need FP coprocessor enabled to handle
281 * formatted printing of %lx for example (double divides I think)
282 *
283 * o Enable CPU profiling hooks.
284 */
285int __init init_per_cpu(int cpunum)
286{
287 int ret;
288 struct pdc_coproc_cfg coproc_cfg;
289
290 set_firmware_width();
291 ret = pdc_coproc_cfg(&coproc_cfg);
292
293 if(ret >= 0 && coproc_cfg.ccr_functional) {
294 mtctl(coproc_cfg.ccr_functional, 10); /* 10 == Coprocessor Control Reg */
295
296 /* FWIW, FP rev/model is a more accurate way to determine
297 ** CPU type. CPU rev/model has some ambiguous cases.
298 */
299 cpu_data[cpunum].fp_rev = coproc_cfg.revision;
300 cpu_data[cpunum].fp_model = coproc_cfg.model;
301
302 printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n",
303 cpunum, coproc_cfg.revision, coproc_cfg.model);
304
305 /*
306 ** store status register to stack (hopefully aligned)
307 ** and clear the T-bit.
308 */
309 asm volatile ("fstd %fr0,8(%sp)");
310
311 } else {
312 printk(KERN_WARNING "WARNING: No FP CoProcessor?!"
313 " (coproc_cfg.ccr_functional == 0x%lx, expected 0xc0)\n"
314#ifdef __LP64__
315 "Halting Machine - FP required\n"
316#endif
317 , coproc_cfg.ccr_functional);
318#ifdef __LP64__
319 mdelay(100); /* previous chars get pushed to console */
320 panic("FP CoProc not reported");
321#endif
322 }
323
324 /* FUTURE: Enable Performance Monitor : ccr bit 0x20 */
325 init_percpu_prof(cpunum);
326
327 return ret;
328}
329
330/*
331 * Display cpu info for all cpu's.
332 */
333int
334show_cpuinfo (struct seq_file *m, void *v)
335{
336 int n;
337
338 for(n=0; n<boot_cpu_data.cpu_count; n++) {
339#ifdef CONFIG_SMP
340 if (0 == cpu_data[n].hpa)
341 continue;
342#ifdef ENTRY_SYS_CPUS
343#error iCOD support wants to show CPU state here
344#endif
345#endif
346 seq_printf(m, "processor\t: %d\n"
347 "cpu family\t: PA-RISC %s\n",
348 n, boot_cpu_data.family_name);
349
350 seq_printf(m, "cpu\t\t: %s\n", boot_cpu_data.cpu_name );
351
352 /* cpu MHz */
353 seq_printf(m, "cpu MHz\t\t: %d.%06d\n",
354 boot_cpu_data.cpu_hz / 1000000,
355 boot_cpu_data.cpu_hz % 1000000 );
356
357 seq_printf(m, "model\t\t: %s\n"
358 "model name\t: %s\n",
359 boot_cpu_data.pdc.sys_model_name,
360 cpu_data[n].dev ?
361 cpu_data[n].dev->name : "Unknown" );
362
363 seq_printf(m, "hversion\t: 0x%08x\n"
364 "sversion\t: 0x%08x\n",
365 boot_cpu_data.hversion,
366 boot_cpu_data.sversion );
367
368 /* print cachesize info */
369 show_cache_info(m);
370
371 seq_printf(m, "bogomips\t: %lu.%02lu\n",
372 cpu_data[n].loops_per_jiffy / (500000 / HZ),
373 (cpu_data[n].loops_per_jiffy / (5000 / HZ)) % 100);
374
375 seq_printf(m, "software id\t: %ld\n\n",
376 boot_cpu_data.pdc.model.sw_id);
377 }
378 return 0;
379}
380
381static struct parisc_device_id processor_tbl[] = {
382 { HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID },
383 { 0, }
384};
385
386static struct parisc_driver cpu_driver = {
387 .name = "CPU",
388 .id_table = processor_tbl,
389 .probe = processor_probe
390};
391
392/**
393 * processor_init - Processor initalization procedure.
394 *
395 * Register this driver.
396 */
397void __init processor_init(void)
398{
399 register_parisc_driver(&cpu_driver);
400}
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 @@
1/*
2 * Kernel support for the ptrace() and syscall tracing interfaces.
3 *
4 * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc.
5 * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx>
6 * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
7 */
8
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <linux/mm.h>
12#include <linux/smp.h>
13#include <linux/smp_lock.h>
14#include <linux/errno.h>
15#include <linux/ptrace.h>
16#include <linux/user.h>
17#include <linux/personality.h>
18#include <linux/security.h>
19#include <linux/compat.h>
20
21#include <asm/uaccess.h>
22#include <asm/pgtable.h>
23#include <asm/system.h>
24#include <asm/processor.h>
25#include <asm/offsets.h>
26
27/* PSW bits we allow the debugger to modify */
28#define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB)
29
30#undef DEBUG_PTRACE
31
32#ifdef DEBUG_PTRACE
33#define DBG(x...) printk(x)
34#else
35#define DBG(x...)
36#endif
37
38#ifdef __LP64__
39
40/* This function is needed to translate 32 bit pt_regs offsets in to
41 * 64 bit pt_regs offsets. For example, a 32 bit gdb under a 64 bit kernel
42 * will request offset 12 if it wants gr3, but the lower 32 bits of
43 * the 64 bit kernels view of gr3 will be at offset 28 (3*8 + 4).
44 * This code relies on a 32 bit pt_regs being comprised of 32 bit values
45 * except for the fp registers which (a) are 64 bits, and (b) follow
46 * the gr registers at the start of pt_regs. The 32 bit pt_regs should
47 * be half the size of the 64 bit pt_regs, plus 32*4 to allow for fr[]
48 * being 64 bit in both cases.
49 */
50
51static long translate_usr_offset(long offset)
52{
53 if (offset < 0)
54 return -1;
55 else if (offset <= 32*4) /* gr[0..31] */
56 return offset * 2 + 4;
57 else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */
58 return offset + 32*4;
59 else if (offset < sizeof(struct pt_regs)/2 + 32*4)
60 return offset * 2 + 4 - 32*8;
61 else
62 return -1;
63}
64#endif
65
66/*
67 * Called by kernel/ptrace.c when detaching..
68 *
69 * Make sure single step bits etc are not set.
70 */
71void ptrace_disable(struct task_struct *child)
72{
73 /* make sure the trap bits are not set */
74 pa_psw(child)->r = 0;
75 pa_psw(child)->t = 0;
76 pa_psw(child)->h = 0;
77 pa_psw(child)->l = 0;
78}
79
80long sys_ptrace(long request, pid_t pid, long addr, long data)
81{
82 struct task_struct *child;
83 long ret;
84#ifdef DEBUG_PTRACE
85 long oaddr=addr, odata=data;
86#endif
87
88 lock_kernel();
89 ret = -EPERM;
90 if (request == PTRACE_TRACEME) {
91 /* are we already being traced? */
92 if (current->ptrace & PT_PTRACED)
93 goto out;
94
95 ret = security_ptrace(current->parent, current);
96 if (ret)
97 goto out;
98
99 /* set the ptrace bit in the process flags. */
100 current->ptrace |= PT_PTRACED;
101 ret = 0;
102 goto out;
103 }
104
105 ret = -ESRCH;
106 read_lock(&tasklist_lock);
107 child = find_task_by_pid(pid);
108 if (child)
109 get_task_struct(child);
110 read_unlock(&tasklist_lock);
111 if (!child)
112 goto out;
113 ret = -EPERM;
114 if (pid == 1) /* no messing around with init! */
115 goto out_tsk;
116
117 if (request == PTRACE_ATTACH) {
118 ret = ptrace_attach(child);
119 goto out_tsk;
120 }
121
122 ret = ptrace_check_attach(child, request == PTRACE_KILL);
123 if (ret < 0)
124 goto out_tsk;
125
126 switch (request) {
127 case PTRACE_PEEKTEXT: /* read word at location addr. */
128 case PTRACE_PEEKDATA: {
129 int copied;
130
131#ifdef __LP64__
132 if (is_compat_task(child)) {
133 unsigned int tmp;
134
135 addr &= 0xffffffffL;
136 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
137 ret = -EIO;
138 if (copied != sizeof(tmp))
139 goto out_tsk;
140 ret = put_user(tmp,(unsigned int *) data);
141 DBG("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n",
142 request == PTRACE_PEEKTEXT ? "TEXT" : "DATA",
143 pid, oaddr, odata, ret, tmp);
144 }
145 else
146#endif
147 {
148 unsigned long tmp;
149
150 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
151 ret = -EIO;
152 if (copied != sizeof(tmp))
153 goto out_tsk;
154 ret = put_user(tmp,(unsigned long *) data);
155 }
156 goto out_tsk;
157 }
158
159 /* when I and D space are separate, this will have to be fixed. */
160 case PTRACE_POKETEXT: /* write the word at location addr. */
161 case PTRACE_POKEDATA:
162 ret = 0;
163#ifdef __LP64__
164 if (is_compat_task(child)) {
165 unsigned int tmp = (unsigned int)data;
166 DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
167 request == PTRACE_POKETEXT ? "TEXT" : "DATA",
168 pid, oaddr, odata);
169 addr &= 0xffffffffL;
170 if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp))
171 goto out_tsk;
172 }
173 else
174#endif
175 {
176 if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
177 goto out_tsk;
178 }
179 ret = -EIO;
180 goto out_tsk;
181
182 /* Read the word at location addr in the USER area. For ptraced
183 processes, the kernel saves all regs on a syscall. */
184 case PTRACE_PEEKUSR: {
185 ret = -EIO;
186#ifdef __LP64__
187 if (is_compat_task(child)) {
188 unsigned int tmp;
189
190 if (addr & (sizeof(int)-1))
191 goto out_tsk;
192 if ((addr = translate_usr_offset(addr)) < 0)
193 goto out_tsk;
194
195 tmp = *(unsigned int *) ((char *) task_regs(child) + addr);
196 ret = put_user(tmp, (unsigned int *) data);
197 DBG("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n",
198 pid, oaddr, odata, ret, addr, tmp);
199 }
200 else
201#endif
202 {
203 unsigned long tmp;
204
205 if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
206 goto out_tsk;
207 tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
208 ret = put_user(tmp, (unsigned long *) data);
209 }
210 goto out_tsk;
211 }
212
213 /* Write the word at location addr in the USER area. This will need
214 to change when the kernel no longer saves all regs on a syscall.
215 FIXME. There is a problem at the moment in that r3-r18 are only
216 saved if the process is ptraced on syscall entry, and even then
217 those values are overwritten by actual register values on syscall
218 exit. */
219 case PTRACE_POKEUSR:
220 ret = -EIO;
221 /* Some register values written here may be ignored in
222 * entry.S:syscall_restore_rfi; e.g. iaoq is written with
223 * r31/r31+4, and not with the values in pt_regs.
224 */
225 /* PT_PSW=0, so this is valid for 32 bit processes under 64
226 * bit kernels.
227 */
228 if (addr == PT_PSW) {
229 /* PT_PSW=0, so this is valid for 32 bit processes
230 * under 64 bit kernels.
231 *
232 * Allow writing to Nullify, Divide-step-correction,
233 * and carry/borrow bits.
234 * BEWARE, if you set N, and then single step, it won't
235 * stop on the nullified instruction.
236 */
237 DBG("sys_ptrace(POKEUSR, %d, %lx, %lx)\n",
238 pid, oaddr, odata);
239 data &= USER_PSW_BITS;
240 task_regs(child)->gr[0] &= ~USER_PSW_BITS;
241 task_regs(child)->gr[0] |= data;
242 ret = 0;
243 goto out_tsk;
244 }
245#ifdef __LP64__
246 if (is_compat_task(child)) {
247 if (addr & (sizeof(int)-1))
248 goto out_tsk;
249 if ((addr = translate_usr_offset(addr)) < 0)
250 goto out_tsk;
251 DBG("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n",
252 pid, oaddr, odata, addr);
253 if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
254 /* Special case, fp regs are 64 bits anyway */
255 *(unsigned int *) ((char *) task_regs(child) + addr) = data;
256 ret = 0;
257 }
258 else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) ||
259 addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 ||
260 addr == PT_SAR+4) {
261 /* Zero the top 32 bits */
262 *(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0;
263 *(unsigned int *) ((char *) task_regs(child) + addr) = data;
264 ret = 0;
265 }
266 goto out_tsk;
267 }
268 else
269#endif
270 {
271 if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
272 goto out_tsk;
273 if ((addr >= PT_GR1 && addr <= PT_GR31) ||
274 addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
275 (addr >= PT_FR0 && addr <= PT_FR31 + 4) ||
276 addr == PT_SAR) {
277 *(unsigned long *) ((char *) task_regs(child) + addr) = data;
278 ret = 0;
279 }
280 goto out_tsk;
281 }
282
283 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
284 case PTRACE_CONT:
285 ret = -EIO;
286 DBG("sys_ptrace(%s)\n",
287 request == PTRACE_SYSCALL ? "SYSCALL" : "CONT");
288 if ((unsigned long) data > _NSIG)
289 goto out_tsk;
290 child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
291 if (request == PTRACE_SYSCALL) {
292 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
293 } else {
294 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
295 }
296 child->exit_code = data;
297 goto out_wake_notrap;
298
299 case PTRACE_KILL:
300 /*
301 * make the child exit. Best I can do is send it a
302 * sigkill. perhaps it should be put in the status
303 * that it wants to exit.
304 */
305 DBG("sys_ptrace(KILL)\n");
306 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
307 goto out_tsk;
308 child->exit_code = SIGKILL;
309 goto out_wake_notrap;
310
311 case PTRACE_SINGLEBLOCK:
312 DBG("sys_ptrace(SINGLEBLOCK)\n");
313 ret = -EIO;
314 if ((unsigned long) data > _NSIG)
315 goto out_tsk;
316 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
317 child->ptrace &= ~PT_SINGLESTEP;
318 child->ptrace |= PT_BLOCKSTEP;
319 child->exit_code = data;
320
321 /* Enable taken branch trap. */
322 pa_psw(child)->r = 0;
323 pa_psw(child)->t = 1;
324 pa_psw(child)->h = 0;
325 pa_psw(child)->l = 0;
326 goto out_wake;
327
328 case PTRACE_SINGLESTEP:
329 DBG("sys_ptrace(SINGLESTEP)\n");
330 ret = -EIO;
331 if ((unsigned long) data > _NSIG)
332 goto out_tsk;
333
334 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
335 child->ptrace &= ~PT_BLOCKSTEP;
336 child->ptrace |= PT_SINGLESTEP;
337 child->exit_code = data;
338
339 if (pa_psw(child)->n) {
340 struct siginfo si;
341
342 /* Nullified, just crank over the queue. */
343 task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1];
344 task_regs(child)->iasq[0] = task_regs(child)->iasq[1];
345 task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4;
346 pa_psw(child)->n = 0;
347 pa_psw(child)->x = 0;
348 pa_psw(child)->y = 0;
349 pa_psw(child)->z = 0;
350 pa_psw(child)->b = 0;
351 ptrace_disable(child);
352 /* Don't wake up the child, but let the
353 parent know something happened. */
354 si.si_code = TRAP_TRACE;
355 si.si_addr = (void __user *) (task_regs(child)->iaoq[0] & ~3);
356 si.si_signo = SIGTRAP;
357 si.si_errno = 0;
358 force_sig_info(SIGTRAP, &si, child);
359 //notify_parent(child, SIGCHLD);
360 //ret = 0;
361 goto out_wake;
362 }
363
364 /* Enable recovery counter traps. The recovery counter
365 * itself will be set to zero on a task switch. If the
366 * task is suspended on a syscall then the syscall return
367 * path will overwrite the recovery counter with a suitable
368 * value such that it traps once back in user space. We
369 * disable interrupts in the childs PSW here also, to avoid
370 * interrupts while the recovery counter is decrementing.
371 */
372 pa_psw(child)->r = 1;
373 pa_psw(child)->t = 0;
374 pa_psw(child)->h = 0;
375 pa_psw(child)->l = 0;
376 /* give it a chance to run. */
377 goto out_wake;
378
379 case PTRACE_DETACH:
380 ret = ptrace_detach(child, data);
381 goto out_tsk;
382
383 case PTRACE_GETEVENTMSG:
384 ret = put_user(child->ptrace_message, (unsigned int __user *) data);
385 goto out_tsk;
386
387 default:
388 ret = ptrace_request(child, request, addr, data);
389 goto out_tsk;
390 }
391
392out_wake_notrap:
393 ptrace_disable(child);
394out_wake:
395 wake_up_process(child);
396 ret = 0;
397out_tsk:
398 put_task_struct(child);
399out:
400 unlock_kernel();
401 DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
402 request, pid, oaddr, odata, ret);
403 return ret;
404}
405
406void syscall_trace(void)
407{
408 if (!test_thread_flag(TIF_SYSCALL_TRACE))
409 return;
410 if (!(current->ptrace & PT_PTRACED))
411 return;
412 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
413 ? 0x80 : 0));
414 /*
415 * this isn't the same as continuing with a signal, but it will do
416 * for normal use. strace only continues with a signal if the
417 * stopping signal is not SIGTRAP. -brl
418 */
419 if (current->exit_code) {
420 send_sig(current->exit_code, current, 1);
421 current->exit_code = 0;
422 }
423}
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 @@
1/*
2 *
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
8 *
9 */
10#include <asm/assembly.h>
11#include <asm/psw.h>
12
13 .section .bss
14 .export real_stack
15 .export real32_stack
16 .export real64_stack
17 .align 64
18real_stack:
19real32_stack:
20real64_stack:
21 .block 8192
22
23#ifdef __LP64__
24# define REG_SZ 8
25#else
26# define REG_SZ 4
27#endif
28
29#define N_SAVED_REGS 9
30
31save_cr_space:
32 .block REG_SZ * N_SAVED_REGS
33save_cr_end:
34
35
36/************************ 32-bit real-mode calls ***********************/
37/* This can be called in both narrow and wide kernels */
38
39 .text
40
41 .export real32_call_asm
42
43 /* unsigned long real32_call_asm(unsigned int *sp,
44 * unsigned int *arg0p,
45 * unsigned int iodc_fn)
46 * sp is value of stack pointer to adopt before calling PDC (virt)
47 * arg0p points to where saved arg values may be found
48 * iodc_fn is the IODC function to call
49 */
50
51real32_call_asm:
52 STREG %rp, -RP_OFFSET(%sp) /* save RP */
53#ifdef __LP64__
54 callee_save
55 ldo 2*REG_SZ(%sp), %sp /* room for a couple more saves */
56 STREG %r27, -1*REG_SZ(%sp)
57 STREG %r29, -2*REG_SZ(%sp)
58#endif
59 STREG %sp, -REG_SZ(%arg0) /* save SP on real-mode stack */
60 copy %arg0, %sp /* adopt the real-mode SP */
61
62 /* save iodc_fn */
63 copy %arg2, %r31
64
65 /* load up the arg registers from the saved arg area */
66 /* 32-bit calling convention passes first 4 args in registers */
67 ldw 0(%arg1), %arg0 /* note overwriting arg0 */
68 ldw -8(%arg1), %arg2
69 ldw -12(%arg1), %arg3
70 ldw -4(%arg1), %arg1 /* obviously must do this one last! */
71
72 tophys_r1 %sp
73
74 b,l rfi_virt2real,%r2
75 nop
76
77 b,l save_control_regs,%r2 /* modifies r1, r2, r28 */
78 nop
79
80#ifdef __LP64__
81 rsm PSW_SM_W, %r0 /* go narrow */
82#endif
83
84 load32 PA(ric_ret), %r2
85 bv 0(%r31)
86 nop
87ric_ret:
88#ifdef __LP64__
89 ssm PSW_SM_W, %r0 /* go wide */
90#endif
91 /* restore CRs before going virtual in case we page fault */
92 b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */
93 nop
94
95 b,l rfi_real2virt,%r2
96 nop
97
98 tovirt_r1 %sp
99 LDREG -REG_SZ(%sp), %sp /* restore SP */
100#ifdef __LP64__
101 LDREG -1*REG_SZ(%sp), %r27
102 LDREG -2*REG_SZ(%sp), %r29
103 ldo -2*REG_SZ(%sp), %sp
104 callee_rest
105#endif
106 LDREG -RP_OFFSET(%sp), %rp /* restore RP */
107 bv 0(%rp)
108 nop
109
110
111# define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where)
112# define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r
113
114 .text
115save_control_regs:
116 load32 PA(save_cr_space), %r28
117 PUSH_CR(%cr24, %r28)
118 PUSH_CR(%cr25, %r28)
119 PUSH_CR(%cr26, %r28)
120 PUSH_CR(%cr27, %r28)
121 PUSH_CR(%cr28, %r28)
122 PUSH_CR(%cr29, %r28)
123 PUSH_CR(%cr30, %r28)
124 PUSH_CR(%cr31, %r28)
125 PUSH_CR(%cr15, %r28)
126 bv 0(%r2)
127 nop
128
129restore_control_regs:
130 load32 PA(save_cr_end), %r26
131 POP_CR(%cr15, %r26)
132 POP_CR(%cr31, %r26)
133 POP_CR(%cr30, %r26)
134 POP_CR(%cr29, %r26)
135 POP_CR(%cr28, %r26)
136 POP_CR(%cr27, %r26)
137 POP_CR(%cr26, %r26)
138 POP_CR(%cr25, %r26)
139 POP_CR(%cr24, %r26)
140 bv 0(%r2)
141 nop
142
143/* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for
144 * more general-purpose use by the several places which need RFIs
145 */
146 .align 128
147 .text
148rfi_virt2real:
149 /* switch to real mode... */
150 ssm 0,0 /* See "relied upon translation" */
151 nop /* PA 2.0 Arch. F-5 */
152 nop
153 nop
154 nop
155 nop
156 nop
157 nop
158 nop
159
160 rsm (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q & I bits to load iia queue */
161 mtctl %r0, %cr17 /* Clear IIASQ tail */
162 mtctl %r0, %cr17 /* Clear IIASQ head */
163 load32 PA(rfi_v2r_1), %r1
164 mtctl %r1, %cr18 /* IIAOQ head */
165 ldo 4(%r1), %r1
166 mtctl %r1, %cr18 /* IIAOQ tail */
167 load32 REAL_MODE_PSW, %r1
168 mtctl %r1, %cr22
169 rfi
170
171 nop
172 nop
173 nop
174 nop
175 nop
176 nop
177 nop
178 nop
179rfi_v2r_1:
180 tophys_r1 %r2
181 bv 0(%r2)
182 nop
183
184 .text
185 .align 128
186rfi_real2virt:
187 ssm 0,0 /* See "relied upon translation" */
188 nop /* PA 2.0 Arch. F-5 */
189 nop
190 nop
191 nop
192 nop
193 nop
194 nop
195 nop
196
197 rsm PSW_SM_Q,%r0 /* disable Q bit to load iia queue */
198 mtctl %r0, %cr17 /* Clear IIASQ tail */
199 mtctl %r0, %cr17 /* Clear IIASQ head */
200 load32 (rfi_r2v_1), %r1
201 mtctl %r1, %cr18 /* IIAOQ head */
202 ldo 4(%r1), %r1
203 mtctl %r1, %cr18 /* IIAOQ tail */
204 load32 KERNEL_PSW, %r1
205 mtctl %r1, %cr22
206 rfi
207
208 nop
209 nop
210 nop
211 nop
212 nop
213 nop
214 nop
215 nop
216rfi_r2v_1:
217 tovirt_r1 %r2
218 bv 0(%r2)
219 nop
220
221#ifdef __LP64__
222
223/************************ 64-bit real-mode calls ***********************/
224/* This is only usable in wide kernels right now and will probably stay so */
225 .text
226 .export real64_call_asm
227 /* unsigned long real64_call_asm(unsigned long *sp,
228 * unsigned long *arg0p,
229 * unsigned long fn)
230 * sp is value of stack pointer to adopt before calling PDC (virt)
231 * arg0p points to where saved arg values may be found
232 * iodc_fn is the IODC function to call
233 */
234real64_call_asm:
235 std %rp, -0x10(%sp) /* save RP */
236 std %sp, -8(%arg0) /* save SP on real-mode stack */
237 copy %arg0, %sp /* adopt the real-mode SP */
238
239 /* save fn */
240 copy %arg2, %r31
241
242 /* set up the new ap */
243 ldo 64(%arg1), %r29
244
245 /* load up the arg registers from the saved arg area */
246 /* 32-bit calling convention passes first 4 args in registers */
247 ldd 0*REG_SZ(%arg1), %arg0 /* note overwriting arg0 */
248 ldd 2*REG_SZ(%arg1), %arg2
249 ldd 3*REG_SZ(%arg1), %arg3
250 ldd 4*REG_SZ(%arg1), %r22
251 ldd 5*REG_SZ(%arg1), %r21
252 ldd 6*REG_SZ(%arg1), %r20
253 ldd 7*REG_SZ(%arg1), %r19
254 ldd 1*REG_SZ(%arg1), %arg1 /* do this one last! */
255
256 tophys_r1 %sp
257
258 b,l rfi_virt2real,%r2
259 nop
260
261 b,l save_control_regs,%r2 /* modifies r1, r2, r28 */
262 nop
263
264 load32 PA(r64_ret), %r2
265 bv 0(%r31)
266 nop
267r64_ret:
268 /* restore CRs before going virtual in case we page fault */
269 b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */
270 nop
271
272 b,l rfi_real2virt,%r2
273 nop
274
275 tovirt_r1 %sp
276 ldd -8(%sp), %sp /* restore SP */
277 ldd -0x10(%sp), %rp /* restore RP */
278 bv 0(%rp)
279 nop
280
281#endif
282
283 .export pc_in_user_space
284 .text
285 /* Doesn't belong here but I couldn't find a nicer spot. */
286 /* Should never get called, only used by profile stuff in time.c */
287pc_in_user_space:
288 bv,n 0(%rp)
289 nop
290
291
292 .export __canonicalize_funcptr_for_compare
293 .text
294 /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html
295 ** GCC 3.3 and later has a new function in libgcc.a for
296 ** comparing function pointers.
297 */
298__canonicalize_funcptr_for_compare:
299#ifdef __LP64__
300 bve (%r2)
301#else
302 bv %r0(%r2)
303#endif
304 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 @@
1/*
2 * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard
3 */
4
5#include <linux/sched.h>
6#include <linux/spinlock.h>
7#include <linux/errno.h>
8#include <linux/init.h>
9
10/*
11 * Semaphores are complex as we wish to avoid using two variables.
12 * `count' has multiple roles, depending on its value. If it is positive
13 * or zero, there are no waiters. The functions here will never be
14 * called; see <asm/semaphore.h>
15 *
16 * When count is -1 it indicates there is at least one task waiting
17 * for the semaphore.
18 *
19 * When count is less than that, there are '- count - 1' wakeups
20 * pending. ie if it has value -3, there are 2 wakeups pending.
21 *
22 * Note that these functions are only called when there is contention
23 * on the lock, and as such all this is the "non-critical" part of the
24 * whole semaphore business. The critical part is the inline stuff in
25 * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
26 */
27void __up(struct semaphore *sem)
28{
29 sem->count--;
30 wake_up(&sem->wait);
31}
32
33#define wakers(count) (-1 - count)
34
35#define DOWN_HEAD \
36 int ret = 0; \
37 DECLARE_WAITQUEUE(wait, current); \
38 \
39 /* Note that someone is waiting */ \
40 if (sem->count == 0) \
41 sem->count = -1; \
42 \
43 /* protected by the sentry still -- use unlocked version */ \
44 wait.flags = WQ_FLAG_EXCLUSIVE; \
45 __add_wait_queue_tail(&sem->wait, &wait); \
46 lost_race: \
47 spin_unlock_irq(&sem->sentry); \
48
49#define DOWN_TAIL \
50 spin_lock_irq(&sem->sentry); \
51 if (wakers(sem->count) == 0 && ret == 0) \
52 goto lost_race; /* Someone stole our wakeup */ \
53 __remove_wait_queue(&sem->wait, &wait); \
54 current->state = TASK_RUNNING; \
55 if (!waitqueue_active(&sem->wait) && (sem->count < 0)) \
56 sem->count = wakers(sem->count);
57
58#define UPDATE_COUNT \
59 sem->count += (sem->count < 0) ? 1 : - 1;
60
61
62void __sched __down(struct semaphore * sem)
63{
64 DOWN_HEAD
65
66 for(;;) {
67 set_task_state(current, TASK_UNINTERRUPTIBLE);
68 /* we can _read_ this without the sentry */
69 if (sem->count != -1)
70 break;
71 schedule();
72 }
73
74 DOWN_TAIL
75 UPDATE_COUNT
76}
77
78int __sched __down_interruptible(struct semaphore * sem)
79{
80 DOWN_HEAD
81
82 for(;;) {
83 set_task_state(current, TASK_INTERRUPTIBLE);
84 /* we can _read_ this without the sentry */
85 if (sem->count != -1)
86 break;
87
88 if (signal_pending(current)) {
89 ret = -EINTR;
90 break;
91 }
92 schedule();
93 }
94
95 DOWN_TAIL
96
97 if (!ret) {
98 UPDATE_COUNT
99 }
100
101 return ret;
102}
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 @@
1/* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $
2 *
3 * Initial setup-routines for HP 9000 based hardware.
4 *
5 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
6 * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
7 * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
8 * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
9 * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
10 * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
11 *
12 * Initial PA-RISC Version: 04-23-1999 by Helge Deller
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 */
29
30#include <linux/config.h>
31#include <linux/kernel.h>
32#include <linux/initrd.h>
33#include <linux/init.h>
34#include <linux/console.h>
35#include <linux/seq_file.h>
36#define PCI_DEBUG
37#include <linux/pci.h>
38#undef PCI_DEBUG
39#include <linux/proc_fs.h>
40
41#include <asm/processor.h>
42#include <asm/pdc.h>
43#include <asm/led.h>
44#include <asm/machdep.h> /* for pa7300lc_init() proto */
45#include <asm/pdc_chassis.h>
46#include <asm/io.h>
47#include <asm/setup.h>
48
49char command_line[COMMAND_LINE_SIZE];
50
51/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
52struct proc_dir_entry * proc_runway_root = NULL;
53struct proc_dir_entry * proc_gsc_root = NULL;
54struct proc_dir_entry * proc_mckinley_root = NULL;
55
56#if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA))
57int parisc_bus_is_phys = 1; /* Assume no IOMMU is present */
58EXPORT_SYMBOL(parisc_bus_is_phys);
59#endif
60
61/* This sets the vmerge boundary and size, it's here because it has to
62 * be available on all platforms (zero means no-virtual merging) */
63unsigned long parisc_vmerge_boundary = 0;
64unsigned long parisc_vmerge_max_size = 0;
65
66void __init setup_cmdline(char **cmdline_p)
67{
68 extern unsigned int boot_args[];
69
70 /* Collect stuff passed in from the boot loader */
71
72 /* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */
73 if (boot_args[0] < 64) {
74 /* called from hpux boot loader */
75 saved_command_line[0] = '\0';
76 } else {
77 strcpy(saved_command_line, (char *)__va(boot_args[1]));
78
79#ifdef CONFIG_BLK_DEV_INITRD
80 if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
81 {
82 initrd_start = (unsigned long)__va(boot_args[2]);
83 initrd_end = (unsigned long)__va(boot_args[3]);
84 }
85#endif
86 }
87
88 strcpy(command_line, saved_command_line);
89 *cmdline_p = command_line;
90}
91
92#ifdef CONFIG_PA11
93void __init dma_ops_init(void)
94{
95 switch (boot_cpu_data.cpu_type) {
96 case pcx:
97 /*
98 * We've got way too many dependencies on 1.1 semantics
99 * to support 1.0 boxes at this point.
100 */
101 panic( "PA-RISC Linux currently only supports machines that conform to\n"
102 "the PA-RISC 1.1 or 2.0 architecture specification.\n");
103
104 case pcxs:
105 case pcxt:
106 hppa_dma_ops = &pcx_dma_ops;
107 break;
108 case pcxl2:
109 pa7300lc_init();
110 case pcxl: /* falls through */
111 hppa_dma_ops = &pcxl_dma_ops;
112 break;
113 default:
114 break;
115 }
116}
117#endif
118
119extern int init_per_cpu(int cpuid);
120extern void collect_boot_cpu_data(void);
121
122void __init setup_arch(char **cmdline_p)
123{
124#ifdef __LP64__
125 extern int parisc_narrow_firmware;
126#endif
127
128 init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */
129
130#ifdef __LP64__
131 printk(KERN_INFO "The 64-bit Kernel has started...\n");
132#else
133 printk(KERN_INFO "The 32-bit Kernel has started...\n");
134#endif
135
136 pdc_console_init();
137
138#ifdef __LP64__
139 if(parisc_narrow_firmware) {
140 printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
141 }
142#endif
143 setup_pdc();
144 setup_cmdline(cmdline_p);
145 collect_boot_cpu_data();
146 do_memory_inventory(); /* probe for physical memory */
147 parisc_cache_init();
148 paging_init();
149
150#ifdef CONFIG_CHASSIS_LCD_LED
151 /* initialize the LCD/LED after boot_cpu_data is available ! */
152 led_init(); /* LCD/LED initialization */
153#endif
154
155#ifdef CONFIG_PA11
156 dma_ops_init();
157#endif
158
159#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
160 conswitchp = &dummy_con; /* we use take_over_console() later ! */
161#endif
162
163}
164
165/*
166 * Display cpu info for all cpu's.
167 * for parisc this is in processor.c
168 */
169extern int show_cpuinfo (struct seq_file *m, void *v);
170
171static void *
172c_start (struct seq_file *m, loff_t *pos)
173{
174 /* Looks like the caller will call repeatedly until we return
175 * 0, signaling EOF perhaps. This could be used to sequence
176 * through CPUs for example. Since we print all cpu info in our
177 * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above)
178 * we only allow for one "position". */
179 return ((long)*pos < 1) ? (void *)1 : NULL;
180}
181
182static void *
183c_next (struct seq_file *m, void *v, loff_t *pos)
184{
185 ++*pos;
186 return c_start(m, pos);
187}
188
189static void
190c_stop (struct seq_file *m, void *v)
191{
192}
193
194struct seq_operations cpuinfo_op = {
195 .start = c_start,
196 .next = c_next,
197 .stop = c_stop,
198 .show = show_cpuinfo
199};
200
201static void __init parisc_proc_mkdir(void)
202{
203 /*
204 ** Can't call proc_mkdir() until after proc_root_init() has been
205 ** called by start_kernel(). In other words, this code can't
206 ** live in arch/.../setup.c because start_parisc() calls
207 ** start_kernel().
208 */
209 switch (boot_cpu_data.cpu_type) {
210 case pcxl:
211 case pcxl2:
212 if (NULL == proc_gsc_root)
213 {
214 proc_gsc_root = proc_mkdir("bus/gsc", NULL);
215 }
216 break;
217 case pcxt_:
218 case pcxu:
219 case pcxu_:
220 case pcxw:
221 case pcxw_:
222 case pcxw2:
223 if (NULL == proc_runway_root)
224 {
225 proc_runway_root = proc_mkdir("bus/runway", NULL);
226 }
227 break;
228 case mako:
229 if (NULL == proc_mckinley_root)
230 {
231 proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
232 }
233 break;
234 default:
235 /* FIXME: this was added to prevent the compiler
236 * complaining about missing pcx, pcxs and pcxt
237 * I'm assuming they have neither gsc nor runway */
238 break;
239 }
240}
241
242static struct resource central_bus = {
243 .name = "Central Bus",
244 .start = F_EXTEND(0xfff80000),
245 .end = F_EXTEND(0xfffaffff),
246 .flags = IORESOURCE_MEM,
247};
248
249static struct resource local_broadcast = {
250 .name = "Local Broadcast",
251 .start = F_EXTEND(0xfffb0000),
252 .end = F_EXTEND(0xfffdffff),
253 .flags = IORESOURCE_MEM,
254};
255
256static struct resource global_broadcast = {
257 .name = "Global Broadcast",
258 .start = F_EXTEND(0xfffe0000),
259 .end = F_EXTEND(0xffffffff),
260 .flags = IORESOURCE_MEM,
261};
262
263static int __init parisc_init_resources(void)
264{
265 int result;
266
267 result = request_resource(&iomem_resource, &central_bus);
268 if (result < 0) {
269 printk(KERN_ERR
270 "%s: failed to claim %s address space!\n",
271 __FILE__, central_bus.name);
272 return result;
273 }
274
275 result = request_resource(&iomem_resource, &local_broadcast);
276 if (result < 0) {
277 printk(KERN_ERR
278 "%s: failed to claim %saddress space!\n",
279 __FILE__, local_broadcast.name);
280 return result;
281 }
282
283 result = request_resource(&iomem_resource, &global_broadcast);
284 if (result < 0) {
285 printk(KERN_ERR
286 "%s: failed to claim %s address space!\n",
287 __FILE__, global_broadcast.name);
288 return result;
289 }
290
291 return 0;
292}
293
294extern void gsc_init(void);
295extern void processor_init(void);
296extern void ccio_init(void);
297extern void hppb_init(void);
298extern void dino_init(void);
299extern void iosapic_init(void);
300extern void lba_init(void);
301extern void sba_init(void);
302extern void eisa_init(void);
303
304static int __init parisc_init(void)
305{
306 parisc_proc_mkdir();
307 parisc_init_resources();
308 do_device_inventory(); /* probe for hardware */
309
310 parisc_pdc_chassis_init();
311
312 /* set up a new led state on systems shipped LED State panel */
313 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART);
314
315 processor_init();
316 printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
317 boot_cpu_data.cpu_count,
318 boot_cpu_data.cpu_name,
319 boot_cpu_data.cpu_hz / 1000000,
320 boot_cpu_data.cpu_hz % 1000000 );
321
322 parisc_setup_cache_timing();
323
324 /* These are in a non-obvious order, will fix when we have an iotree */
325#if defined(CONFIG_IOSAPIC)
326 iosapic_init();
327#endif
328#if defined(CONFIG_IOMMU_SBA)
329 sba_init();
330#endif
331#if defined(CONFIG_PCI_LBA)
332 lba_init();
333#endif
334
335 /* CCIO before any potential subdevices */
336#if defined(CONFIG_IOMMU_CCIO)
337 ccio_init();
338#endif
339
340 /*
341 * Need to register Asp & Wax before the EISA adapters for the IRQ
342 * regions. EISA must come before PCI to be sure it gets IRQ region
343 * 0.
344 */
345#if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX)
346 gsc_init();
347#endif
348#ifdef CONFIG_EISA
349 eisa_init();
350#endif
351
352#if defined(CONFIG_HPPB)
353 hppb_init();
354#endif
355
356#if defined(CONFIG_GSC_DINO)
357 dino_init();
358#endif
359
360#ifdef CONFIG_CHASSIS_LCD_LED
361 register_led_regions(); /* register LED port info in procfs */
362#endif
363
364 return 0;
365}
366
367arch_initcall(parisc_init);
368
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 @@
1/*
2 * linux/arch/parisc/kernel/signal.c: Architecture-specific signal
3 * handling support.
4 *
5 * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
6 * Copyright (C) 2000 Linuxcare, Inc.
7 *
8 * Based on the ia64, i386, and alpha versions.
9 *
10 * Like the IA-64, we are a recent enough port (we are *starting*
11 * with glibc2.2) that we do not need to support the old non-realtime
12 * Linux signals. Therefore we don't. HP/UX signals will go in
13 * arch/parisc/hpux/signal.c when we figure out how to do them.
14 */
15
16#include <linux/sched.h>
17#include <linux/mm.h>
18#include <linux/smp.h>
19#include <linux/smp_lock.h>
20#include <linux/kernel.h>
21#include <linux/signal.h>
22#include <linux/errno.h>
23#include <linux/wait.h>
24#include <linux/ptrace.h>
25#include <linux/unistd.h>
26#include <linux/stddef.h>
27#include <linux/compat.h>
28#include <linux/elf.h>
29#include <linux/personality.h>
30#include <asm/ucontext.h>
31#include <asm/rt_sigframe.h>
32#include <asm/uaccess.h>
33#include <asm/pgalloc.h>
34#include <asm/cacheflush.h>
35#include <asm/offsets.h>
36
37#ifdef CONFIG_COMPAT
38#include <linux/compat.h>
39#include "signal32.h"
40#endif
41
42#define DEBUG_SIG 0
43#define DEBUG_SIG_LEVEL 2
44
45#if DEBUG_SIG
46#define DBG(LEVEL, ...) \
47 ((DEBUG_SIG_LEVEL >= LEVEL) \
48 ? printk(__VA_ARGS__) : (void) 0)
49#else
50#define DBG(LEVEL, ...)
51#endif
52
53
54#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
55
56/* gcc will complain if a pointer is cast to an integer of different
57 * size. If you really need to do this (and we do for an ELF32 user
58 * application in an ELF64 kernel) then you have to do a cast to an
59 * integer of the same size first. The A() macro accomplishes
60 * this. */
61#define A(__x) ((unsigned long)(__x))
62
63int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
64
65/*
66 * Atomically swap in the new signal mask, and wait for a signal.
67 */
68#ifdef __LP64__
69#include "sys32.h"
70#endif
71
72asmlinkage int
73sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
74{
75 sigset_t saveset, newset;
76#ifdef __LP64__
77 compat_sigset_t newset32;
78
79 if(personality(current->personality) == PER_LINUX32){
80 /* XXX: Don't preclude handling different sized sigset_t's. */
81 if (sigsetsize != sizeof(compat_sigset_t))
82 return -EINVAL;
83 if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
84 return -EFAULT;
85 sigset_32to64(&newset,&newset32);
86
87 } else
88#endif
89 {
90 /* XXX: Don't preclude handling different sized sigset_t's. */
91 if (sigsetsize != sizeof(sigset_t))
92 return -EINVAL;
93
94 if (copy_from_user(&newset, unewset, sizeof(newset)))
95 return -EFAULT;
96 }
97
98 sigdelsetmask(&newset, ~_BLOCKABLE);
99
100 spin_lock_irq(&current->sighand->siglock);
101 saveset = current->blocked;
102 current->blocked = newset;
103 recalc_sigpending();
104 spin_unlock_irq(&current->sighand->siglock);
105
106 regs->gr[28] = -EINTR;
107 while (1) {
108 current->state = TASK_INTERRUPTIBLE;
109 schedule();
110 if (do_signal(&saveset, regs, 1))
111 return -EINTR;
112 }
113}
114
115/*
116 * Do a signal return - restore sigcontext.
117 */
118
119/* Trampoline for calling rt_sigreturn() */
120#define INSN_LDI_R25_0 0x34190000 /* ldi 0,%r25 (in_syscall=0) */
121#define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */
122#define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */
123#define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
124#define INSN_NOP 0x08000240 /* nop */
125/* For debugging */
126#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
127
128static long
129restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
130{
131 long err = 0;
132
133 err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
134 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
135 err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
136 err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
137 err |= __get_user(regs->sar, &sc->sc_sar);
138 DBG(2,"restore_sigcontext: iaoq is 0x%#lx / 0x%#lx\n",
139 regs->iaoq[0],regs->iaoq[1]);
140 DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
141 return err;
142}
143
144void
145sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
146{
147 struct rt_sigframe __user *frame;
148 struct siginfo si;
149 sigset_t set;
150 unsigned long usp = (regs->gr[30] & ~(0x01UL));
151 unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
152#ifdef __LP64__
153 compat_sigset_t compat_set;
154 struct compat_rt_sigframe __user * compat_frame;
155
156 if(personality(current->personality) == PER_LINUX32)
157 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
158#endif
159
160
161 /* Unwind the user stack to get the rt_sigframe structure. */
162 frame = (struct rt_sigframe __user *)
163 (usp - sigframe_size);
164 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
165
166#ifdef __LP64__
167 compat_frame = (struct compat_rt_sigframe __user *)frame;
168
169 if(personality(current->personality) == PER_LINUX32){
170 DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
171 if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
172 goto give_sigsegv;
173 sigset_32to64(&set,&compat_set);
174 } else
175#endif
176 {
177 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
178 goto give_sigsegv;
179 }
180
181 sigdelsetmask(&set, ~_BLOCKABLE);
182 spin_lock_irq(&current->sighand->siglock);
183 current->blocked = set;
184 recalc_sigpending();
185 spin_unlock_irq(&current->sighand->siglock);
186
187 /* Good thing we saved the old gr[30], eh? */
188#ifdef __LP64__
189 if(personality(current->personality) == PER_LINUX32){
190 DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
191 &compat_frame->uc.uc_mcontext);
192// FIXME: Load upper half from register file
193 if (restore_sigcontext32(&compat_frame->uc.uc_mcontext,
194 &compat_frame->regs, regs))
195 goto give_sigsegv;
196 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
197 usp, &compat_frame->uc.uc_stack);
198 if (do_sigaltstack32(&compat_frame->uc.uc_stack, NULL, usp) == -EFAULT)
199 goto give_sigsegv;
200 } else
201#endif
202 {
203 DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
204 &frame->uc.uc_mcontext);
205 if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
206 goto give_sigsegv;
207 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
208 usp, &frame->uc.uc_stack);
209 if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
210 goto give_sigsegv;
211 }
212
213
214
215 /* If we are on the syscall path IAOQ will not be restored, and
216 * if we are on the interrupt path we must not corrupt gr31.
217 */
218 if (in_syscall)
219 regs->gr[31] = regs->iaoq[0];
220#if DEBUG_SIG
221 DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
222 show_regs(regs);
223#endif
224 return;
225
226give_sigsegv:
227 DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
228 si.si_signo = SIGSEGV;
229 si.si_errno = 0;
230 si.si_code = SI_KERNEL;
231 si.si_pid = current->pid;
232 si.si_uid = current->uid;
233 si.si_addr = &frame->uc;
234 force_sig_info(SIGSEGV, &si, current);
235 return;
236}
237
238/*
239 * Set up a signal frame.
240 */
241
242static inline void __user *
243get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
244{
245 /*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
246 don't use the parameter it doesn't matter */
247
248 DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
249 (unsigned long)ka, sp, frame_size);
250
251 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
252 sp = current->sas_ss_sp; /* Stacks grow up! */
253
254 DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
255 return (void __user *) sp; /* Stacks grow up. Fun. */
256}
257
258static long
259setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
260
261{
262 unsigned long flags = 0;
263 long err = 0;
264
265 if (on_sig_stack((unsigned long) sc))
266 flags |= PARISC_SC_FLAG_ONSTACK;
267 if (in_syscall) {
268 flags |= PARISC_SC_FLAG_IN_SYSCALL;
269 /* regs->iaoq is undefined in the syscall return path */
270 err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
271 err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
272 err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
273 err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
274 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
275 regs->gr[31], regs->gr[31]+4);
276 } else {
277 err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
278 err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
279 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n",
280 regs->iaoq[0], regs->iaoq[1]);
281 }
282
283 err |= __put_user(flags, &sc->sc_flags);
284 err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
285 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
286 err |= __put_user(regs->sar, &sc->sc_sar);
287 DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
288
289 return err;
290}
291
292static long
293setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
294 sigset_t *set, struct pt_regs *regs, int in_syscall)
295{
296 struct rt_sigframe __user *frame;
297 unsigned long rp, usp;
298 unsigned long haddr, sigframe_size;
299 struct siginfo si;
300 int err = 0;
301#ifdef __LP64__
302 compat_int_t compat_val;
303 struct compat_rt_sigframe __user * compat_frame;
304 compat_sigset_t compat_set;
305#endif
306
307 usp = (regs->gr[30] & ~(0x01UL));
308 /*FIXME: frame_size parameter is unused, remove it. */
309 frame = get_sigframe(ka, usp, sizeof(*frame));
310
311 DBG(1,"SETUP_RT_FRAME: START\n");
312 DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
313
314
315#ifdef __LP64__
316
317 compat_frame = (struct compat_rt_sigframe __user *)frame;
318
319 if(personality(current->personality) == PER_LINUX32) {
320 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
321 err |= compat_copy_siginfo_to_user(&compat_frame->info, info);
322 DBG(1,"SETUP_RT_FRAME: 1\n");
323 compat_val = (compat_int_t)current->sas_ss_sp;
324 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
325 DBG(1,"SETUP_RT_FRAME: 2\n");
326 compat_val = (compat_int_t)current->sas_ss_size;
327 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_size);
328 DBG(1,"SETUP_RT_FRAME: 3\n");
329 compat_val = sas_ss_flags(regs->gr[30]);
330 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_flags);
331 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
332 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
333 err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
334 &compat_frame->regs, regs, in_syscall);
335 sigset_64to32(&compat_set,set);
336 err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
337 } else
338#endif
339 {
340 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
341 err |= copy_siginfo_to_user(&frame->info, info);
342 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
343 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
344 err |= __put_user(sas_ss_flags(regs->gr[30]),
345 &frame->uc.uc_stack.ss_flags);
346 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
347 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
348 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
349 /* FIXME: Should probably be converted aswell for the compat case */
350 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
351 }
352
353 if (err)
354 goto give_sigsegv;
355
356 /* Set up to return from userspace. If provided, use a stub
357 already in userspace. The first words of tramp are used to
358 save the previous sigrestartblock trampoline that might be
359 on the stack. We start the sigreturn trampoline at
360 SIGRESTARTBLOCK_TRAMP+X. */
361 err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
362 &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
363 err |= __put_user(INSN_LDI_R20,
364 &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
365 err |= __put_user(INSN_BLE_SR2_R0,
366 &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
367 err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
368
369#if DEBUG_SIG
370 /* Assert that we're flushing in the correct space... */
371 {
372 int sid;
373 asm ("mfsp %%sr3,%0" : "=r" (sid));
374 DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
375 sid, frame->tramp);
376 }
377#endif
378
379 flush_user_dcache_range((unsigned long) &frame->tramp[0],
380 (unsigned long) &frame->tramp[TRAMP_SIZE]);
381 flush_user_icache_range((unsigned long) &frame->tramp[0],
382 (unsigned long) &frame->tramp[TRAMP_SIZE]);
383
384 /* TRAMP Words 0-4, Lenght 5 = SIGRESTARTBLOCK_TRAMP
385 * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
386 * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
387 */
388 rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
389
390 if (err)
391 goto give_sigsegv;
392
393 haddr = A(ka->sa.sa_handler);
394 /* The sa_handler may be a pointer to a function descriptor */
395#ifdef __LP64__
396 if(personality(current->personality) == PER_LINUX32) {
397#endif
398 if (haddr & PA_PLABEL_FDESC) {
399 Elf32_Fdesc fdesc;
400 Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
401
402 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
403
404 if (err)
405 goto give_sigsegv;
406
407 haddr = fdesc.addr;
408 regs->gr[19] = fdesc.gp;
409 }
410#ifdef __LP64__
411 } else {
412 Elf64_Fdesc fdesc;
413 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
414
415 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
416
417 if (err)
418 goto give_sigsegv;
419
420 haddr = fdesc.addr;
421 regs->gr[19] = fdesc.gp;
422 DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
423 haddr, regs->gr[19], in_syscall);
424 }
425#endif
426
427 /* The syscall return path will create IAOQ values from r31.
428 */
429 sigframe_size = PARISC_RT_SIGFRAME_SIZE;
430#ifdef __LP64__
431 if(personality(current->personality) == PER_LINUX32)
432 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
433#endif
434 if (in_syscall) {
435 regs->gr[31] = haddr;
436#ifdef __LP64__
437 if(personality(current->personality) == PER_LINUX)
438 sigframe_size |= 1;
439#endif
440 } else {
441 unsigned long psw = USER_PSW;
442#ifdef __LP64__
443 if(personality(current->personality) == PER_LINUX)
444 psw |= PSW_W;
445#endif
446
447 /* If we are singlestepping, arrange a trap to be delivered
448 when we return to userspace. Note the semantics -- we
449 should trap before the first insn in the handler is
450 executed. Ref:
451 http://sources.redhat.com/ml/gdb/2004-11/msg00245.html
452 */
453 if (pa_psw(current)->r) {
454 pa_psw(current)->r = 0;
455 psw |= PSW_R;
456 mtctl(-1, 0);
457 }
458
459 regs->gr[0] = psw;
460 regs->iaoq[0] = haddr | 3;
461 regs->iaoq[1] = regs->iaoq[0] + 4;
462 }
463
464 regs->gr[2] = rp; /* userland return pointer */
465 regs->gr[26] = sig; /* signal number */
466
467#ifdef __LP64__
468 if(personality(current->personality) == PER_LINUX32){
469 regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
470 regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */
471 } else
472#endif
473 {
474 regs->gr[25] = A(&frame->info); /* siginfo pointer */
475 regs->gr[24] = A(&frame->uc); /* ucontext pointer */
476 }
477
478 DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
479 regs->gr[30], sigframe_size,
480 regs->gr[30] + sigframe_size);
481 /* Raise the user stack pointer to make a proper call frame. */
482 regs->gr[30] = (A(frame) + sigframe_size);
483
484
485 DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
486 current->comm, current->pid, frame, regs->gr[30],
487 regs->iaoq[0], regs->iaoq[1], rp);
488
489 return 1;
490
491give_sigsegv:
492 DBG(1,"setup_rt_frame: sending SIGSEGV\n");
493 if (sig == SIGSEGV)
494 ka->sa.sa_handler = SIG_DFL;
495 si.si_signo = SIGSEGV;
496 si.si_errno = 0;
497 si.si_code = SI_KERNEL;
498 si.si_pid = current->pid;
499 si.si_uid = current->uid;
500 si.si_addr = frame;
501 force_sig_info(SIGSEGV, &si, current);
502 return 0;
503}
504
505/*
506 * OK, we're invoking a handler.
507 */
508
509static long
510handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
511 sigset_t *oldset, struct pt_regs *regs, int in_syscall)
512{
513 DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
514 sig, ka, info, oldset, regs);
515
516 /* Set up the stack frame */
517 if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
518 return 0;
519
520 if (!(ka->sa.sa_flags & SA_NODEFER)) {
521 spin_lock_irq(&current->sighand->siglock);
522 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
523 sigaddset(&current->blocked,sig);
524 recalc_sigpending();
525 spin_unlock_irq(&current->sighand->siglock);
526 }
527 return 1;
528}
529
530/*
531 * Note that 'init' is a special process: it doesn't get signals it doesn't
532 * want to handle. Thus you cannot kill init even with a SIGKILL even by
533 * mistake.
534 *
535 * We need to be able to restore the syscall arguments (r21-r26) to
536 * restart syscalls. Thus, the syscall path should save them in the
537 * pt_regs structure (it's okay to do so since they are caller-save
538 * registers). As noted below, the syscall number gets restored for
539 * us due to the magic of delayed branching.
540 */
541
542asmlinkage int
543do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
544{
545 siginfo_t info;
546 struct k_sigaction ka;
547 int signr;
548
549 DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
550 oldset, regs, regs->sr[7], in_syscall);
551
552 /* Everyone else checks to see if they are in kernel mode at
553 this point and exits if that's the case. I'm not sure why
554 we would be called in that case, but for some reason we
555 are. */
556
557 if (!oldset)
558 oldset = &current->blocked;
559
560 DBG(1,"do_signal: oldset %08lx / %08lx\n",
561 oldset->sig[0], oldset->sig[1]);
562
563
564 /* May need to force signal if handle_signal failed to deliver */
565 while (1) {
566
567 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
568 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
569
570 if (signr <= 0)
571 break;
572
573 /* Restart a system call if necessary. */
574 if (in_syscall) {
575 /* Check the return code */
576 switch (regs->gr[28]) {
577 case -ERESTART_RESTARTBLOCK:
578 current_thread_info()->restart_block.fn = do_no_restart_syscall;
579 case -ERESTARTNOHAND:
580 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
581 regs->gr[28] = -EINTR;
582 break;
583
584 case -ERESTARTSYS:
585 if (!(ka.sa.sa_flags & SA_RESTART)) {
586 DBG(1,"ERESTARTSYS: putting -EINTR\n");
587 regs->gr[28] = -EINTR;
588 break;
589 }
590 /* fallthrough */
591 case -ERESTARTNOINTR:
592 /* A syscall is just a branch, so all
593 we have to do is fiddle the return pointer. */
594 regs->gr[31] -= 8; /* delayed branching */
595 /* Preserve original r28. */
596 regs->gr[28] = regs->orig_r28;
597 break;
598 }
599 }
600 /* Whee! Actually deliver the signal. If the
601 delivery failed, we need to continue to iterate in
602 this loop so we can deliver the SIGSEGV... */
603 if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) {
604 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
605 regs->gr[28]);
606 return 1;
607 }
608 }
609 /* end of while(1) looping forever if we can't force a signal */
610
611 /* Did we come from a system call? */
612 if (in_syscall) {
613 /* Restart the system call - no handlers present */
614 if (regs->gr[28] == -ERESTART_RESTARTBLOCK) {
615 unsigned int *usp = (unsigned int *)regs->gr[30];
616
617 /* Setup a trampoline to restart the syscall
618 * with __NR_restart_syscall
619 *
620 * 0: <return address (orig r31)>
621 * 4: <2nd half for 64-bit>
622 * 8: ldw 0(%sp), %r31
623 * 12: be 0x100(%sr2, %r0)
624 * 16: ldi __NR_restart_syscall, %r20
625 */
626#ifndef __LP64__
627 put_user(regs->gr[31], &usp[0]);
628 put_user(0x0fc0109f, &usp[2]);
629#else
630 put_user(regs->gr[31] >> 32, &usp[0]);
631 put_user(regs->gr[31] & 0xffffffff, &usp[1]);
632 put_user(0x0fc010df, &usp[2]);
633#endif
634 put_user(0xe0008200, &usp[3]);
635 put_user(0x34140000, &usp[4]);
636
637 /* Stack is 64-byte aligned, and we only
638 * need to flush 1 cache line */
639 asm("fdc 0(%%sr3, %0)\n"
640 "fic 0(%%sr3, %0)\n"
641 "sync\n"
642 : : "r"(regs->gr[30]));
643
644 regs->gr[31] = regs->gr[30] + 8;
645 /* Preserve original r28. */
646 regs->gr[28] = regs->orig_r28;
647 } else if (regs->gr[28] == -ERESTARTNOHAND ||
648 regs->gr[28] == -ERESTARTSYS ||
649 regs->gr[28] == -ERESTARTNOINTR) {
650 /* Hooray for delayed branching. We don't
651 have to restore %r20 (the system call
652 number) because it gets loaded in the delay
653 slot of the branch external instruction. */
654 regs->gr[31] -= 8;
655 /* Preserve original r28. */
656 regs->gr[28] = regs->orig_r28;
657 }
658 }
659
660 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
661 regs->gr[28]);
662
663 return 0;
664}
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 @@
1/* Signal support for 32-bit kernel builds
2 *
3 * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
4 * Code was mostly borrowed from kernel/signal.c.
5 * See kernel/signal.c for additional Copyrights.
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/compat.h>
24#include <linux/slab.h>
25#include <linux/module.h>
26#include <linux/unistd.h>
27#include <linux/smp_lock.h>
28#include <linux/init.h>
29#include <linux/sched.h>
30#include <linux/syscalls.h>
31#include <linux/types.h>
32#include <linux/errno.h>
33
34#include <asm/compat_signal.h>
35#include <asm/uaccess.h>
36
37#include "signal32.h"
38#include "sys32.h"
39
40#define DEBUG_COMPAT_SIG 0
41#define DEBUG_COMPAT_SIG_LEVEL 2
42
43#if DEBUG_COMPAT_SIG
44#define DBG(LEVEL, ...) \
45 ((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
46 ? printk(__VA_ARGS__) : (void) 0)
47#else
48#define DBG(LEVEL, ...)
49#endif
50
51#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
52
53inline void
54sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
55{
56 s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
57}
58
59inline void
60sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
61{
62 s32->sig[0] = s64->sig[0] & 0xffffffffUL;
63 s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
64}
65
66static int
67put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
68{
69 compat_sigset_t s;
70
71 if (sz != sizeof *set) panic("put_sigset32()");
72 sigset_64to32(&s, set);
73
74 return copy_to_user(up, &s, sizeof s);
75}
76
77static int
78get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
79{
80 compat_sigset_t s;
81 int r;
82
83 if (sz != sizeof *set) panic("put_sigset32()");
84
85 if ((r = copy_from_user(&s, up, sz)) == 0) {
86 sigset_32to64(set, &s);
87 }
88
89 return r;
90}
91
92int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
93 unsigned int sigsetsize)
94{
95 sigset_t old_set, new_set;
96 int ret;
97
98 if (set && get_sigset32(set, &new_set, sigsetsize))
99 return -EFAULT;
100
101 KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL,
102 oset ? (sigset_t __user *)&old_set : NULL, sigsetsize);
103
104 if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
105 return -EFAULT;
106
107 return ret;
108}
109
110
111int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize)
112{
113 int ret;
114 sigset_t set;
115
116 KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize);
117
118 if (!ret && put_sigset32(uset, &set, sigsetsize))
119 return -EFAULT;
120
121 return ret;
122}
123
124long
125sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact,
126 size_t sigsetsize)
127{
128 struct k_sigaction32 new_sa32, old_sa32;
129 struct k_sigaction new_sa, old_sa;
130 int ret = -EINVAL;
131
132 if (act) {
133 if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
134 return -EFAULT;
135 new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
136 new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
137 sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
138 }
139
140 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
141
142 if (!ret && oact) {
143 sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
144 old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
145 old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
146 if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
147 return -EFAULT;
148 }
149 return ret;
150}
151
152int
153do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp)
154{
155 compat_stack_t ss32, oss32;
156 stack_t ss, oss;
157 stack_t *ssp = NULL, *ossp = NULL;
158 int ret;
159
160 if (uss32) {
161 if (copy_from_user(&ss32, uss32, sizeof ss32))
162 return -EFAULT;
163
164 ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp;
165 ss.ss_flags = ss32.ss_flags;
166 ss.ss_size = ss32.ss_size;
167
168 ssp = &ss;
169 }
170
171 if (uoss32)
172 ossp = &oss;
173
174 KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp);
175
176 if (!ret && uoss32) {
177 oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
178 oss32.ss_flags = oss.ss_flags;
179 oss32.ss_size = oss.ss_size;
180 if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
181 return -EFAULT;
182 }
183
184 return ret;
185}
186
187long
188restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
189 struct pt_regs *regs)
190{
191 long err = 0;
192 compat_uint_t compat_reg;
193 compat_uint_t compat_regt;
194 int regn;
195
196 /* When loading 32-bit values into 64-bit registers make
197 sure to clear the upper 32-bits */
198 DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
199 DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
200 DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
201 for(regn=0; regn < 32; regn++){
202 err |= __get_user(compat_reg,&sc->sc_gr[regn]);
203 regs->gr[regn] = compat_reg;
204 /* Load upper half */
205 err |= __get_user(compat_regt,&rf->rf_gr[regn]);
206 regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
207 DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n",
208 regn, regs->gr[regn], compat_regt, compat_reg);
209 }
210 DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
211 /* XXX: BE WARNED FR's are 64-BIT! */
212 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
213
214 /* Better safe than sorry, pass __get_user two things of
215 the same size and let gcc do the upward conversion to
216 64-bits */
217 err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
218 /* Load upper half */
219 err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
220 regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
221 DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
222 DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n",
223 &sc->sc_iaoq[0], compat_reg);
224
225 err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
226 /* Load upper half */
227 err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
228 regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
229 DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
230 DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n",
231 &sc->sc_iaoq[1],compat_reg);
232 DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n",
233 regs->iaoq[0],regs->iaoq[1]);
234
235 err |= __get_user(compat_reg, &sc->sc_iasq[0]);
236 /* Load the upper half for iasq */
237 err |= __get_user(compat_regt, &rf->rf_iasq[0]);
238 regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
239 DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
240
241 err |= __get_user(compat_reg, &sc->sc_iasq[1]);
242 /* Load the upper half for iasq */
243 err |= __get_user(compat_regt, &rf->rf_iasq[1]);
244 regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
245 DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
246 DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n",
247 regs->iasq[0],regs->iasq[1]);
248
249 err |= __get_user(compat_reg, &sc->sc_sar);
250 /* Load the upper half for sar */
251 err |= __get_user(compat_regt, &rf->rf_sar);
252 regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;
253 DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);
254 DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);
255 DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
256
257 return err;
258}
259
260/*
261 * Set up the sigcontext structure for this process.
262 * This is not an easy task if the kernel is 64-bit, it will require
263 * that we examine the process personality to determine if we need to
264 * truncate for a 32-bit userspace.
265 */
266long
267setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
268 struct pt_regs *regs, int in_syscall)
269{
270 compat_int_t flags = 0;
271 long err = 0;
272 compat_uint_t compat_reg;
273 compat_uint_t compat_regb;
274 int regn;
275
276 if (on_sig_stack((unsigned long) sc))
277 flags |= PARISC_SC_FLAG_ONSTACK;
278
279 if (in_syscall) {
280
281 DBG(1,"setup_sigcontext32: in_syscall\n");
282
283 flags |= PARISC_SC_FLAG_IN_SYSCALL;
284 /* Truncate gr31 */
285 compat_reg = (compat_uint_t)(regs->gr[31]);
286 /* regs->iaoq is undefined in the syscall return path */
287 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
288 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
289 &sc->sc_iaoq[0], compat_reg);
290
291 /* Store upper half */
292 compat_reg = (compat_uint_t)(regs->gr[32] >> 32);
293 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
294 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
295
296
297 compat_reg = (compat_uint_t)(regs->gr[31]+4);
298 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
299 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
300 &sc->sc_iaoq[1], compat_reg);
301 /* Store upper half */
302 compat_reg = (compat_uint_t)((regs->gr[32]+4) >> 32);
303 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
304 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
305
306 /* Truncate sr3 */
307 compat_reg = (compat_uint_t)(regs->sr[3]);
308 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
309 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
310
311 /* Store upper half */
312 compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
313 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
314 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
315
316 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
317 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
318 DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",
319 regs->gr[31], regs->gr[31]+4);
320
321 } else {
322
323 compat_reg = (compat_uint_t)(regs->iaoq[0]);
324 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
325 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
326 &sc->sc_iaoq[0], compat_reg);
327 /* Store upper half */
328 compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
329 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
330 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
331
332 compat_reg = (compat_uint_t)(regs->iaoq[1]);
333 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
334 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
335 &sc->sc_iaoq[1], compat_reg);
336 /* Store upper half */
337 compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
338 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
339 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
340
341
342 compat_reg = (compat_uint_t)(regs->iasq[0]);
343 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
344 DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
345 &sc->sc_iasq[0], compat_reg);
346 /* Store upper half */
347 compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
348 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
349 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
350
351
352 compat_reg = (compat_uint_t)(regs->iasq[1]);
353 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
354 DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
355 &sc->sc_iasq[1], compat_reg);
356 /* Store upper half */
357 compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
358 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
359 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
360
361 /* Print out the IAOQ for debugging */
362 DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n",
363 regs->iaoq[0], regs->iaoq[1]);
364 }
365
366 err |= __put_user(flags, &sc->sc_flags);
367
368 DBG(1,"setup_sigcontext32: Truncating general registers.\n");
369
370 for(regn=0; regn < 32; regn++){
371 /* Truncate a general register */
372 compat_reg = (compat_uint_t)(regs->gr[regn]);
373 err |= __put_user(compat_reg, &sc->sc_gr[regn]);
374 /* Store upper half */
375 compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
376 err |= __put_user(compat_regb, &rf->rf_gr[regn]);
377
378 /* DEBUG: Write out the "upper / lower" register data */
379 DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn,
380 compat_regb, compat_reg);
381 }
382
383 /* Copy the floating point registers (same size)
384 XXX: BE WARNED FR's are 64-BIT! */
385 DBG(1,"setup_sigcontext32: Copying from regs to sc, "
386 "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
387 sizeof(regs->fr), sizeof(sc->sc_fr));
388 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
389
390 compat_reg = (compat_uint_t)(regs->sar);
391 err |= __put_user(compat_reg, &sc->sc_sar);
392 DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
393 /* Store upper half */
394 compat_reg = (compat_uint_t)(regs->sar >> 32);
395 err |= __put_user(compat_reg, &rf->rf_sar);
396 DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
397 DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
398
399 return err;
400}
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 @@
1/*
2 * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
3 * Copyright (C) 2003 Carlos O'Donell <carlos at parisc-linux.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#ifndef _PARISC64_KERNEL_SIGNAL32_H
20#define _PARISC64_KERNEL_SIGNAL32_H
21
22#include <linux/compat.h>
23#include <asm/compat_signal.h>
24#include <asm/compat_rt_sigframe.h>
25
26/* ELF32 signal handling */
27
28struct k_sigaction32 {
29 struct compat_sigaction sa;
30};
31
32void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
33void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
34int do_sigaltstack32 (const compat_stack_t __user *uss32,
35 compat_stack_t __user *uoss32, unsigned long sp);
36long restore_sigcontext32(struct compat_sigcontext __user *sc,
37 struct compat_regfile __user *rf,
38 struct pt_regs *regs);
39long setup_sigcontext32(struct compat_sigcontext __user *sc,
40 struct compat_regfile __user *rf,
41 struct pt_regs *regs, int in_syscall);
42
43#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 @@
1/*
2** SMP Support
3**
4** Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
5** Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
6** Copyright (C) 2001,2004 Grant Grundler <grundler@parisc-linux.org>
7**
8** Lots of stuff stolen from arch/alpha/kernel/smp.c
9** ...and then parisc stole from arch/ia64/kernel/smp.c. Thanks David! :^)
10**
11** Thanks to John Curry and Ullas Ponnadi. I learned alot from their work.
12** -grant (1/12/2001)
13**
14** This program is free software; you can redistribute it and/or modify
15** it under the terms of the GNU General Public License as published by
16** the Free Software Foundation; either version 2 of the License, or
17** (at your option) any later version.
18*/
19#undef ENTRY_SYS_CPUS /* syscall support for iCOD-like functionality */
20
21#include <linux/autoconf.h>
22
23#include <linux/types.h>
24#include <linux/spinlock.h>
25#include <linux/slab.h>
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/sched.h>
30#include <linux/init.h>
31#include <linux/interrupt.h>
32#include <linux/smp.h>
33#include <linux/kernel_stat.h>
34#include <linux/mm.h>
35#include <linux/delay.h>
36#include <linux/bitops.h>
37
38#include <asm/system.h>
39#include <asm/atomic.h>
40#include <asm/current.h>
41#include <asm/delay.h>
42#include <asm/pgalloc.h> /* for flush_tlb_all() proto/macro */
43
44#include <asm/io.h>
45#include <asm/irq.h> /* for CPU_IRQ_REGION and friends */
46#include <asm/mmu_context.h>
47#include <asm/page.h>
48#include <asm/pgtable.h>
49#include <asm/pgalloc.h>
50#include <asm/processor.h>
51#include <asm/ptrace.h>
52#include <asm/unistd.h>
53#include <asm/cacheflush.h>
54
55#define kDEBUG 0
56
57DEFINE_SPINLOCK(smp_lock);
58
59volatile struct task_struct *smp_init_current_idle_task;
60
61static volatile int cpu_now_booting = 0; /* track which CPU is booting */
62
63static int parisc_max_cpus = 1;
64
65/* online cpus are ones that we've managed to bring up completely
66 * possible cpus are all valid cpu
67 * present cpus are all detected cpu
68 *
69 * On startup we bring up the "possible" cpus. Since we discover
70 * CPUs later, we add them as hotplug, so the possible cpu mask is
71 * empty in the beginning.
72 */
73
74cpumask_t cpu_online_map = CPU_MASK_NONE; /* Bitmap of online CPUs */
75cpumask_t cpu_possible_map = CPU_MASK_ALL; /* Bitmap of Present CPUs */
76
77EXPORT_SYMBOL(cpu_online_map);
78EXPORT_SYMBOL(cpu_possible_map);
79
80
81struct smp_call_struct {
82 void (*func) (void *info);
83 void *info;
84 long wait;
85 atomic_t unstarted_count;
86 atomic_t unfinished_count;
87};
88static volatile struct smp_call_struct *smp_call_function_data;
89
90enum ipi_message_type {
91 IPI_NOP=0,
92 IPI_RESCHEDULE=1,
93 IPI_CALL_FUNC,
94 IPI_CPU_START,
95 IPI_CPU_STOP,
96 IPI_CPU_TEST
97};
98
99
100/********** SMP inter processor interrupt and communication routines */
101
102#undef PER_CPU_IRQ_REGION
103#ifdef PER_CPU_IRQ_REGION
104/* XXX REVISIT Ignore for now.
105** *May* need this "hook" to register IPI handler
106** once we have perCPU ExtIntr switch tables.
107*/
108static void
109ipi_init(int cpuid)
110{
111
112 /* If CPU is present ... */
113#ifdef ENTRY_SYS_CPUS
114 /* *and* running (not stopped) ... */
115#error iCOD support wants state checked here.
116#endif
117
118#error verify IRQ_OFFSET(IPI_IRQ) is ipi_interrupt() in new IRQ region
119
120 if(cpu_online(cpuid) )
121 {
122 switch_to_idle_task(current);
123 }
124
125 return;
126}
127#endif
128
129
130/*
131** Yoink this CPU from the runnable list...
132**
133*/
134static void
135halt_processor(void)
136{
137#ifdef ENTRY_SYS_CPUS
138#error halt_processor() needs rework
139/*
140** o migrate I/O interrupts off this CPU.
141** o leave IPI enabled - __cli() will disable IPI.
142** o leave CPU in online map - just change the state
143*/
144 cpu_data[this_cpu].state = STATE_STOPPED;
145 mark_bh(IPI_BH);
146#else
147 /* REVISIT : redirect I/O Interrupts to another CPU? */
148 /* REVISIT : does PM *know* this CPU isn't available? */
149 cpu_clear(smp_processor_id(), cpu_online_map);
150 local_irq_disable();
151 for (;;)
152 ;
153#endif
154}
155
156
157irqreturn_t
158ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
159{
160 int this_cpu = smp_processor_id();
161 struct cpuinfo_parisc *p = &cpu_data[this_cpu];
162 unsigned long ops;
163 unsigned long flags;
164
165 /* Count this now; we may make a call that never returns. */
166 p->ipi_count++;
167
168 mb(); /* Order interrupt and bit testing. */
169
170 for (;;) {
171 spin_lock_irqsave(&(p->lock),flags);
172 ops = p->pending_ipi;
173 p->pending_ipi = 0;
174 spin_unlock_irqrestore(&(p->lock),flags);
175
176 mb(); /* Order bit clearing and data access. */
177
178 if (!ops)
179 break;
180
181 while (ops) {
182 unsigned long which = ffz(~ops);
183
184 switch (which) {
185 case IPI_RESCHEDULE:
186#if (kDEBUG>=100)
187 printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu);
188#endif /* kDEBUG */
189 ops &= ~(1 << IPI_RESCHEDULE);
190 /*
191 * Reschedule callback. Everything to be
192 * done is done by the interrupt return path.
193 */
194 break;
195
196 case IPI_CALL_FUNC:
197#if (kDEBUG>=100)
198 printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu);
199#endif /* kDEBUG */
200 ops &= ~(1 << IPI_CALL_FUNC);
201 {
202 volatile struct smp_call_struct *data;
203 void (*func)(void *info);
204 void *info;
205 int wait;
206
207 data = smp_call_function_data;
208 func = data->func;
209 info = data->info;
210 wait = data->wait;
211
212 mb();
213 atomic_dec ((atomic_t *)&data->unstarted_count);
214
215 /* At this point, *data can't
216 * be relied upon.
217 */
218
219 (*func)(info);
220
221 /* Notify the sending CPU that the
222 * task is done.
223 */
224 mb();
225 if (wait)
226 atomic_dec ((atomic_t *)&data->unfinished_count);
227 }
228 break;
229
230 case IPI_CPU_START:
231#if (kDEBUG>=100)
232 printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu);
233#endif /* kDEBUG */
234 ops &= ~(1 << IPI_CPU_START);
235#ifdef ENTRY_SYS_CPUS
236 p->state = STATE_RUNNING;
237#endif
238 break;
239
240 case IPI_CPU_STOP:
241#if (kDEBUG>=100)
242 printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu);
243#endif /* kDEBUG */
244 ops &= ~(1 << IPI_CPU_STOP);
245#ifdef ENTRY_SYS_CPUS
246#else
247 halt_processor();
248#endif
249 break;
250
251 case IPI_CPU_TEST:
252#if (kDEBUG>=100)
253 printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu);
254#endif /* kDEBUG */
255 ops &= ~(1 << IPI_CPU_TEST);
256 break;
257
258 default:
259 printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n",
260 this_cpu, which);
261 ops &= ~(1 << which);
262 return IRQ_NONE;
263 } /* Switch */
264 } /* while (ops) */
265 }
266 return IRQ_HANDLED;
267}
268
269
270static inline void
271ipi_send(int cpu, enum ipi_message_type op)
272{
273 struct cpuinfo_parisc *p = &cpu_data[cpu];
274 unsigned long flags;
275
276 spin_lock_irqsave(&(p->lock),flags);
277 p->pending_ipi |= 1 << op;
278 gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa);
279 spin_unlock_irqrestore(&(p->lock),flags);
280}
281
282
283static inline void
284send_IPI_single(int dest_cpu, enum ipi_message_type op)
285{
286 if (dest_cpu == NO_PROC_ID) {
287 BUG();
288 return;
289 }
290
291 ipi_send(dest_cpu, op);
292}
293
294static inline void
295send_IPI_allbutself(enum ipi_message_type op)
296{
297 int i;
298
299 for (i = 0; i < NR_CPUS; i++) {
300 if (cpu_online(i) && i != smp_processor_id())
301 send_IPI_single(i, op);
302 }
303}
304
305
306inline void
307smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); }
308
309static inline void
310smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); }
311
312void
313smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); }
314
315
316/**
317 * Run a function on all other CPUs.
318 * <func> The function to run. This must be fast and non-blocking.
319 * <info> An arbitrary pointer to pass to the function.
320 * <retry> If true, keep retrying until ready.
321 * <wait> If true, wait until function has completed on other CPUs.
322 * [RETURNS] 0 on success, else a negative status code.
323 *
324 * Does not return until remote CPUs are nearly ready to execute <func>
325 * or have executed.
326 */
327
328int
329smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
330{
331 struct smp_call_struct data;
332 unsigned long timeout;
333 static DEFINE_SPINLOCK(lock);
334 int retries = 0;
335
336 if (num_online_cpus() < 2)
337 return 0;
338
339 /* Can deadlock when called with interrupts disabled */
340 WARN_ON(irqs_disabled());
341
342 data.func = func;
343 data.info = info;
344 data.wait = wait;
345 atomic_set(&data.unstarted_count, num_online_cpus() - 1);
346 atomic_set(&data.unfinished_count, num_online_cpus() - 1);
347
348 if (retry) {
349 spin_lock (&lock);
350 while (smp_call_function_data != 0)
351 barrier();
352 }
353 else {
354 spin_lock (&lock);
355 if (smp_call_function_data) {
356 spin_unlock (&lock);
357 return -EBUSY;
358 }
359 }
360
361 smp_call_function_data = &data;
362 spin_unlock (&lock);
363
364 /* Send a message to all other CPUs and wait for them to respond */
365 send_IPI_allbutself(IPI_CALL_FUNC);
366
367 retry:
368 /* Wait for response */
369 timeout = jiffies + HZ;
370 while ( (atomic_read (&data.unstarted_count) > 0) &&
371 time_before (jiffies, timeout) )
372 barrier ();
373
374 if (atomic_read (&data.unstarted_count) > 0) {
375 printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d), try %d\n",
376 smp_processor_id(), ++retries);
377 goto retry;
378 }
379 /* We either got one or timed out. Release the lock */
380
381 mb();
382 smp_call_function_data = NULL;
383
384 while (wait && atomic_read (&data.unfinished_count) > 0)
385 barrier ();
386
387 return 0;
388}
389
390EXPORT_SYMBOL(smp_call_function);
391
392/*
393 * Flush all other CPU's tlb and then mine. Do this with on_each_cpu()
394 * as we want to ensure all TLB's flushed before proceeding.
395 */
396
397extern void flush_tlb_all_local(void);
398
399void
400smp_flush_tlb_all(void)
401{
402 on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
403}
404
405
406void
407smp_do_timer(struct pt_regs *regs)
408{
409 int cpu = smp_processor_id();
410 struct cpuinfo_parisc *data = &cpu_data[cpu];
411
412 if (!--data->prof_counter) {
413 data->prof_counter = data->prof_multiplier;
414 update_process_times(user_mode(regs));
415 }
416}
417
418/*
419 * Called by secondaries to update state and initialize CPU registers.
420 */
421static void __init
422smp_cpu_init(int cpunum)
423{
424 extern int init_per_cpu(int); /* arch/parisc/kernel/setup.c */
425 extern void init_IRQ(void); /* arch/parisc/kernel/irq.c */
426
427 /* Set modes and Enable floating point coprocessor */
428 (void) init_per_cpu(cpunum);
429
430 disable_sr_hashing();
431
432 mb();
433
434 /* Well, support 2.4 linux scheme as well. */
435 if (cpu_test_and_set(cpunum, cpu_online_map))
436 {
437 extern void machine_halt(void); /* arch/parisc.../process.c */
438
439 printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum);
440 machine_halt();
441 }
442
443 /* Initialise the idle task for this CPU */
444 atomic_inc(&init_mm.mm_count);
445 current->active_mm = &init_mm;
446 if(current->mm)
447 BUG();
448 enter_lazy_tlb(&init_mm, current);
449
450 init_IRQ(); /* make sure no IRQ's are enabled or pending */
451}
452
453
454/*
455 * Slaves start using C here. Indirectly called from smp_slave_stext.
456 * Do what start_kernel() and main() do for boot strap processor (aka monarch)
457 */
458void __init smp_callin(void)
459{
460 int slave_id = cpu_now_booting;
461#if 0
462 void *istack;
463#endif
464
465 smp_cpu_init(slave_id);
466
467#if 0 /* NOT WORKING YET - see entry.S */
468 istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER);
469 if (istack == NULL) {
470 printk(KERN_CRIT "Failed to allocate interrupt stack for cpu %d\n",slave_id);
471 BUG();
472 }
473 mtctl(istack,31);
474#endif
475
476 flush_cache_all_local(); /* start with known state */
477 flush_tlb_all_local();
478
479 local_irq_enable(); /* Interrupts have been off until now */
480
481 cpu_idle(); /* Wait for timer to schedule some work */
482
483 /* NOTREACHED */
484 panic("smp_callin() AAAAaaaaahhhh....\n");
485}
486
487/*
488 * Bring one cpu online.
489 */
490int __init smp_boot_one_cpu(int cpuid)
491{
492 struct task_struct *idle;
493 long timeout;
494
495 /*
496 * Create an idle task for this CPU. Note the address wed* give
497 * to kernel_thread is irrelevant -- it's going to start
498 * where OS_BOOT_RENDEVZ vector in SAL says to start. But
499 * this gets all the other task-y sort of data structures set
500 * up like we wish. We need to pull the just created idle task
501 * off the run queue and stuff it into the init_tasks[] array.
502 * Sheesh . . .
503 */
504
505 idle = fork_idle(cpuid);
506 if (IS_ERR(idle))
507 panic("SMP: fork failed for CPU:%d", cpuid);
508
509 idle->thread_info->cpu = cpuid;
510
511 /* Let _start know what logical CPU we're booting
512 ** (offset into init_tasks[],cpu_data[])
513 */
514 cpu_now_booting = cpuid;
515
516 /*
517 ** boot strap code needs to know the task address since
518 ** it also contains the process stack.
519 */
520 smp_init_current_idle_task = idle ;
521 mb();
522
523 printk("Releasing cpu %d now, hpa=%lx\n", cpuid, cpu_data[cpuid].hpa);
524
525 /*
526 ** This gets PDC to release the CPU from a very tight loop.
527 **
528 ** From the PA-RISC 2.0 Firmware Architecture Reference Specification:
529 ** "The MEM_RENDEZ vector specifies the location of OS_RENDEZ which
530 ** is executed after receiving the rendezvous signal (an interrupt to
531 ** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the
532 ** contents of memory are valid."
533 */
534 gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, cpu_data[cpuid].hpa);
535 mb();
536
537 /*
538 * OK, wait a bit for that CPU to finish staggering about.
539 * Slave will set a bit when it reaches smp_cpu_init().
540 * Once the "monarch CPU" sees the bit change, it can move on.
541 */
542 for (timeout = 0; timeout < 10000; timeout++) {
543 if(cpu_online(cpuid)) {
544 /* Which implies Slave has started up */
545 cpu_now_booting = 0;
546 smp_init_current_idle_task = NULL;
547 goto alive ;
548 }
549 udelay(100);
550 barrier();
551 }
552
553 put_task_struct(idle);
554 idle = NULL;
555
556 printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);
557 return -1;
558
559alive:
560 /* Remember the Slave data */
561#if (kDEBUG>=100)
562 printk(KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n",
563 cpuid, timeout * 100);
564#endif /* kDEBUG */
565#ifdef ENTRY_SYS_CPUS
566 cpu_data[cpuid].state = STATE_RUNNING;
567#endif
568 return 0;
569}
570
571void __devinit smp_prepare_boot_cpu(void)
572{
573 int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */
574
575#ifdef ENTRY_SYS_CPUS
576 cpu_data[0].state = STATE_RUNNING;
577#endif
578
579 /* Setup BSP mappings */
580 printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor);
581
582 cpu_set(bootstrap_processor, cpu_online_map);
583 cpu_set(bootstrap_processor, cpu_present_map);
584}
585
586
587
588/*
589** inventory.c:do_inventory() hasn't yet been run and thus we
590** don't 'discover' the additional CPU's until later.
591*/
592void __init smp_prepare_cpus(unsigned int max_cpus)
593{
594 cpus_clear(cpu_present_map);
595 cpu_set(0, cpu_present_map);
596
597 parisc_max_cpus = max_cpus;
598 if (!max_cpus)
599 printk(KERN_INFO "SMP mode deactivated.\n");
600}
601
602
603void smp_cpus_done(unsigned int cpu_max)
604{
605 return;
606}
607
608
609int __devinit __cpu_up(unsigned int cpu)
610{
611 if (cpu != 0 && cpu < parisc_max_cpus)
612 smp_boot_one_cpu(cpu);
613
614 return cpu_online(cpu) ? 0 : -ENOSYS;
615}
616
617
618
619#ifdef ENTRY_SYS_CPUS
620/* Code goes along with:
621** entry.s: ENTRY_NAME(sys_cpus) / * 215, for cpu stat * /
622*/
623int sys_cpus(int argc, char **argv)
624{
625 int i,j=0;
626 extern int current_pid(int cpu);
627
628 if( argc > 2 ) {
629 printk("sys_cpus:Only one argument supported\n");
630 return (-1);
631 }
632 if ( argc == 1 ){
633
634#ifdef DUMP_MORE_STATE
635 for(i=0; i<NR_CPUS; i++) {
636 int cpus_per_line = 4;
637 if(cpu_online(i)) {
638 if (j++ % cpus_per_line)
639 printk(" %3d",i);
640 else
641 printk("\n %3d",i);
642 }
643 }
644 printk("\n");
645#else
646 printk("\n 0\n");
647#endif
648 } else if((argc==2) && !(strcmp(argv[1],"-l"))) {
649 printk("\nCPUSTATE TASK CPUNUM CPUID HARDCPU(HPA)\n");
650#ifdef DUMP_MORE_STATE
651 for(i=0;i<NR_CPUS;i++) {
652 if (!cpu_online(i))
653 continue;
654 if (cpu_data[i].cpuid != NO_PROC_ID) {
655 switch(cpu_data[i].state) {
656 case STATE_RENDEZVOUS:
657 printk("RENDEZVS ");
658 break;
659 case STATE_RUNNING:
660 printk((current_pid(i)!=0) ? "RUNNING " : "IDLING ");
661 break;
662 case STATE_STOPPED:
663 printk("STOPPED ");
664 break;
665 case STATE_HALTED:
666 printk("HALTED ");
667 break;
668 default:
669 printk("%08x?", cpu_data[i].state);
670 break;
671 }
672 if(cpu_online(i)) {
673 printk(" %4d",current_pid(i));
674 }
675 printk(" %6d",cpu_number_map(i));
676 printk(" %5d",i);
677 printk(" 0x%lx\n",cpu_data[i].hpa);
678 }
679 }
680#else
681 printk("\n%s %4d 0 0 --------",
682 (current->pid)?"RUNNING ": "IDLING ",current->pid);
683#endif
684 } else if ((argc==2) && !(strcmp(argv[1],"-s"))) {
685#ifdef DUMP_MORE_STATE
686 printk("\nCPUSTATE CPUID\n");
687 for (i=0;i<NR_CPUS;i++) {
688 if (!cpu_online(i))
689 continue;
690 if (cpu_data[i].cpuid != NO_PROC_ID) {
691 switch(cpu_data[i].state) {
692 case STATE_RENDEZVOUS:
693 printk("RENDEZVS");break;
694 case STATE_RUNNING:
695 printk((current_pid(i)!=0) ? "RUNNING " : "IDLING");
696 break;
697 case STATE_STOPPED:
698 printk("STOPPED ");break;
699 case STATE_HALTED:
700 printk("HALTED ");break;
701 default:
702 }
703 printk(" %5d\n",i);
704 }
705 }
706#else
707 printk("\n%s CPU0",(current->pid==0)?"RUNNING ":"IDLING ");
708#endif
709 } else {
710 printk("sys_cpus:Unknown request\n");
711 return (-1);
712 }
713 return 0;
714}
715#endif /* ENTRY_SYS_CPUS */
716
717#ifdef CONFIG_PROC_FS
718int __init
719setup_profiling_timer(unsigned int multiplier)
720{
721 return -EINVAL;
722}
723#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 @@
1/*
2 * Copyright (C) 2002 Richard Hirst <rhirst at parisc-linux.org>
3 * Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org>
4 * Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#ifndef _PARISC64_KERNEL_SYS32_H
21#define _PARISC64_KERNEL_SYS32_H
22
23#include <linux/compat.h>
24
25/* Call a kernel syscall which will use kernel space instead of user
26 * space for its copy_to/from_user.
27 */
28#define KERNEL_SYSCALL(ret, syscall, args...) \
29{ \
30 mm_segment_t old_fs = get_fs(); \
31 set_fs(KERNEL_DS); \
32 ret = syscall(args); \
33 set_fs (old_fs); \
34}
35
36#ifdef CONFIG_COMPAT
37
38typedef __u32 __sighandler_t32;
39
40struct sigaction32 {
41 __sighandler_t32 sa_handler;
42 unsigned int sa_flags;
43 compat_sigset_t sa_mask; /* mask last for extensibility */
44};
45
46#endif
47
48#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 @@
1
2/*
3 * PARISC specific syscalls
4 *
5 * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
6 * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
7 * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <asm/uaccess.h>
26#include <linux/file.h>
27#include <linux/fs.h>
28#include <linux/linkage.h>
29#include <linux/mm.h>
30#include <linux/mman.h>
31#include <linux/shm.h>
32#include <linux/smp_lock.h>
33#include <linux/syscalls.h>
34
35int sys_pipe(int __user *fildes)
36{
37 int fd[2];
38 int error;
39
40 error = do_pipe(fd);
41 if (!error) {
42 if (copy_to_user(fildes, fd, 2*sizeof(int)))
43 error = -EFAULT;
44 }
45 return error;
46}
47
48static unsigned long get_unshared_area(unsigned long addr, unsigned long len)
49{
50 struct vm_area_struct *vma;
51
52 addr = PAGE_ALIGN(addr);
53
54 for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
55 /* At this point: (!vma || addr < vma->vm_end). */
56 if (TASK_SIZE - len < addr)
57 return -ENOMEM;
58 if (!vma || addr + len <= vma->vm_start)
59 return addr;
60 addr = vma->vm_end;
61 }
62}
63
64#define DCACHE_ALIGN(addr) (((addr) + (SHMLBA - 1)) &~ (SHMLBA - 1))
65
66/*
67 * We need to know the offset to use. Old scheme was to look for
68 * existing mapping and use the same offset. New scheme is to use the
69 * address of the kernel data structure as the seed for the offset.
70 * We'll see how that works...
71 *
72 * The mapping is cacheline aligned, so there's no information in the bottom
73 * few bits of the address. We're looking for 10 bits (4MB / 4k), so let's
74 * drop the bottom 8 bits and use bits 8-17.
75 */
76static int get_offset(struct address_space *mapping)
77{
78 int offset = (unsigned long) mapping << (PAGE_SHIFT - 8);
79 return offset & 0x3FF000;
80}
81
82static unsigned long get_shared_area(struct address_space *mapping,
83 unsigned long addr, unsigned long len, unsigned long pgoff)
84{
85 struct vm_area_struct *vma;
86 int offset = mapping ? get_offset(mapping) : 0;
87
88 addr = DCACHE_ALIGN(addr - offset) + offset;
89
90 for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
91 /* At this point: (!vma || addr < vma->vm_end). */
92 if (TASK_SIZE - len < addr)
93 return -ENOMEM;
94 if (!vma || addr + len <= vma->vm_start)
95 return addr;
96 addr = DCACHE_ALIGN(vma->vm_end - offset) + offset;
97 if (addr < vma->vm_end) /* handle wraparound */
98 return -ENOMEM;
99 }
100}
101
102unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
103 unsigned long len, unsigned long pgoff, unsigned long flags)
104{
105 if (len > TASK_SIZE)
106 return -ENOMEM;
107 if (!addr)
108 addr = TASK_UNMAPPED_BASE;
109
110 if (filp) {
111 addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
112 } else if(flags & MAP_SHARED) {
113 addr = get_shared_area(NULL, addr, len, pgoff);
114 } else {
115 addr = get_unshared_area(addr, len);
116 }
117 return addr;
118}
119
120static unsigned long do_mmap2(unsigned long addr, unsigned long len,
121 unsigned long prot, unsigned long flags, unsigned long fd,
122 unsigned long pgoff)
123{
124 struct file * file = NULL;
125 unsigned long error = -EBADF;
126 if (!(flags & MAP_ANONYMOUS)) {
127 file = fget(fd);
128 if (!file)
129 goto out;
130 }
131
132 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
133
134 down_write(&current->mm->mmap_sem);
135 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
136 up_write(&current->mm->mmap_sem);
137
138 if (file != NULL)
139 fput(file);
140out:
141 return error;
142}
143
144asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
145 unsigned long prot, unsigned long flags, unsigned long fd,
146 unsigned long pgoff)
147{
148 /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
149 we have. */
150 return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
151}
152
153asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
154 unsigned long prot, unsigned long flags, unsigned long fd,
155 unsigned long offset)
156{
157 if (!(offset & ~PAGE_MASK)) {
158 return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
159 } else {
160 return -EINVAL;
161 }
162}
163
164long sys_shmat_wrapper(int shmid, char __user *shmaddr, int shmflag)
165{
166 unsigned long raddr;
167 int r;
168
169 r = do_shmat(shmid, shmaddr, shmflag, &raddr);
170 if (r < 0)
171 return r;
172 return raddr;
173}
174
175/* Fucking broken ABI */
176
177#ifdef CONFIG_64BIT
178asmlinkage long parisc_truncate64(const char __user * path,
179 unsigned int high, unsigned int low)
180{
181 return sys_truncate(path, (long)high << 32 | low);
182}
183
184asmlinkage long parisc_ftruncate64(unsigned int fd,
185 unsigned int high, unsigned int low)
186{
187 return sys_ftruncate(fd, (long)high << 32 | low);
188}
189
190/* stubs for the benefit of the syscall_table since truncate64 and truncate
191 * are identical on LP64 */
192asmlinkage long sys_truncate64(const char __user * path, unsigned long length)
193{
194 return sys_truncate(path, length);
195}
196asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length)
197{
198 return sys_ftruncate(fd, length);
199}
200asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
201{
202 return sys_fcntl(fd, cmd, arg);
203}
204#else
205
206asmlinkage long parisc_truncate64(const char __user * path,
207 unsigned int high, unsigned int low)
208{
209 return sys_truncate64(path, (loff_t)high << 32 | low);
210}
211
212asmlinkage long parisc_ftruncate64(unsigned int fd,
213 unsigned int high, unsigned int low)
214{
215 return sys_ftruncate64(fd, (loff_t)high << 32 | low);
216}
217#endif
218
219asmlinkage ssize_t parisc_pread64(unsigned int fd, char __user *buf, size_t count,
220 unsigned int high, unsigned int low)
221{
222 return sys_pread64(fd, buf, count, (loff_t)high << 32 | low);
223}
224
225asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char __user *buf,
226 size_t count, unsigned int high, unsigned int low)
227{
228 return sys_pwrite64(fd, buf, count, (loff_t)high << 32 | low);
229}
230
231asmlinkage ssize_t parisc_readahead(int fd, unsigned int high, unsigned int low,
232 size_t count)
233{
234 return sys_readahead(fd, (loff_t)high << 32 | low, count);
235}
236
237asmlinkage long parisc_fadvise64_64(int fd,
238 unsigned int high_off, unsigned int low_off,
239 unsigned int high_len, unsigned int low_len, int advice)
240{
241 return sys_fadvise64_64(fd, (loff_t)high_off << 32 | low_off,
242 (loff_t)high_len << 32 | low_len, advice);
243}
244
245asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag)
246{
247 return -ENOMEM;
248}
249
250asmlinkage int sys_free_hugepages(unsigned long addr)
251{
252 return -EINVAL;
253}
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 @@
1/*
2 * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls.
3 *
4 * Copyright (C) 2000-2001 Hewlett Packard Company
5 * Copyright (C) 2000 John Marvin
6 * Copyright (C) 2001 Matthew Wilcox
7 *
8 * These routines maintain argument size conversion between 32bit and 64bit
9 * environment. Based heavily on sys_ia32.c and sys_sparc32.c.
10 */
11
12#include <linux/config.h>
13#include <linux/compat.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/fs.h>
17#include <linux/mm.h>
18#include <linux/file.h>
19#include <linux/signal.h>
20#include <linux/resource.h>
21#include <linux/times.h>
22#include <linux/utsname.h>
23#include <linux/time.h>
24#include <linux/timex.h>
25#include <linux/smp.h>
26#include <linux/smp_lock.h>
27#include <linux/sem.h>
28#include <linux/msg.h>
29#include <linux/shm.h>
30#include <linux/slab.h>
31#include <linux/uio.h>
32#include <linux/nfs_fs.h>
33#include <linux/ncp_fs.h>
34#include <linux/sunrpc/svc.h>
35#include <linux/nfsd/nfsd.h>
36#include <linux/nfsd/cache.h>
37#include <linux/nfsd/xdr.h>
38#include <linux/nfsd/syscall.h>
39#include <linux/poll.h>
40#include <linux/personality.h>
41#include <linux/stat.h>
42#include <linux/highmem.h>
43#include <linux/highuid.h>
44#include <linux/mman.h>
45#include <linux/binfmts.h>
46#include <linux/namei.h>
47#include <linux/vfs.h>
48#include <linux/ptrace.h>
49#include <linux/swap.h>
50#include <linux/syscalls.h>
51
52#include <asm/types.h>
53#include <asm/uaccess.h>
54#include <asm/semaphore.h>
55#include <asm/mmu_context.h>
56
57#include "sys32.h"
58
59#undef DEBUG
60
61#ifdef DEBUG
62#define DBG(x) printk x
63#else
64#define DBG(x)
65#endif
66
67/*
68 * sys32_execve() executes a new program.
69 */
70
71asmlinkage int sys32_execve(struct pt_regs *regs)
72{
73 int error;
74 char *filename;
75
76 DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
77 filename = getname((const char __user *) regs->gr[26]);
78 error = PTR_ERR(filename);
79 if (IS_ERR(filename))
80 goto out;
81 error = compat_do_execve(filename, compat_ptr(regs->gr[25]),
82 compat_ptr(regs->gr[24]), regs);
83 if (error == 0) {
84 task_lock(current);
85 current->ptrace &= ~PT_DTRACE;
86 task_unlock(current);
87 }
88 putname(filename);
89out:
90
91 return error;
92}
93
94asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
95 int r22, int r21, int r20)
96{
97 printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n",
98 current->comm, current->pid, r20);
99 return -ENOSYS;
100}
101
102#ifdef CONFIG_SYSCTL
103
104struct __sysctl_args32 {
105 u32 name;
106 int nlen;
107 u32 oldval;
108 u32 oldlenp;
109 u32 newval;
110 u32 newlen;
111 u32 __unused[4];
112};
113
114asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
115{
116 struct __sysctl_args32 tmp;
117 int error;
118 unsigned int oldlen32;
119 size_t oldlen, *oldlenp = NULL;
120 unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
121 extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
122 void *newval, size_t newlen);
123
124 DBG(("sysctl32(%p)\n", args));
125
126 if (copy_from_user(&tmp, args, sizeof(tmp)))
127 return -EFAULT;
128
129 if (tmp.oldval && tmp.oldlenp) {
130 /* Duh, this is ugly and might not work if sysctl_args
131 is in read-only memory, but do_sysctl does indirectly
132 a lot of uaccess in both directions and we'd have to
133 basically copy the whole sysctl.c here, and
134 glibc's __sysctl uses rw memory for the structure
135 anyway. */
136 /* a possibly better hack than this, which will avoid the
137 * problem if the struct is read only, is to push the
138 * 'oldlen' value out to the user's stack instead. -PB
139 */
140 if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
141 return -EFAULT;
142 oldlen = oldlen32;
143 if (put_user(oldlen, (size_t *)addr))
144 return -EFAULT;
145 oldlenp = (size_t *)addr;
146 }
147
148 lock_kernel();
149 error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval,
150 oldlenp, (void *)(u64)tmp.newval, tmp.newlen);
151 unlock_kernel();
152 if (oldlenp) {
153 if (!error) {
154 if (get_user(oldlen, (size_t *)addr)) {
155 error = -EFAULT;
156 } else {
157 oldlen32 = oldlen;
158 if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
159 error = -EFAULT;
160 }
161 }
162 if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused)))
163 error = -EFAULT;
164 }
165 return error;
166}
167
168#endif /* CONFIG_SYSCTL */
169
170asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
171 struct compat_timespec __user *interval)
172{
173 struct timespec t;
174 int ret;
175
176 KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t);
177 if (put_compat_timespec(&t, interval))
178 return -EFAULT;
179 return ret;
180}
181
182static int
183put_compat_timeval(struct compat_timeval __user *u, struct timeval *t)
184{
185 struct compat_timeval t32;
186 t32.tv_sec = t->tv_sec;
187 t32.tv_usec = t->tv_usec;
188 return copy_to_user(u, &t32, sizeof t32);
189}
190
191static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
192{
193 long usec;
194
195 if (__get_user(o->tv_sec, &i->tv_sec))
196 return -EFAULT;
197 if (__get_user(usec, &i->tv_usec))
198 return -EFAULT;
199 o->tv_nsec = usec * 1000;
200 return 0;
201}
202
203asmlinkage int
204sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
205{
206 extern void do_gettimeofday(struct timeval *tv);
207
208 if (tv) {
209 struct timeval ktv;
210 do_gettimeofday(&ktv);
211 if (put_compat_timeval(tv, &ktv))
212 return -EFAULT;
213 }
214 if (tz) {
215 extern struct timezone sys_tz;
216 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
217 return -EFAULT;
218 }
219 return 0;
220}
221
222asmlinkage
223int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
224{
225 struct timespec kts;
226 struct timezone ktz;
227
228 if (tv) {
229 if (get_ts32(&kts, tv))
230 return -EFAULT;
231 }
232 if (tz) {
233 if (copy_from_user(&ktz, tz, sizeof(ktz)))
234 return -EFAULT;
235 }
236
237 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
238}
239
240int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
241{
242 int err;
243
244 if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
245 !new_valid_dev(stat->rdev))
246 return -EOVERFLOW;
247
248 err = put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
249 err |= put_user(stat->ino, &statbuf->st_ino);
250 err |= put_user(stat->mode, &statbuf->st_mode);
251 err |= put_user(stat->nlink, &statbuf->st_nlink);
252 err |= put_user(0, &statbuf->st_reserved1);
253 err |= put_user(0, &statbuf->st_reserved2);
254 err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
255 err |= put_user(stat->size, &statbuf->st_size);
256 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
257 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
258 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
259 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
260 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
261 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
262 err |= put_user(stat->blksize, &statbuf->st_blksize);
263 err |= put_user(stat->blocks, &statbuf->st_blocks);
264 err |= put_user(0, &statbuf->__unused1);
265 err |= put_user(0, &statbuf->__unused2);
266 err |= put_user(0, &statbuf->__unused3);
267 err |= put_user(0, &statbuf->__unused4);
268 err |= put_user(0, &statbuf->__unused5);
269 err |= put_user(0, &statbuf->st_fstype); /* not avail */
270 err |= put_user(0, &statbuf->st_realdev); /* not avail */
271 err |= put_user(0, &statbuf->st_basemode); /* not avail */
272 err |= put_user(0, &statbuf->st_spareshort);
273 err |= put_user(stat->uid, &statbuf->st_uid);
274 err |= put_user(stat->gid, &statbuf->st_gid);
275 err |= put_user(0, &statbuf->st_spare4[0]);
276 err |= put_user(0, &statbuf->st_spare4[1]);
277 err |= put_user(0, &statbuf->st_spare4[2]);
278
279 return err;
280}
281
282struct linux32_dirent {
283 u32 d_ino;
284 compat_off_t d_off;
285 u16 d_reclen;
286 char d_name[1];
287};
288
289struct old_linux32_dirent {
290 u32 d_ino;
291 u32 d_offset;
292 u16 d_namlen;
293 char d_name[1];
294};
295
296struct getdents32_callback {
297 struct linux32_dirent __user * current_dir;
298 struct linux32_dirent __user * previous;
299 int count;
300 int error;
301};
302
303struct readdir32_callback {
304 struct old_linux32_dirent __user * dirent;
305 int count;
306};
307
308#define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
309#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
310static int
311filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
312 unsigned int d_type)
313{
314 struct linux32_dirent __user * dirent;
315 struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
316 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
317
318 buf->error = -EINVAL; /* only used if we fail.. */
319 if (reclen > buf->count)
320 return -EINVAL;
321 dirent = buf->previous;
322 if (dirent)
323 put_user(offset, &dirent->d_off);
324 dirent = buf->current_dir;
325 buf->previous = dirent;
326 put_user(ino, &dirent->d_ino);
327 put_user(reclen, &dirent->d_reclen);
328 copy_to_user(dirent->d_name, name, namlen);
329 put_user(0, dirent->d_name + namlen);
330 dirent = ((void __user *)dirent) + reclen;
331 buf->current_dir = dirent;
332 buf->count -= reclen;
333 return 0;
334}
335
336asmlinkage long
337sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
338{
339 struct file * file;
340 struct linux32_dirent __user * lastdirent;
341 struct getdents32_callback buf;
342 int error;
343
344 error = -EBADF;
345 file = fget(fd);
346 if (!file)
347 goto out;
348
349 buf.current_dir = (struct linux32_dirent __user *) dirent;
350 buf.previous = NULL;
351 buf.count = count;
352 buf.error = 0;
353
354 error = vfs_readdir(file, filldir32, &buf);
355 if (error < 0)
356 goto out_putf;
357 error = buf.error;
358 lastdirent = buf.previous;
359 if (lastdirent) {
360 put_user(file->f_pos, &lastdirent->d_off);
361 error = count - buf.count;
362 }
363
364out_putf:
365 fput(file);
366out:
367 return error;
368}
369
370static int
371fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
372 unsigned int d_type)
373{
374 struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
375 struct old_linux32_dirent __user * dirent;
376
377 if (buf->count)
378 return -EINVAL;
379 buf->count++;
380 dirent = buf->dirent;
381 put_user(ino, &dirent->d_ino);
382 put_user(offset, &dirent->d_offset);
383 put_user(namlen, &dirent->d_namlen);
384 copy_to_user(dirent->d_name, name, namlen);
385 put_user(0, dirent->d_name + namlen);
386 return 0;
387}
388
389asmlinkage long
390sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count)
391{
392 int error;
393 struct file * file;
394 struct readdir32_callback buf;
395
396 error = -EBADF;
397 file = fget(fd);
398 if (!file)
399 goto out;
400
401 buf.count = 0;
402 buf.dirent = dirent;
403
404 error = vfs_readdir(file, fillonedir32, &buf);
405 if (error >= 0)
406 error = buf.count;
407 fput(file);
408out:
409 return error;
410}
411
412/*** copied from mips64 ***/
413/*
414 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
415 * 64-bit unsigned longs.
416 */
417
418static inline int
419get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
420{
421 n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
422 if (ufdset) {
423 unsigned long odd;
424
425 if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32)))
426 return -EFAULT;
427
428 odd = n & 1UL;
429 n &= ~1UL;
430 while (n) {
431 unsigned long h, l;
432 __get_user(l, ufdset);
433 __get_user(h, ufdset+1);
434 ufdset += 2;
435 *fdset++ = h << 32 | l;
436 n -= 2;
437 }
438 if (odd)
439 __get_user(*fdset, ufdset);
440 } else {
441 /* Tricky, must clear full unsigned long in the
442 * kernel fdset at the end, this makes sure that
443 * actually happens.
444 */
445 memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
446 }
447 return 0;
448}
449
450static inline void
451set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
452{
453 unsigned long odd;
454 n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
455
456 if (!ufdset)
457 return;
458
459 odd = n & 1UL;
460 n &= ~1UL;
461 while (n) {
462 unsigned long h, l;
463 l = *fdset++;
464 h = l >> 32;
465 __put_user(l, ufdset);
466 __put_user(h, ufdset+1);
467 ufdset += 2;
468 n -= 2;
469 }
470 if (odd)
471 __put_user(*fdset, ufdset);
472}
473
474struct msgbuf32 {
475 int mtype;
476 char mtext[1];
477};
478
479asmlinkage long sys32_msgsnd(int msqid,
480 struct msgbuf32 __user *umsgp32,
481 size_t msgsz, int msgflg)
482{
483 struct msgbuf *mb;
484 struct msgbuf32 mb32;
485 int err;
486
487 if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
488 return -ENOMEM;
489
490 err = get_user(mb32.mtype, &umsgp32->mtype);
491 mb->mtype = mb32.mtype;
492 err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz);
493
494 if (err)
495 err = -EFAULT;
496 else
497 KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg);
498
499 kfree(mb);
500 return err;
501}
502
503asmlinkage long sys32_msgrcv(int msqid,
504 struct msgbuf32 __user *umsgp32,
505 size_t msgsz, long msgtyp, int msgflg)
506{
507 struct msgbuf *mb;
508 struct msgbuf32 mb32;
509 int err, len;
510
511 if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
512 return -ENOMEM;
513
514 KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg);
515
516 if (err >= 0) {
517 len = err;
518 mb32.mtype = mb->mtype;
519 err = put_user(mb32.mtype, &umsgp32->mtype);
520 err |= copy_to_user(&umsgp32->mtext, mb->mtext, len);
521 if (err)
522 err = -EFAULT;
523 else
524 err = len;
525 }
526
527 kfree(mb);
528 return err;
529}
530
531asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
532{
533 mm_segment_t old_fs = get_fs();
534 int ret;
535 off_t of;
536
537 if (offset && get_user(of, offset))
538 return -EFAULT;
539
540 set_fs(KERNEL_DS);
541 ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
542 set_fs(old_fs);
543
544 if (offset && put_user(of, offset))
545 return -EFAULT;
546
547 return ret;
548}
549
550asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
551{
552 mm_segment_t old_fs = get_fs();
553 int ret;
554 loff_t lof;
555
556 if (offset && get_user(lof, offset))
557 return -EFAULT;
558
559 set_fs(KERNEL_DS);
560 ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count);
561 set_fs(old_fs);
562
563 if (offset && put_user(lof, offset))
564 return -EFAULT;
565
566 return ret;
567}
568
569
570struct timex32 {
571 unsigned int modes; /* mode selector */
572 int offset; /* time offset (usec) */
573 int freq; /* frequency offset (scaled ppm) */
574 int maxerror; /* maximum error (usec) */
575 int esterror; /* estimated error (usec) */
576 int status; /* clock command/status */
577 int constant; /* pll time constant */
578 int precision; /* clock precision (usec) (read only) */
579 int tolerance; /* clock frequency tolerance (ppm)
580 * (read only)
581 */
582 struct compat_timeval time; /* (read only) */
583 int tick; /* (modified) usecs between clock ticks */
584
585 int ppsfreq; /* pps frequency (scaled ppm) (ro) */
586 int jitter; /* pps jitter (us) (ro) */
587 int shift; /* interval duration (s) (shift) (ro) */
588 int stabil; /* pps stability (scaled ppm) (ro) */
589 int jitcnt; /* jitter limit exceeded (ro) */
590 int calcnt; /* calibration intervals (ro) */
591 int errcnt; /* calibration errors (ro) */
592 int stbcnt; /* stability limit exceeded (ro) */
593
594 int :32; int :32; int :32; int :32;
595 int :32; int :32; int :32; int :32;
596 int :32; int :32; int :32; int :32;
597};
598
599asmlinkage long sys32_adjtimex(struct timex32 __user *txc_p32)
600{
601 struct timex txc;
602 struct timex32 t32;
603 int ret;
604 extern int do_adjtimex(struct timex *txc);
605
606 if(copy_from_user(&t32, txc_p32, sizeof(struct timex32)))
607 return -EFAULT;
608#undef CP
609#define CP(x) txc.x = t32.x
610 CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
611 CP(status); CP(constant); CP(precision); CP(tolerance);
612 CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
613 CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
614 CP(stbcnt);
615 ret = do_adjtimex(&txc);
616#undef CP
617#define CP(x) t32.x = txc.x
618 CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
619 CP(status); CP(constant); CP(precision); CP(tolerance);
620 CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
621 CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
622 CP(stbcnt);
623 return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret;
624}
625
626
627struct sysinfo32 {
628 s32 uptime;
629 u32 loads[3];
630 u32 totalram;
631 u32 freeram;
632 u32 sharedram;
633 u32 bufferram;
634 u32 totalswap;
635 u32 freeswap;
636 unsigned short procs;
637 u32 totalhigh;
638 u32 freehigh;
639 u32 mem_unit;
640 char _f[12];
641};
642
643/* We used to call sys_sysinfo and translate the result. But sys_sysinfo
644 * undoes the good work done elsewhere, and rather than undoing the
645 * damage, I decided to just duplicate the code from sys_sysinfo here.
646 */
647
648asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
649{
650 struct sysinfo val;
651 int err;
652 unsigned long seq;
653
654 /* We don't need a memset here because we copy the
655 * struct to userspace once element at a time.
656 */
657
658 do {
659 seq = read_seqbegin(&xtime_lock);
660 val.uptime = jiffies / HZ;
661
662 val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
663 val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
664 val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
665
666 val.procs = nr_threads;
667 } while (read_seqretry(&xtime_lock, seq));
668
669
670 si_meminfo(&val);
671 si_swapinfo(&val);
672
673 err = put_user (val.uptime, &info->uptime);
674 err |= __put_user (val.loads[0], &info->loads[0]);
675 err |= __put_user (val.loads[1], &info->loads[1]);
676 err |= __put_user (val.loads[2], &info->loads[2]);
677 err |= __put_user (val.totalram, &info->totalram);
678 err |= __put_user (val.freeram, &info->freeram);
679 err |= __put_user (val.sharedram, &info->sharedram);
680 err |= __put_user (val.bufferram, &info->bufferram);
681 err |= __put_user (val.totalswap, &info->totalswap);
682 err |= __put_user (val.freeswap, &info->freeswap);
683 err |= __put_user (val.procs, &info->procs);
684 err |= __put_user (val.totalhigh, &info->totalhigh);
685 err |= __put_user (val.freehigh, &info->freehigh);
686 err |= __put_user (val.mem_unit, &info->mem_unit);
687 return err ? -EFAULT : 0;
688}
689
690
691/* lseek() needs a wrapper because 'offset' can be negative, but the top
692 * half of the argument has been zeroed by syscall.S.
693 */
694
695asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin)
696{
697 return sys_lseek(fd, offset, origin);
698}
699
700asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg)
701{
702 union semun u;
703
704 if (cmd == SETVAL) {
705 /* Ugh. arg is a union of int,ptr,ptr,ptr, so is 8 bytes.
706 * The int should be in the first 4, but our argument
707 * frobbing has left it in the last 4.
708 */
709 u.val = *((int *)&arg + 1);
710 return sys_semctl (semid, semnum, cmd, u);
711 }
712 return sys_semctl (semid, semnum, cmd, arg);
713}
714
715long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
716 size_t len)
717{
718 return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
719 buf, len);
720}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
5 * Licensed under the GNU GPL.
6 * thanks to Philipp Rumpf, Mike Shaver and various others
7 * sorry about the wall, puffin..
8 */
9
10#include <asm/offsets.h>
11#include <asm/unistd.h>
12#include <asm/errno.h>
13#include <asm/psw.h>
14#include <asm/thread_info.h>
15
16#include <asm/assembly.h>
17#include <asm/processor.h>
18
19 /* We fill the empty parts of the gateway page with
20 * something that will kill the kernel or a
21 * userspace application.
22 */
23#define KILL_INSN break 0,0
24
25#include <linux/config.h> /* for CONFIG_SMP */
26
27#ifdef __LP64__
28 .level 2.0w
29#else
30 .level 1.1
31#endif
32
33#ifndef __LP64__
34 .macro fixup_branch,lbl
35 b \lbl
36 .endm
37#else
38 .macro fixup_branch,lbl
39 ldil L%\lbl, %r1
40 ldo R%\lbl(%r1), %r1
41 bv,n %r0(%r1)
42 .endm
43#endif
44
45 .text
46
47 .import syscall_exit,code
48 .import syscall_exit_rfi,code
49 .export linux_gateway_page
50
51 /* Linux gateway page is aliased to virtual page 0 in the kernel
52 * address space. Since it is a gateway page it cannot be
53 * dereferenced, so null pointers will still fault. We start
54 * the actual entry point at 0x100. We put break instructions
55 * at the beginning of the page to trap null indirect function
56 * pointers.
57 */
58
59 .align 4096
60linux_gateway_page:
61
62 /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
63 .rept 44
64 KILL_INSN
65 .endr
66
67 /* ADDRESS 0xb0 to 0xb4, lws uses 1 insns for entry */
68 /* Light-weight-syscall entry must always be located at 0xb0 */
69 /* WARNING: Keep this number updated with table size changes */
70#define __NR_lws_entries (2)
71
72lws_entry:
73 /* Unconditional branch to lws_start, located on the
74 same gateway page */
75 b,n lws_start
76
77 /* Fill from 0xb4 to 0xe0 */
78 .rept 11
79 KILL_INSN
80 .endr
81
82 /* This function MUST be located at 0xe0 for glibc's threading
83 mechanism to work. DO NOT MOVE THIS CODE EVER! */
84set_thread_pointer:
85 gate .+8, %r0 /* increase privilege */
86 depi 3, 31, 2, %r31 /* Ensure we return into user mode. */
87 be 0(%sr7,%r31) /* return to user space */
88 mtctl %r26, %cr27 /* move arg0 to the control register */
89
90 /* Increase the chance of trapping if random jumps occur to this
91 address, fill from 0xf0 to 0x100 */
92 .rept 4
93 KILL_INSN
94 .endr
95
96/* This address must remain fixed at 0x100 for glibc's syscalls to work */
97 .align 256
98linux_gateway_entry:
99 gate .+8, %r0 /* become privileged */
100 mtsp %r0,%sr4 /* get kernel space into sr4 */
101 mtsp %r0,%sr5 /* get kernel space into sr5 */
102 mtsp %r0,%sr6 /* get kernel space into sr6 */
103 mfsp %sr7,%r1 /* save user sr7 */
104 mtsp %r1,%sr3 /* and store it in sr3 */
105
106#ifdef __LP64__
107 /* for now we can *always* set the W bit on entry to the syscall
108 * since we don't support wide userland processes. We could
109 * also save the current SM other than in r0 and restore it on
110 * exit from the syscall, and also use that value to know
111 * whether to do narrow or wide syscalls. -PB
112 */
113 ssm PSW_SM_W, %r1
114 extrd,u %r1,PSW_W_BIT,1,%r1
115 /* sp must be aligned on 4, so deposit the W bit setting into
116 * the bottom of sp temporarily */
117 or,ev %r1,%r30,%r30
118 b,n 1f
119 /* The top halves of argument registers must be cleared on syscall
120 * entry from narrow executable.
121 */
122 depdi 0, 31, 32, %r26
123 depdi 0, 31, 32, %r25
124 depdi 0, 31, 32, %r24
125 depdi 0, 31, 32, %r23
126 depdi 0, 31, 32, %r22
127 depdi 0, 31, 32, %r21
1281:
129#endif
130 mfctl %cr30,%r1
131 xor %r1,%r30,%r30 /* ye olde xor trick */
132 xor %r1,%r30,%r1
133 xor %r1,%r30,%r30
134
135 ldo THREAD_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */
136
137 /* N.B.: It is critical that we don't set sr7 to 0 until r30
138 * contains a valid kernel stack pointer. It is also
139 * critical that we don't start using the kernel stack
140 * until after sr7 has been set to 0.
141 */
142
143 mtsp %r0,%sr7 /* get kernel space into sr7 */
144 STREGM %r1,FRAME_SIZE(%r30) /* save r1 (usp) here for now */
145 mfctl %cr30,%r1 /* get task ptr in %r1 */
146 LDREG TI_TASK(%r1),%r1
147
148 /* Save some registers for sigcontext and potential task
149 switch (see entry.S for the details of which ones are
150 saved/restored). TASK_PT_PSW is zeroed so we can see whether
151 a process is on a syscall or not. For an interrupt the real
152 PSW value is stored. This is needed for gdb and sys_ptrace. */
153 STREG %r0, TASK_PT_PSW(%r1)
154 STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
155 STREG %r19, TASK_PT_GR19(%r1)
156
157 LDREGM -FRAME_SIZE(%r30), %r2 /* get users sp back */
158#ifdef __LP64__
159 extrd,u %r2,63,1,%r19 /* W hidden in bottom bit */
160#if 0
161 xor %r19,%r2,%r2 /* clear bottom bit */
162 depd,z %r19,1,1,%r19
163 std %r19,TASK_PT_PSW(%r1)
164#endif
165#endif
166 STREG %r2, TASK_PT_GR30(%r1) /* ... and save it */
167
168 STREG %r20, TASK_PT_GR20(%r1)
169 STREG %r21, TASK_PT_GR21(%r1)
170 STREG %r22, TASK_PT_GR22(%r1)
171 STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */
172 STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */
173 STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */
174 STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
175 STREG %r27, TASK_PT_GR27(%r1) /* user dp */
176 STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
177 STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */
178 STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */
179 STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
180
181 ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */
182 save_fp %r27 /* or potential task switch */
183
184 mfctl %cr11, %r27 /* i.e. SAR */
185 STREG %r27, TASK_PT_SAR(%r1)
186
187 loadgp
188
189#ifdef __LP64__
190 ldo -16(%r30),%r29 /* Reference param save area */
191 copy %r19,%r2 /* W bit back to r2 */
192#else
193 /* no need to save these on stack in wide mode because the first 8
194 * args are passed in registers */
195 stw %r22, -52(%r30) /* 5th argument */
196 stw %r21, -56(%r30) /* 6th argument */
197#endif
198
199 /* Are we being ptraced? */
200 mfctl %cr30, %r1
201 LDREG TI_TASK(%r1),%r1
202 LDREG TASK_PTRACE(%r1), %r1
203 bb,<,n %r1,31,.Ltracesys
204
205 /* Note! We cannot use the syscall table that is mapped
206 nearby since the gateway page is mapped execute-only. */
207
208#ifdef __LP64__
209 ldil L%sys_call_table, %r1
210 or,= %r2,%r2,%r2
211 addil L%(sys_call_table64-sys_call_table), %r1
212 ldo R%sys_call_table(%r1), %r19
213 or,= %r2,%r2,%r2
214 ldo R%sys_call_table64(%r1), %r19
215#else
216 ldil L%sys_call_table, %r1
217 ldo R%sys_call_table(%r1), %r19
218#endif
219 comiclr,>>= __NR_Linux_syscalls, %r20, %r0
220 b,n .Lsyscall_nosys
221
222 LDREGX %r20(%r19), %r19
223
224 /* If this is a sys_rt_sigreturn call, and the signal was received
225 * when not in_syscall, then we want to return via syscall_exit_rfi,
226 * not syscall_exit. Signal no. in r20, in_syscall in r25 (see
227 * trampoline code in signal.c).
228 */
229 ldi __NR_rt_sigreturn,%r2
230 comb,= %r2,%r20,.Lrt_sigreturn
231.Lin_syscall:
232 ldil L%syscall_exit,%r2
233 be 0(%sr7,%r19)
234 ldo R%syscall_exit(%r2),%r2
235.Lrt_sigreturn:
236 comib,<> 0,%r25,.Lin_syscall
237 ldil L%syscall_exit_rfi,%r2
238 be 0(%sr7,%r19)
239 ldo R%syscall_exit_rfi(%r2),%r2
240
241 /* Note! Because we are not running where we were linked, any
242 calls to functions external to this file must be indirect. To
243 be safe, we apply the opposite rule to functions within this
244 file, with local labels given to them to ensure correctness. */
245
246.Lsyscall_nosys:
247syscall_nosys:
248 ldil L%syscall_exit,%r1
249 be R%syscall_exit(%sr7,%r1)
250 ldo -ENOSYS(%r0),%r28 /* set errno */
251
252
253/* Warning! This trace code is a virtual duplicate of the code above so be
254 * sure to maintain both! */
255.Ltracesys:
256tracesys:
257 /* Need to save more registers so the debugger can see where we
258 * are. This saves only the lower 8 bits of PSW, so that the C
259 * bit is still clear on syscalls, and the D bit is set if this
260 * full register save path has been executed. We check the D
261 * bit on syscall_return_rfi to determine which registers to
262 * restore. An interrupt results in a full PSW saved with the
263 * C bit set, a non-straced syscall entry results in C and D clear
264 * in the saved PSW.
265 */
266 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
267 LDREG TI_TASK(%r1), %r1
268 ssm 0,%r2
269 STREG %r2,TASK_PT_PSW(%r1) /* Lower 8 bits only!! */
270 mfsp %sr0,%r2
271 STREG %r2,TASK_PT_SR0(%r1)
272 mfsp %sr1,%r2
273 STREG %r2,TASK_PT_SR1(%r1)
274 mfsp %sr2,%r2
275 STREG %r2,TASK_PT_SR2(%r1)
276 mfsp %sr3,%r2
277 STREG %r2,TASK_PT_SR3(%r1)
278 STREG %r2,TASK_PT_SR4(%r1)
279 STREG %r2,TASK_PT_SR5(%r1)
280 STREG %r2,TASK_PT_SR6(%r1)
281 STREG %r2,TASK_PT_SR7(%r1)
282 STREG %r2,TASK_PT_IASQ0(%r1)
283 STREG %r2,TASK_PT_IASQ1(%r1)
284 LDREG TASK_PT_GR31(%r1),%r2
285 STREG %r2,TASK_PT_IAOQ0(%r1)
286 ldo 4(%r2),%r2
287 STREG %r2,TASK_PT_IAOQ1(%r1)
288 ldo TASK_REGS(%r1),%r2
289 /* reg_save %r2 */
290 STREG %r3,PT_GR3(%r2)
291 STREG %r4,PT_GR4(%r2)
292 STREG %r5,PT_GR5(%r2)
293 STREG %r6,PT_GR6(%r2)
294 STREG %r7,PT_GR7(%r2)
295 STREG %r8,PT_GR8(%r2)
296 STREG %r9,PT_GR9(%r2)
297 STREG %r10,PT_GR10(%r2)
298 STREG %r11,PT_GR11(%r2)
299 STREG %r12,PT_GR12(%r2)
300 STREG %r13,PT_GR13(%r2)
301 STREG %r14,PT_GR14(%r2)
302 STREG %r15,PT_GR15(%r2)
303 STREG %r16,PT_GR16(%r2)
304 STREG %r17,PT_GR17(%r2)
305 STREG %r18,PT_GR18(%r2)
306 /* Finished saving things for the debugger */
307
308 ldil L%syscall_trace,%r1
309 ldil L%tracesys_next,%r2
310 be R%syscall_trace(%sr7,%r1)
311 ldo R%tracesys_next(%r2),%r2
312
313tracesys_next:
314 ldil L%sys_call_table,%r1
315 ldo R%sys_call_table(%r1), %r19
316
317 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
318 LDREG TI_TASK(%r1), %r1
319 LDREG TASK_PT_GR20(%r1), %r20
320 LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */
321 LDREG TASK_PT_GR25(%r1), %r25
322 LDREG TASK_PT_GR24(%r1), %r24
323 LDREG TASK_PT_GR23(%r1), %r23
324#ifdef __LP64__
325 LDREG TASK_PT_GR22(%r1), %r22
326 LDREG TASK_PT_GR21(%r1), %r21
327 ldo -16(%r30),%r29 /* Reference param save area */
328#endif
329
330 comiclr,>>= __NR_Linux_syscalls, %r20, %r0
331 b,n .Lsyscall_nosys
332
333 LDREGX %r20(%r19), %r19
334
335 /* If this is a sys_rt_sigreturn call, and the signal was received
336 * when not in_syscall, then we want to return via syscall_exit_rfi,
337 * not syscall_exit. Signal no. in r20, in_syscall in r25 (see
338 * trampoline code in signal.c).
339 */
340 ldi __NR_rt_sigreturn,%r2
341 comb,= %r2,%r20,.Ltrace_rt_sigreturn
342.Ltrace_in_syscall:
343 ldil L%tracesys_exit,%r2
344 be 0(%sr7,%r19)
345 ldo R%tracesys_exit(%r2),%r2
346
347 /* Do *not* call this function on the gateway page, because it
348 makes a direct call to syscall_trace. */
349
350tracesys_exit:
351 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
352 LDREG TI_TASK(%r1), %r1
353#ifdef __LP64__
354 ldo -16(%r30),%r29 /* Reference param save area */
355#endif
356 bl syscall_trace, %r2
357 STREG %r28,TASK_PT_GR28(%r1) /* save return value now */
358 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
359 LDREG TI_TASK(%r1), %r1
360 LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */
361
362 ldil L%syscall_exit,%r1
363 be,n R%syscall_exit(%sr7,%r1)
364
365.Ltrace_rt_sigreturn:
366 comib,<> 0,%r25,.Ltrace_in_syscall
367 ldil L%tracesys_sigexit,%r2
368 be 0(%sr7,%r19)
369 ldo R%tracesys_sigexit(%r2),%r2
370
371tracesys_sigexit:
372 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
373 LDREG 0(%r1), %r1
374#ifdef __LP64__
375 ldo -16(%r30),%r29 /* Reference param save area */
376#endif
377 bl syscall_trace, %r2
378 nop
379
380 ldil L%syscall_exit_rfi,%r1
381 be,n R%syscall_exit_rfi(%sr7,%r1)
382
383
384 /*********************************************************
385 Light-weight-syscall code
386
387 r20 - lws number
388 r26,r25,r24,r23,r22 - Input registers
389 r28 - Function return register
390 r21 - Error code.
391
392 Scracth: Any of the above that aren't being
393 currently used, including r1.
394
395 Return pointer: r31 (Not usable)
396
397 Error codes returned by entry path:
398
399 ENOSYS - r20 was an invalid LWS number.
400
401 *********************************************************/
402lws_start:
403 /* Gate and ensure we return to userspace */
404 gate .+8, %r0
405 depi 3, 31, 2, %r31 /* Ensure we return to userspace */
406
407#ifdef __LP64__
408 /* FIXME: If we are a 64-bit kernel just
409 * turn this on unconditionally.
410 */
411 ssm PSW_SM_W, %r1
412 extrd,u %r1,PSW_W_BIT,1,%r1
413 /* sp must be aligned on 4, so deposit the W bit setting into
414 * the bottom of sp temporarily */
415 or,ev %r1,%r30,%r30
416
417 /* Clip LWS number to a 32-bit value always */
418 depdi 0, 31, 32, %r20
419#endif
420
421 /* Is the lws entry number valid? */
422 comiclr,>>= __NR_lws_entries, %r20, %r0
423 b,n lws_exit_nosys
424
425 /* WARNING: Trashing sr2 and sr3 */
426 mfsp %sr7,%r1 /* get userspace into sr3 */
427 mtsp %r1,%sr3
428 mtsp %r0,%sr2 /* get kernel space into sr2 */
429
430 /* Load table start */
431 ldil L%lws_table, %r1
432 ldo R%lws_table(%r1), %r28 /* Scratch use of r28 */
433 LDREGX %r20(%sr2,r28), %r21 /* Scratch use of r21 */
434
435 /* Jump to lws, lws table pointers already relocated */
436 be,n 0(%sr2,%r21)
437
438lws_exit_nosys:
439 ldo -ENOSYS(%r0),%r21 /* set errno */
440 /* Fall through: Return to userspace */
441
442lws_exit:
443#ifdef __LP64__
444 /* decide whether to reset the wide mode bit
445 *
446 * For a syscall, the W bit is stored in the lowest bit
447 * of sp. Extract it and reset W if it is zero */
448 extrd,u,*<> %r30,63,1,%r1
449 rsm PSW_SM_W, %r0
450 /* now reset the lowest bit of sp if it was set */
451 xor %r30,%r1,%r30
452#endif
453 be,n 0(%sr3, %r31)
454
455
456
457 /***************************************************
458 Implementing CAS as an atomic operation:
459
460 %r26 - Address to examine
461 %r25 - Old value to check (old)
462 %r24 - New value to set (new)
463 %r28 - Return prev through this register.
464 %r21 - Kernel error code
465
466 If debugging is DISabled:
467
468 %r21 has the following meanings:
469
470 EAGAIN - CAS is busy, ldcw failed, try again.
471 EFAULT - Read or write failed.
472
473 If debugging is enabled:
474
475 EDEADLOCK - CAS called recursively.
476 EAGAIN && r28 == 1 - CAS is busy. Lock contended.
477 EAGAIN && r28 == 2 - CAS is busy. ldcw failed.
478 EFAULT - Read or write failed.
479
480 Scratch: r20, r28, r1
481
482 ****************************************************/
483
484 /* Do not enable LWS debugging */
485#define ENABLE_LWS_DEBUG 0
486
487 /* ELF64 Process entry path */
488lws_compare_and_swap64:
489#ifdef __LP64__
490 b,n lws_compare_and_swap
491#else
492 /* If we are not a 64-bit kernel, then we don't
493 * implement having 64-bit input registers
494 */
495 b,n lws_exit_nosys
496#endif
497
498 /* ELF32 Process entry path */
499lws_compare_and_swap32:
500#ifdef __LP64__
501 /* Clip all the input registers */
502 depdi 0, 31, 32, %r26
503 depdi 0, 31, 32, %r25
504 depdi 0, 31, 32, %r24
505#endif
506
507lws_compare_and_swap:
508#ifdef CONFIG_SMP
509 /* Load start of lock table */
510 ldil L%lws_lock_start, %r20
511 ldo R%lws_lock_start(%r20), %r28
512
513 /* Extract four bits from r26 and hash lock (Bits 4-7) */
514 extru %r26, 27, 4, %r20
515
516 /* Find lock to use, the hash is either one of 0 to
517 15, multiplied by 16 (keep it 16-byte aligned)
518 and add to the lock table offset. */
519 shlw %r20, 4, %r20
520 add %r20, %r28, %r20
521
522# ifdef ENABLE_LWS_DEBUG
523 /*
524 DEBUG, check for deadlock!
525 If the thread register values are the same
526 then we were the one that locked it last and
527 this is a recurisve call that will deadlock.
528 We *must* giveup this call and fail.
529 */
530 ldw 4(%sr2,%r20), %r28 /* Load thread register */
531 mfctl %cr27, %r21 /* Get current thread register */
532 cmpb,<>,n %r21, %r28, cas_lock /* Called recursive? */
533 b lws_exit /* Return error! */
534 ldo -EDEADLOCK(%r0), %r21
535cas_lock:
536 cmpb,=,n %r0, %r28, cas_nocontend /* Is nobody using it? */
537 ldo 1(%r0), %r28 /* 1st case */
538 b lws_exit /* Contended... */
539 ldo -EAGAIN(%r0), %r21 /* Spin in userspace */
540cas_nocontend:
541# endif
542/* ENABLE_LWS_DEBUG */
543
544 ldcw 0(%sr2,%r20), %r28 /* Try to acquire the lock */
545 cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */
546cas_wouldblock:
547 ldo 2(%r0), %r28 /* 2nd case */
548 b lws_exit /* Contended... */
549 ldo -EAGAIN(%r0), %r21 /* Spin in userspace */
550#endif
551/* CONFIG_SMP */
552
553 /*
554 prev = *addr;
555 if ( prev == old )
556 *addr = new;
557 return prev;
558 */
559
560 /* NOTES:
561 This all works becuse intr_do_signal
562 and schedule both check the return iasq
563 and see that we are on the kernel page
564 so this process is never scheduled off
565 or is ever sent any signal of any sort,
566 thus it is wholly atomic from usrspaces
567 perspective
568 */
569cas_action:
570#if defined CONFIG_SMP && defined ENABLE_LWS_DEBUG
571 /* DEBUG */
572 mfctl %cr27, %r1
573 stw %r1, 4(%sr2,%r20)
574#endif
575 /* The load and store could fail */
5761: ldw 0(%sr3,%r26), %r28
577 sub,<> %r28, %r25, %r0
5782: stw %r24, 0(%sr3,%r26)
579#ifdef CONFIG_SMP
580 /* Free lock */
581 stw %r20, 0(%sr2,%r20)
582# ifdef ENABLE_LWS_DEBUG
583 /* Clear thread register indicator */
584 stw %r0, 4(%sr2,%r20)
585# endif
586#endif
587 /* Return to userspace, set no error */
588 b lws_exit
589 copy %r0, %r21
590
5913:
592 /* Error occured on load or store */
593#ifdef CONFIG_SMP
594 /* Free lock */
595 stw %r20, 0(%sr2,%r20)
596# ifdef ENABLE_LWS_DEBUG
597 stw %r0, 4(%sr2,%r20)
598# endif
599#endif
600 b lws_exit
601 ldo -EFAULT(%r0),%r21 /* set errno */
602 nop
603 nop
604 nop
605 nop
606
607 /* Two exception table entries, one for the load,
608 the other for the store. Either return -EFAULT.
609 Each of the entries must be relocated. */
610 .section __ex_table,"aw"
611#ifdef __LP64__
612 /* Pad the address calculation */
613 .word 0,(2b - linux_gateway_page)
614 .word 0,(3b - linux_gateway_page)
615#else
616 .word (2b - linux_gateway_page)
617 .word (3b - linux_gateway_page)
618#endif
619 .previous
620
621 .section __ex_table,"aw"
622#ifdef __LP64__
623 /* Pad the address calculation */
624 .word 0,(1b - linux_gateway_page)
625 .word 0,(3b - linux_gateway_page)
626#else
627 .word (1b - linux_gateway_page)
628 .word (3b - linux_gateway_page)
629#endif
630 .previous
631
632end_compare_and_swap:
633
634 /* Make sure nothing else is placed on this page */
635 .align 4096
636 .export end_linux_gateway_page
637end_linux_gateway_page:
638
639 /* Relocate symbols assuming linux_gateway_page is mapped
640 to virtual address 0x0 */
641#ifdef __LP64__
642 /* FIXME: The code will always be on the gateay page
643 and thus it will be on the first 4k, the
644 assembler seems to think that the final
645 subtraction result is only a word in
646 length, so we pad the value.
647 */
648#define LWS_ENTRY(_name_) .word 0,(lws_##_name_ - linux_gateway_page)
649#else
650#define LWS_ENTRY(_name_) .word (lws_##_name_ - linux_gateway_page)
651#endif
652
653 .align 4096
654 /* Light-weight-syscall table */
655 /* Start of lws table. */
656 .export lws_table
657.Llws_table:
658lws_table:
659 LWS_ENTRY(compare_and_swap32) /* 0 - ELF32 Atomic compare and swap */
660 LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic compare and swap */
661 /* End of lws table */
662
663 .align 4096
664 .export sys_call_table
665.Lsys_call_table:
666sys_call_table:
667#include "syscall_table.S"
668
669#ifdef __LP64__
670 .align 4096
671 .export sys_call_table64
672.Lsys_call_table64:
673sys_call_table64:
674#define SYSCALL_TABLE_64BIT
675#include "syscall_table.S"
676#endif
677
678#ifdef CONFIG_SMP
679 /*
680 All light-weight-syscall atomic operations
681 will use this set of locks
682 */
683 .section .data
684 .align 4096
685 .export lws_lock_start
686.Llws_lock_start:
687lws_lock_start:
688 /* lws locks */
689 .align 16
690 .rept 16
691 /* Keep locks aligned at 16-bytes */
692 .word 1
693 .word 0
694 .word 0
695 .word 0
696 .endr
697 .previous
698#endif
699/* CONFIG_SMP for lws_lock_start */
700
701.end
702
703
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 @@
1/* System Call Table
2 *
3 * Copyright (C) 1999-2004 Matthew Wilcox <willy at parisc-linux.org>
4 * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org>
5 * Copyright (C) 2000 Alan Modra <amodra at parisc-linux.org>
6 * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
7 * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
8 * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
9 * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org>
10 * Copyright (C) 2000 Grant Grundler <grundler at parisc-linux.org>
11 * Copyright (C) 2001 Richard Hirst <rhirst with parisc-linux.org>
12 * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
13 * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
14 * Copyright (C) 2000-2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
15 * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
16 *
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 */
32
33#undef ENTRY_SAME
34#undef ENTRY_DIFF
35#undef ENTRY_UHOH
36#undef ENTRY_COMP
37#undef ENTRY_OURS
38#if defined(__LP64__) && !defined(SYSCALL_TABLE_64BIT)
39/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
40 * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
41 * implementation is required on wide palinux. Use ENTRY_COMP where
42 * the compatability layer has a useful 32-bit implementation.
43 */
44#define ENTRY_SAME(_name_) .dword sys_##_name_
45#define ENTRY_DIFF(_name_) .dword sys32_##_name_
46#define ENTRY_UHOH(_name_) .dword sys32_##unimplemented
47#define ENTRY_OURS(_name_) .dword parisc_##_name_
48#define ENTRY_COMP(_name_) .dword compat_sys_##_name_
49#elif defined(__LP64__) && defined(SYSCALL_TABLE_64BIT)
50#define ENTRY_SAME(_name_) .dword sys_##_name_
51#define ENTRY_DIFF(_name_) .dword sys_##_name_
52#define ENTRY_UHOH(_name_) .dword sys_##_name_
53#define ENTRY_OURS(_name_) .dword sys_##_name_
54#define ENTRY_COMP(_name_) .dword sys_##_name_
55#else
56#define ENTRY_SAME(_name_) .word sys_##_name_
57#define ENTRY_DIFF(_name_) .word sys_##_name_
58#define ENTRY_UHOH(_name_) .word sys_##_name_
59#define ENTRY_OURS(_name_) .word parisc_##_name_
60#define ENTRY_COMP(_name_) .word sys_##_name_
61#endif
62
63 ENTRY_SAME(restart_syscall) /* 0 */
64 ENTRY_SAME(exit)
65 ENTRY_SAME(fork_wrapper)
66 ENTRY_SAME(read)
67 ENTRY_SAME(write)
68 ENTRY_SAME(open) /* 5 */
69 ENTRY_SAME(close)
70 ENTRY_SAME(waitpid)
71 ENTRY_SAME(creat)
72 ENTRY_SAME(link)
73 ENTRY_SAME(unlink) /* 10 */
74 ENTRY_DIFF(execve_wrapper)
75 ENTRY_SAME(chdir)
76 /* See comments in kernel/time.c!!! Maybe we don't need this? */
77 ENTRY_COMP(time)
78 ENTRY_SAME(mknod)
79 ENTRY_SAME(chmod) /* 15 */
80 ENTRY_SAME(lchown)
81 ENTRY_SAME(socket)
82 /* struct stat is MAYBE identical wide and narrow ?? */
83 ENTRY_COMP(newstat)
84 ENTRY_DIFF(lseek)
85 ENTRY_SAME(getpid) /* 20 */
86 /* the 'void * data' parameter may need re-packing in wide */
87 ENTRY_COMP(mount)
88 /* concerned about struct sockaddr in wide/narrow */
89 /* ---> I think sockaddr is OK unless the compiler packs the struct */
90 /* differently to align the char array */
91 ENTRY_SAME(bind)
92 ENTRY_SAME(setuid)
93 ENTRY_SAME(getuid)
94 ENTRY_COMP(stime) /* 25 */
95 ENTRY_SAME(ptrace)
96 ENTRY_SAME(alarm)
97 /* see stat comment */
98 ENTRY_COMP(newfstat)
99 ENTRY_SAME(pause)
100 /* struct utimbuf uses time_t which might vary */
101 ENTRY_COMP(utime) /* 30 */
102 /* struct sockaddr... */
103 ENTRY_SAME(connect)
104 ENTRY_SAME(listen)
105 ENTRY_SAME(access)
106 ENTRY_SAME(nice)
107 /* struct sockaddr... */
108 ENTRY_SAME(accept) /* 35 */
109 ENTRY_SAME(sync)
110 ENTRY_SAME(kill)
111 ENTRY_SAME(rename)
112 ENTRY_SAME(mkdir)
113 ENTRY_SAME(rmdir) /* 40 */
114 ENTRY_SAME(dup)
115 ENTRY_SAME(pipe)
116 ENTRY_COMP(times)
117 /* struct sockaddr... */
118 ENTRY_SAME(getsockname)
119 /* it seems possible brk() could return a >4G pointer... */
120 ENTRY_SAME(brk) /* 45 */
121 ENTRY_SAME(setgid)
122 ENTRY_SAME(getgid)
123 ENTRY_SAME(signal)
124 ENTRY_SAME(geteuid)
125 ENTRY_SAME(getegid) /* 50 */
126 ENTRY_SAME(acct)
127 ENTRY_SAME(umount)
128 /* struct sockaddr... */
129 ENTRY_SAME(getpeername)
130 ENTRY_COMP(ioctl)
131 ENTRY_COMP(fcntl) /* 55 */
132 ENTRY_SAME(socketpair)
133 ENTRY_SAME(setpgid)
134 ENTRY_SAME(send)
135 ENTRY_SAME(newuname)
136 ENTRY_SAME(umask) /* 60 */
137 ENTRY_SAME(chroot)
138 ENTRY_SAME(ustat)
139 ENTRY_SAME(dup2)
140 ENTRY_SAME(getppid)
141 ENTRY_SAME(getpgrp) /* 65 */
142 ENTRY_SAME(setsid)
143 ENTRY_SAME(pivot_root)
144 /* I don't like this */
145 ENTRY_UHOH(sgetmask)
146 ENTRY_UHOH(ssetmask)
147 ENTRY_SAME(setreuid) /* 70 */
148 ENTRY_SAME(setregid)
149 ENTRY_SAME(mincore)
150 ENTRY_COMP(sigpending)
151 ENTRY_SAME(sethostname)
152 /* Following 3 have linux-common-code structs containing longs -( */
153 ENTRY_COMP(setrlimit) /* 75 */
154 ENTRY_COMP(getrlimit)
155 ENTRY_COMP(getrusage)
156 /* struct timeval and timezone are maybe?? consistent wide and narrow */
157 ENTRY_DIFF(gettimeofday)
158 ENTRY_DIFF(settimeofday)
159 ENTRY_SAME(getgroups) /* 80 */
160 ENTRY_SAME(setgroups)
161 /* struct socketaddr... */
162 ENTRY_SAME(sendto)
163 ENTRY_SAME(symlink)
164 /* see stat comment */
165 ENTRY_COMP(newlstat)
166 ENTRY_SAME(readlink) /* 85 */
167 ENTRY_SAME(ni_syscall) /* was uselib */
168 ENTRY_SAME(swapon)
169 ENTRY_SAME(reboot)
170 ENTRY_SAME(mmap2)
171 ENTRY_SAME(mmap) /* 90 */
172 ENTRY_SAME(munmap)
173 ENTRY_SAME(truncate)
174 ENTRY_SAME(ftruncate)
175 ENTRY_SAME(fchmod)
176 ENTRY_SAME(fchown) /* 95 */
177 ENTRY_SAME(getpriority)
178 ENTRY_SAME(setpriority)
179 ENTRY_SAME(recv)
180 ENTRY_COMP(statfs)
181 ENTRY_COMP(fstatfs) /* 100 */
182 ENTRY_SAME(stat64)
183 ENTRY_SAME(ni_syscall) /* was socketcall */
184 ENTRY_SAME(syslog)
185 /* even though manpage says struct timeval contains longs, ours has
186 * time_t and suseconds_t -- both of which are safe wide/narrow */
187 ENTRY_COMP(setitimer)
188 ENTRY_COMP(getitimer) /* 105 */
189 ENTRY_SAME(capget)
190 ENTRY_SAME(capset)
191 ENTRY_OURS(pread64)
192 ENTRY_OURS(pwrite64)
193 ENTRY_SAME(getcwd) /* 110 */
194 ENTRY_SAME(vhangup)
195 ENTRY_SAME(fstat64)
196 ENTRY_SAME(vfork_wrapper)
197 /* struct rusage contains longs... */
198 ENTRY_COMP(wait4)
199 ENTRY_SAME(swapoff) /* 115 */
200 ENTRY_DIFF(sysinfo)
201 ENTRY_SAME(shutdown)
202 ENTRY_SAME(fsync)
203 ENTRY_SAME(madvise)
204 ENTRY_SAME(clone_wrapper) /* 120 */
205 ENTRY_SAME(setdomainname)
206 ENTRY_DIFF(sendfile)
207 /* struct sockaddr... */
208 ENTRY_SAME(recvfrom)
209 /* struct timex contains longs */
210 ENTRY_DIFF(adjtimex)
211 ENTRY_SAME(mprotect) /* 125 */
212 /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
213 ENTRY_COMP(sigprocmask)
214 ENTRY_SAME(ni_syscall) /* create_module */
215 ENTRY_SAME(init_module)
216 ENTRY_SAME(delete_module)
217 ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */
218 /* time_t inside struct dqblk */
219 ENTRY_SAME(quotactl)
220 ENTRY_SAME(getpgid)
221 ENTRY_SAME(fchdir)
222 ENTRY_SAME(bdflush)
223 ENTRY_SAME(sysfs) /* 135 */
224 ENTRY_SAME(personality)
225 ENTRY_SAME(ni_syscall) /* for afs_syscall */
226 ENTRY_SAME(setfsuid)
227 ENTRY_SAME(setfsgid)
228 /* I think this might work */
229 ENTRY_SAME(llseek) /* 140 */
230 /* struct linux_dirent has longs, like 'unsigned long d_ino' which
231 * almost definitely should be 'ino_t d_ino' but it's too late now */
232 ENTRY_DIFF(getdents)
233 /* it is POSSIBLE that select will be OK because even though fd_set
234 * contains longs, the macros and sizes are clever. */
235 ENTRY_COMP(select)
236 ENTRY_SAME(flock)
237 ENTRY_SAME(msync)
238 /* struct iovec contains pointers */
239 ENTRY_COMP(readv) /* 145 */
240 ENTRY_COMP(writev)
241 ENTRY_SAME(getsid)
242 ENTRY_SAME(fdatasync)
243 /* struct __sysctl_args is a mess */
244 ENTRY_DIFF(sysctl)
245 ENTRY_SAME(mlock) /* 150 */
246 ENTRY_SAME(munlock)
247 ENTRY_SAME(mlockall)
248 ENTRY_SAME(munlockall)
249 /* struct sched_param is ok for now */
250 ENTRY_SAME(sched_setparam)
251 ENTRY_SAME(sched_getparam) /* 155 */
252 ENTRY_SAME(sched_setscheduler)
253 ENTRY_SAME(sched_getscheduler)
254 ENTRY_SAME(sched_yield)
255 ENTRY_SAME(sched_get_priority_max)
256 ENTRY_SAME(sched_get_priority_min) /* 160 */
257 /* These 2 would've worked if someone had defined struct timespec
258 * carefully, like timeval for example (which is about the same).
259 * Unfortunately it contains a long :-( */
260 ENTRY_DIFF(sched_rr_get_interval)
261 ENTRY_COMP(nanosleep)
262 ENTRY_SAME(mremap)
263 ENTRY_SAME(setresuid)
264 ENTRY_SAME(getresuid) /* 165 */
265 ENTRY_DIFF(sigaltstack_wrapper)
266 ENTRY_SAME(ni_syscall) /* query_module */
267 ENTRY_SAME(poll)
268 /* structs contain pointers and an in_addr... */
269 ENTRY_COMP(nfsservctl)
270 ENTRY_SAME(setresgid) /* 170 */
271 ENTRY_SAME(getresgid)
272 ENTRY_SAME(prctl)
273 /* signals need a careful review */
274 ENTRY_SAME(rt_sigreturn_wrapper)
275 ENTRY_DIFF(rt_sigaction)
276 ENTRY_DIFF(rt_sigprocmask) /* 175 */
277 ENTRY_DIFF(rt_sigpending)
278 ENTRY_COMP(rt_sigtimedwait)
279 /* even though the struct siginfo_t is different, it appears like
280 * all the paths use values which should be same wide and narrow.
281 * Also the struct is padded to 128 bytes which means we don't have
282 * to worry about faulting trying to copy in a larger 64-bit
283 * struct from a 32-bit user-space app.
284 */
285 ENTRY_SAME(rt_sigqueueinfo)
286 ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
287 ENTRY_SAME(chown) /* 180 */
288 /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
289 ENTRY_COMP(setsockopt)
290 ENTRY_SAME(getsockopt)
291 ENTRY_COMP(sendmsg)
292 ENTRY_COMP(recvmsg)
293 ENTRY_SAME(semop) /* 185 */
294 ENTRY_SAME(semget)
295 ENTRY_DIFF(semctl)
296 ENTRY_DIFF(msgsnd)
297 ENTRY_DIFF(msgrcv)
298 ENTRY_SAME(msgget) /* 190 */
299 ENTRY_SAME(msgctl)
300 ENTRY_SAME(shmat_wrapper)
301 ENTRY_SAME(shmdt)
302 ENTRY_SAME(shmget)
303 ENTRY_SAME(shmctl) /* 195 */
304 ENTRY_SAME(ni_syscall) /* streams1 */
305 ENTRY_SAME(ni_syscall) /* streams2 */
306 ENTRY_SAME(lstat64)
307 ENTRY_OURS(truncate64)
308 ENTRY_OURS(ftruncate64) /* 200 */
309 ENTRY_SAME(getdents64)
310 ENTRY_COMP(fcntl64)
311 ENTRY_SAME(ni_syscall) /* attrctl -- dead */
312 ENTRY_SAME(ni_syscall) /* acl_get -- dead */
313 ENTRY_SAME(ni_syscall) /* 205 (acl_set -- dead) */
314 ENTRY_SAME(gettid)
315 ENTRY_OURS(readahead)
316 ENTRY_SAME(tkill)
317 ENTRY_SAME(sendfile64)
318 ENTRY_COMP(futex) /* 210 */
319 ENTRY_COMP(sched_setaffinity)
320 ENTRY_COMP(sched_getaffinity)
321 ENTRY_SAME(ni_syscall) /* set_thread_area */
322 ENTRY_SAME(ni_syscall) /* get_thread_area */
323 ENTRY_SAME(io_setup) /* 215 */
324 ENTRY_SAME(io_destroy)
325 ENTRY_SAME(io_getevents)
326 ENTRY_SAME(io_submit)
327 ENTRY_SAME(io_cancel)
328 ENTRY_SAME(alloc_hugepages) /* 220 */
329 ENTRY_SAME(free_hugepages)
330 ENTRY_SAME(exit_group)
331 ENTRY_DIFF(lookup_dcookie)
332 ENTRY_SAME(epoll_create)
333 ENTRY_SAME(epoll_ctl) /* 225 */
334 ENTRY_SAME(epoll_wait)
335 ENTRY_SAME(remap_file_pages)
336 ENTRY_SAME(semtimedop)
337 ENTRY_SAME(mq_open)
338 ENTRY_SAME(mq_unlink) /* 230 */
339 ENTRY_SAME(mq_timedsend)
340 ENTRY_SAME(mq_timedreceive)
341 ENTRY_SAME(mq_notify)
342 ENTRY_SAME(mq_getsetattr)
343 ENTRY_COMP(waitid) /* 235 */
344 ENTRY_OURS(fadvise64_64)
345 ENTRY_SAME(set_tid_address)
346 ENTRY_SAME(setxattr)
347 ENTRY_SAME(lsetxattr)
348 ENTRY_SAME(fsetxattr) /* 240 */
349 ENTRY_SAME(getxattr)
350 ENTRY_SAME(lgetxattr)
351 ENTRY_SAME(fgetxattr)
352 ENTRY_SAME(listxattr)
353 ENTRY_SAME(llistxattr) /* 245 */
354 ENTRY_SAME(flistxattr)
355 ENTRY_SAME(removexattr)
356 ENTRY_SAME(lremovexattr)
357 ENTRY_SAME(fremovexattr)
358 ENTRY_COMP(timer_create) /* 250 */
359 ENTRY_COMP(timer_settime)
360 ENTRY_COMP(timer_gettime)
361 ENTRY_SAME(timer_getoverrun)
362 ENTRY_SAME(timer_delete)
363 ENTRY_COMP(clock_settime) /* 255 */
364 ENTRY_COMP(clock_gettime)
365 ENTRY_COMP(clock_getres)
366 ENTRY_COMP(clock_nanosleep)
367 ENTRY_SAME(tgkill)
368 ENTRY_COMP(mbind) /* 260 */
369 ENTRY_COMP(get_mempolicy)
370 ENTRY_COMP(set_mempolicy)
371 /* Nothing yet */
372
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 @@
1/*
2 * linux/arch/parisc/kernel/time.c
3 *
4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
5 * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King
6 * Copyright (C) 1999 SuSE GmbH, (Philipp Rumpf, prumpf@tux.org)
7 *
8 * 1994-07-02 Alan Modra
9 * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
10 * 1998-12-20 Updated NTP code according to technical memorandum Jan '96
11 * "A Kernel Model for Precision Timekeeping" by Dave Mills
12 */
13#include <linux/config.h>
14#include <linux/errno.h>
15#include <linux/module.h>
16#include <linux/sched.h>
17#include <linux/kernel.h>
18#include <linux/param.h>
19#include <linux/string.h>
20#include <linux/mm.h>
21#include <linux/interrupt.h>
22#include <linux/time.h>
23#include <linux/init.h>
24#include <linux/smp.h>
25#include <linux/profile.h>
26
27#include <asm/uaccess.h>
28#include <asm/io.h>
29#include <asm/irq.h>
30#include <asm/param.h>
31#include <asm/pdc.h>
32#include <asm/led.h>
33
34#include <linux/timex.h>
35
36u64 jiffies_64 = INITIAL_JIFFIES;
37
38EXPORT_SYMBOL(jiffies_64);
39
40/* xtime and wall_jiffies keep wall-clock time */
41extern unsigned long wall_jiffies;
42
43static long clocktick; /* timer cycles per tick */
44static long halftick;
45
46#ifdef CONFIG_SMP
47extern void smp_do_timer(struct pt_regs *regs);
48#endif
49
50irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
51{
52 long now;
53 long next_tick;
54 int nticks;
55 int cpu = smp_processor_id();
56
57 profile_tick(CPU_PROFILING, regs);
58
59 now = mfctl(16);
60 /* initialize next_tick to time at last clocktick */
61 next_tick = cpu_data[cpu].it_value;
62
63 /* since time passes between the interrupt and the mfctl()
64 * above, it is never true that last_tick + clocktick == now. If we
65 * never miss a clocktick, we could set next_tick = last_tick + clocktick
66 * but maybe we'll miss ticks, hence the loop.
67 *
68 * Variables are *signed*.
69 */
70
71 nticks = 0;
72 while((next_tick - now) < halftick) {
73 next_tick += clocktick;
74 nticks++;
75 }
76 mtctl(next_tick, 16);
77 cpu_data[cpu].it_value = next_tick;
78
79 while (nticks--) {
80#ifdef CONFIG_SMP
81 smp_do_timer(regs);
82#else
83 update_process_times(user_mode(regs));
84#endif
85 if (cpu == 0) {
86 write_seqlock(&xtime_lock);
87 do_timer(regs);
88 write_sequnlock(&xtime_lock);
89 }
90 }
91
92#ifdef CONFIG_CHASSIS_LCD_LED
93 /* Only schedule the led tasklet on cpu 0, and only if it
94 * is enabled.
95 */
96 if (cpu == 0 && !atomic_read(&led_tasklet.count))
97 tasklet_schedule(&led_tasklet);
98#endif
99
100 /* check soft power switch status */
101 if (cpu == 0 && !atomic_read(&power_tasklet.count))
102 tasklet_schedule(&power_tasklet);
103
104 return IRQ_HANDLED;
105}
106
107/*** converted from ia64 ***/
108/*
109 * Return the number of micro-seconds that elapsed since the last
110 * update to wall time (aka xtime aka wall_jiffies). The xtime_lock
111 * must be at least read-locked when calling this routine.
112 */
113static inline unsigned long
114gettimeoffset (void)
115{
116#ifndef CONFIG_SMP
117 /*
118 * FIXME: This won't work on smp because jiffies are updated by cpu 0.
119 * Once parisc-linux learns the cr16 difference between processors,
120 * this could be made to work.
121 */
122 long last_tick;
123 long elapsed_cycles;
124
125 /* it_value is the intended time of the next tick */
126 last_tick = cpu_data[smp_processor_id()].it_value;
127
128 /* Subtract one tick and account for possible difference between
129 * when we expected the tick and when it actually arrived.
130 * (aka wall vs real)
131 */
132 last_tick -= clocktick * (jiffies - wall_jiffies + 1);
133 elapsed_cycles = mfctl(16) - last_tick;
134
135 /* the precision of this math could be improved */
136 return elapsed_cycles / (PAGE0->mem_10msec / 10000);
137#else
138 return 0;
139#endif
140}
141
142void
143do_gettimeofday (struct timeval *tv)
144{
145 unsigned long flags, seq, usec, sec;
146
147 do {
148 seq = read_seqbegin_irqsave(&xtime_lock, flags);
149 usec = gettimeoffset();
150 sec = xtime.tv_sec;
151 usec += (xtime.tv_nsec / 1000);
152 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
153
154 while (usec >= 1000000) {
155 usec -= 1000000;
156 ++sec;
157 }
158
159 tv->tv_sec = sec;
160 tv->tv_usec = usec;
161}
162
163EXPORT_SYMBOL(do_gettimeofday);
164
165int
166do_settimeofday (struct timespec *tv)
167{
168 time_t wtm_sec, sec = tv->tv_sec;
169 long wtm_nsec, nsec = tv->tv_nsec;
170
171 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
172 return -EINVAL;
173
174 write_seqlock_irq(&xtime_lock);
175 {
176 /*
177 * This is revolting. We need to set "xtime"
178 * correctly. However, the value in this location is
179 * the value at the most recent update of wall time.
180 * Discover what correction gettimeofday would have
181 * done, and then undo it!
182 */
183 nsec -= gettimeoffset() * 1000;
184
185 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
186 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
187
188 set_normalized_timespec(&xtime, sec, nsec);
189 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
190
191 time_adjust = 0; /* stop active adjtime() */
192 time_status |= STA_UNSYNC;
193 time_maxerror = NTP_PHASE_LIMIT;
194 time_esterror = NTP_PHASE_LIMIT;
195 }
196 write_sequnlock_irq(&xtime_lock);
197 clock_was_set();
198 return 0;
199}
200EXPORT_SYMBOL(do_settimeofday);
201
202/*
203 * XXX: We can do better than this.
204 * Returns nanoseconds
205 */
206
207unsigned long long sched_clock(void)
208{
209 return (unsigned long long)jiffies * (1000000000 / HZ);
210}
211
212
213void __init time_init(void)
214{
215 unsigned long next_tick;
216 static struct pdc_tod tod_data;
217
218 clocktick = (100 * PAGE0->mem_10msec) / HZ;
219 halftick = clocktick / 2;
220
221 /* Setup clock interrupt timing */
222
223 next_tick = mfctl(16);
224 next_tick += clocktick;
225 cpu_data[smp_processor_id()].it_value = next_tick;
226
227 /* kick off Itimer (CR16) */
228 mtctl(next_tick, 16);
229
230 if(pdc_tod_read(&tod_data) == 0) {
231 write_seqlock_irq(&xtime_lock);
232 xtime.tv_sec = tod_data.tod_sec;
233 xtime.tv_nsec = tod_data.tod_usec * 1000;
234 set_normalized_timespec(&wall_to_monotonic,
235 -xtime.tv_sec, -xtime.tv_nsec);
236 write_sequnlock_irq(&xtime_lock);
237 } else {
238 printk(KERN_ERR "Error reading tod clock\n");
239 xtime.tv_sec = 0;
240 xtime.tv_nsec = 0;
241 }
242}
243
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 @@
1/*
2 * arch/parisc/kernel/topology.c - Populate driverfs with topology information
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12 * NON INFRINGEMENT. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <linux/init.h>
21#include <linux/smp.h>
22#include <linux/cpu.h>
23
24static struct cpu cpu_devices[NR_CPUS];
25
26static int __init topology_init(void)
27{
28 struct node *parent = NULL;
29 int num;
30
31 for_each_present_cpu(num) {
32 register_cpu(&cpu_devices[num], num, parent);
33 }
34 return 0;
35}
36
37subsys_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 @@
1/*
2 * linux/arch/parisc/traps.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org>
6 */
7
8/*
9 * 'Traps.c' handles hardware traps and faults after we have saved some
10 * state in 'asm.s'.
11 */
12
13#include <linux/config.h>
14#include <linux/sched.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/errno.h>
18#include <linux/ptrace.h>
19#include <linux/timer.h>
20#include <linux/mm.h>
21#include <linux/module.h>
22#include <linux/smp.h>
23#include <linux/smp_lock.h>
24#include <linux/spinlock.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/console.h>
28#include <linux/kallsyms.h>
29
30#include <asm/assembly.h>
31#include <asm/system.h>
32#include <asm/uaccess.h>
33#include <asm/io.h>
34#include <asm/irq.h>
35#include <asm/traps.h>
36#include <asm/unaligned.h>
37#include <asm/atomic.h>
38#include <asm/smp.h>
39#include <asm/pdc.h>
40#include <asm/pdc_chassis.h>
41#include <asm/unwind.h>
42
43#include "../math-emu/math-emu.h" /* for handle_fpe() */
44
45#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
46 /* dumped to the console via printk) */
47
48#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
49DEFINE_SPINLOCK(pa_dbit_lock);
50#endif
51
52int printbinary(char *buf, unsigned long x, int nbits)
53{
54 unsigned long mask = 1UL << (nbits - 1);
55 while (mask != 0) {
56 *buf++ = (mask & x ? '1' : '0');
57 mask >>= 1;
58 }
59 *buf = '\0';
60
61 return nbits;
62}
63
64#ifdef __LP64__
65#define RFMT "%016lx"
66#else
67#define RFMT "%08lx"
68#endif
69
70void show_regs(struct pt_regs *regs)
71{
72 int i;
73 char buf[128], *p;
74 char *level;
75 unsigned long cr30;
76 unsigned long cr31;
77
78 level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
79
80 printk("%s\n", level); /* don't want to have that pretty register dump messed up */
81
82 printk("%s YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);
83 printbinary(buf, regs->gr[0], 32);
84 printk("%sPSW: %s %s\n", level, buf, print_tainted());
85
86 for (i = 0; i < 32; i += 4) {
87 int j;
88 p = buf;
89 p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3);
90 for (j = 0; j < 4; j++) {
91 p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]);
92 }
93 printk("%s\n", buf);
94 }
95
96 for (i = 0; i < 8; i += 4) {
97 int j;
98 p = buf;
99 p += sprintf(p, "%ssr%d-%d ", level, i, i + 3);
100 for (j = 0; j < 4; j++) {
101 p += sprintf(p, " " RFMT, regs->sr[i + j]);
102 }
103 printk("%s\n", buf);
104 }
105
106#if RIDICULOUSLY_VERBOSE
107 for (i = 0; i < 32; i += 2)
108 printk("%sFR%02d : %016lx FR%2d : %016lx", level, i,
109 regs->fr[i], i+1, regs->fr[i+1]);
110#endif
111
112 cr30 = mfctl(30);
113 cr31 = mfctl(31);
114 printk("%s\n", level);
115 printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n",
116 level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
117 printk("%s IIR: %08lx ISR: " RFMT " IOR: " RFMT "\n",
118 level, regs->iir, regs->isr, regs->ior);
119 printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n",
120 level, current_thread_info()->cpu, cr30, cr31);
121 printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);
122 printk(level);
123 print_symbol(" IAOQ[0]: %s\n", regs->iaoq[0]);
124 printk(level);
125 print_symbol(" IAOQ[1]: %s\n", regs->iaoq[1]);
126 printk(level);
127 print_symbol(" RP(r2): %s\n", regs->gr[2]);
128}
129
130
131void dump_stack(void)
132{
133 show_stack(NULL, NULL);
134}
135
136EXPORT_SYMBOL(dump_stack);
137
138static void do_show_stack(struct unwind_frame_info *info)
139{
140 int i = 1;
141
142 printk("Backtrace:\n");
143 while (i <= 16) {
144 if (unwind_once(info) < 0 || info->ip == 0)
145 break;
146
147 if (__kernel_text_address(info->ip)) {
148 printk(" [<" RFMT ">] ", info->ip);
149#ifdef CONFIG_KALLSYMS
150 print_symbol("%s\n", info->ip);
151#else
152 if ((i & 0x03) == 0)
153 printk("\n");
154#endif
155 i++;
156 }
157 }
158 printk("\n");
159}
160
161void show_stack(struct task_struct *task, unsigned long *s)
162{
163 struct unwind_frame_info info;
164
165 if (!task) {
166 unsigned long sp;
167 struct pt_regs *r;
168
169HERE:
170 asm volatile ("copy %%r30, %0" : "=r"(sp));
171 r = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
172 if (!r)
173 return;
174 memset(r, 0, sizeof(struct pt_regs));
175 r->iaoq[0] = (unsigned long)&&HERE;
176 r->gr[2] = (unsigned long)__builtin_return_address(0);
177 r->gr[30] = sp;
178 unwind_frame_init(&info, current, r);
179 kfree(r);
180 } else {
181 unwind_frame_init_from_blocked_task(&info, task);
182 }
183
184 do_show_stack(&info);
185}
186
187void die_if_kernel(char *str, struct pt_regs *regs, long err)
188{
189 if (user_mode(regs)) {
190 if (err == 0)
191 return; /* STFU */
192
193 printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
194 current->comm, current->pid, str, err, regs->iaoq[0]);
195#ifdef PRINT_USER_FAULTS
196 /* XXX for debugging only */
197 show_regs(regs);
198#endif
199 return;
200 }
201
202 oops_in_progress = 1;
203
204 /* Amuse the user in a SPARC fashion */
205 printk(
206" _______________________________ \n"
207" < Your System ate a SPARC! Gah! >\n"
208" ------------------------------- \n"
209" \\ ^__^\n"
210" \\ (xx)\\_______\n"
211" (__)\\ )\\/\\\n"
212" U ||----w |\n"
213" || ||\n");
214
215 /* unlock the pdc lock if necessary */
216 pdc_emergency_unlock();
217
218 /* maybe the kernel hasn't booted very far yet and hasn't been able
219 * to initialize the serial or STI console. In that case we should
220 * re-enable the pdc console, so that the user will be able to
221 * identify the problem. */
222 if (!console_drivers)
223 pdc_console_restart();
224
225 printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
226 current->comm, current->pid, str, err);
227 show_regs(regs);
228
229 /* Wot's wrong wif bein' racy? */
230 if (current->thread.flags & PARISC_KERNEL_DEATH) {
231 printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
232 local_irq_enable();
233 while (1);
234 }
235
236 current->thread.flags |= PARISC_KERNEL_DEATH;
237 do_exit(SIGSEGV);
238}
239
240int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
241{
242 return syscall(regs);
243}
244
245/* gdb uses break 4,8 */
246#define GDB_BREAK_INSN 0x10004
247void handle_gdb_break(struct pt_regs *regs, int wot)
248{
249 struct siginfo si;
250
251 si.si_code = wot;
252 si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
253 si.si_signo = SIGTRAP;
254 si.si_errno = 0;
255 force_sig_info(SIGTRAP, &si, current);
256}
257
258void handle_break(unsigned iir, struct pt_regs *regs)
259{
260 struct siginfo si;
261
262 switch(iir) {
263 case 0x00:
264#ifdef PRINT_USER_FAULTS
265 printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n",
266 current->pid, current->comm);
267#endif
268 die_if_kernel("Breakpoint", regs, 0);
269#ifdef PRINT_USER_FAULTS
270 show_regs(regs);
271#endif
272 si.si_code = TRAP_BRKPT;
273 si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
274 si.si_signo = SIGTRAP;
275 force_sig_info(SIGTRAP, &si, current);
276 break;
277
278 case GDB_BREAK_INSN:
279 die_if_kernel("Breakpoint", regs, 0);
280 handle_gdb_break(regs, TRAP_BRKPT);
281 break;
282
283 default:
284#ifdef PRINT_USER_FAULTS
285 printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n",
286 iir, current->pid, current->comm);
287 show_regs(regs);
288#endif
289 si.si_signo = SIGTRAP;
290 si.si_code = TRAP_BRKPT;
291 si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
292 force_sig_info(SIGTRAP, &si, current);
293 return;
294 }
295}
296
297
298int handle_toc(void)
299{
300 printk(KERN_CRIT "TOC call.\n");
301 return 0;
302}
303
304static void default_trap(int code, struct pt_regs *regs)
305{
306 printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id());
307 show_regs(regs);
308}
309
310void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
311
312
313void transfer_pim_to_trap_frame(struct pt_regs *regs)
314{
315 register int i;
316 extern unsigned int hpmc_pim_data[];
317 struct pdc_hpmc_pim_11 *pim_narrow;
318 struct pdc_hpmc_pim_20 *pim_wide;
319
320 if (boot_cpu_data.cpu_type >= pcxu) {
321
322 pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
323
324 /*
325 * Note: The following code will probably generate a
326 * bunch of truncation error warnings from the compiler.
327 * Could be handled with an ifdef, but perhaps there
328 * is a better way.
329 */
330
331 regs->gr[0] = pim_wide->cr[22];
332
333 for (i = 1; i < 32; i++)
334 regs->gr[i] = pim_wide->gr[i];
335
336 for (i = 0; i < 32; i++)
337 regs->fr[i] = pim_wide->fr[i];
338
339 for (i = 0; i < 8; i++)
340 regs->sr[i] = pim_wide->sr[i];
341
342 regs->iasq[0] = pim_wide->cr[17];
343 regs->iasq[1] = pim_wide->iasq_back;
344 regs->iaoq[0] = pim_wide->cr[18];
345 regs->iaoq[1] = pim_wide->iaoq_back;
346
347 regs->sar = pim_wide->cr[11];
348 regs->iir = pim_wide->cr[19];
349 regs->isr = pim_wide->cr[20];
350 regs->ior = pim_wide->cr[21];
351 }
352 else {
353 pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
354
355 regs->gr[0] = pim_narrow->cr[22];
356
357 for (i = 1; i < 32; i++)
358 regs->gr[i] = pim_narrow->gr[i];
359
360 for (i = 0; i < 32; i++)
361 regs->fr[i] = pim_narrow->fr[i];
362
363 for (i = 0; i < 8; i++)
364 regs->sr[i] = pim_narrow->sr[i];
365
366 regs->iasq[0] = pim_narrow->cr[17];
367 regs->iasq[1] = pim_narrow->iasq_back;
368 regs->iaoq[0] = pim_narrow->cr[18];
369 regs->iaoq[1] = pim_narrow->iaoq_back;
370
371 regs->sar = pim_narrow->cr[11];
372 regs->iir = pim_narrow->cr[19];
373 regs->isr = pim_narrow->cr[20];
374 regs->ior = pim_narrow->cr[21];
375 }
376
377 /*
378 * The following fields only have meaning if we came through
379 * another path. So just zero them here.
380 */
381
382 regs->ksp = 0;
383 regs->kpc = 0;
384 regs->orig_r28 = 0;
385}
386
387
388/*
389 * This routine is called as a last resort when everything else
390 * has gone clearly wrong. We get called for faults in kernel space,
391 * and HPMC's.
392 */
393void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
394{
395 static DEFINE_SPINLOCK(terminate_lock);
396
397 oops_in_progress = 1;
398
399 set_eiem(0);
400 local_irq_disable();
401 spin_lock(&terminate_lock);
402
403 /* unlock the pdc lock if necessary */
404 pdc_emergency_unlock();
405
406 /* restart pdc console if necessary */
407 if (!console_drivers)
408 pdc_console_restart();
409
410 /* Not all paths will gutter the processor... */
411 switch(code){
412
413 case 1:
414 transfer_pim_to_trap_frame(regs);
415 break;
416
417 default:
418 /* Fall through */
419 break;
420
421 }
422
423 {
424 /* show_stack(NULL, (unsigned long *)regs->gr[30]); */
425 struct unwind_frame_info info;
426 unwind_frame_init(&info, current, regs);
427 do_show_stack(&info);
428 }
429
430 printk("\n");
431 printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
432 msg, code, regs, offset);
433 show_regs(regs);
434
435 spin_unlock(&terminate_lock);
436
437 /* put soft power button back under hardware control;
438 * if the user had pressed it once at any time, the
439 * system will shut down immediately right here. */
440 pdc_soft_power_button(0);
441
442 /* Call kernel panic() so reboot timeouts work properly
443 * FIXME: This function should be on the list of
444 * panic notifiers, and we should call panic
445 * directly from the location that we wish.
446 * e.g. We should not call panic from
447 * parisc_terminate, but rather the oter way around.
448 * This hack works, prints the panic message twice,
449 * and it enables reboot timers!
450 */
451 panic(msg);
452}
453
454void handle_interruption(int code, struct pt_regs *regs)
455{
456 unsigned long fault_address = 0;
457 unsigned long fault_space = 0;
458 struct siginfo si;
459
460 if (code == 1)
461 pdc_console_restart(); /* switch back to pdc if HPMC */
462 else
463 local_irq_enable();
464
465 /* Security check:
466 * If the priority level is still user, and the
467 * faulting space is not equal to the active space
468 * then the user is attempting something in a space
469 * that does not belong to them. Kill the process.
470 *
471 * This is normally the situation when the user
472 * attempts to jump into the kernel space at the
473 * wrong offset, be it at the gateway page or a
474 * random location.
475 *
476 * We cannot normally signal the process because it
477 * could *be* on the gateway page, and processes
478 * executing on the gateway page can't have signals
479 * delivered.
480 *
481 * We merely readjust the address into the users
482 * space, at a destination address of zero, and
483 * allow processing to continue.
484 */
485 if (((unsigned long)regs->iaoq[0] & 3) &&
486 ((unsigned long)regs->iasq[0] != (unsigned long)regs->sr[7])) {
487 /* Kill the user process later */
488 regs->iaoq[0] = 0 | 3;
489 regs->iaoq[1] = regs->iaoq[0] + 4;
490 regs->iasq[0] = regs->iasq[0] = regs->sr[7];
491 regs->gr[0] &= ~PSW_B;
492 return;
493 }
494
495#if 0
496 printk(KERN_CRIT "Interruption # %d\n", code);
497#endif
498
499 switch(code) {
500
501 case 1:
502 /* High-priority machine check (HPMC) */
503
504 /* set up a new led state on systems shipped with a LED State panel */
505 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_HPMC);
506
507 parisc_terminate("High Priority Machine Check (HPMC)",
508 regs, code, 0);
509 /* NOT REACHED */
510
511 case 2:
512 /* Power failure interrupt */
513 printk(KERN_CRIT "Power failure interrupt !\n");
514 return;
515
516 case 3:
517 /* Recovery counter trap */
518 regs->gr[0] &= ~PSW_R;
519 if (user_space(regs))
520 handle_gdb_break(regs, TRAP_TRACE);
521 /* else this must be the start of a syscall - just let it run */
522 return;
523
524 case 5:
525 /* Low-priority machine check */
526 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC);
527
528 flush_all_caches();
529 cpu_lpmc(5, regs);
530 return;
531
532 case 6:
533 /* Instruction TLB miss fault/Instruction page fault */
534 fault_address = regs->iaoq[0];
535 fault_space = regs->iasq[0];
536 break;
537
538 case 8:
539 /* Illegal instruction trap */
540 die_if_kernel("Illegal instruction", regs, code);
541 si.si_code = ILL_ILLOPC;
542 goto give_sigill;
543
544 case 9:
545 /* Break instruction trap */
546 handle_break(regs->iir,regs);
547 return;
548
549 case 10:
550 /* Privileged operation trap */
551 die_if_kernel("Privileged operation", regs, code);
552 si.si_code = ILL_PRVOPC;
553 goto give_sigill;
554
555 case 11:
556 /* Privileged register trap */
557 if ((regs->iir & 0xffdfffe0) == 0x034008a0) {
558
559 /* This is a MFCTL cr26/cr27 to gr instruction.
560 * PCXS traps on this, so we need to emulate it.
561 */
562
563 if (regs->iir & 0x00200000)
564 regs->gr[regs->iir & 0x1f] = mfctl(27);
565 else
566 regs->gr[regs->iir & 0x1f] = mfctl(26);
567
568 regs->iaoq[0] = regs->iaoq[1];
569 regs->iaoq[1] += 4;
570 regs->iasq[0] = regs->iasq[1];
571 return;
572 }
573
574 die_if_kernel("Privileged register usage", regs, code);
575 si.si_code = ILL_PRVREG;
576 give_sigill:
577 si.si_signo = SIGILL;
578 si.si_errno = 0;
579 si.si_addr = (void __user *) regs->iaoq[0];
580 force_sig_info(SIGILL, &si, current);
581 return;
582
583 case 12:
584 /* Overflow Trap, let the userland signal handler do the cleanup */
585 si.si_signo = SIGFPE;
586 si.si_code = FPE_INTOVF;
587 si.si_addr = (void __user *) regs->iaoq[0];
588 force_sig_info(SIGFPE, &si, current);
589 return;
590
591 case 13:
592 /* Conditional Trap
593 The condition succees in an instruction which traps
594 on condition */
595 if(user_mode(regs)){
596 si.si_signo = SIGFPE;
597 /* Set to zero, and let the userspace app figure it out from
598 the insn pointed to by si_addr */
599 si.si_code = 0;
600 si.si_addr = (void __user *) regs->iaoq[0];
601 force_sig_info(SIGFPE, &si, current);
602 return;
603 }
604 /* The kernel doesn't want to handle condition codes */
605 break;
606
607 case 14:
608 /* Assist Exception Trap, i.e. floating point exception. */
609 die_if_kernel("Floating point exception", regs, 0); /* quiet */
610 handle_fpe(regs);
611 return;
612
613 case 15:
614 /* Data TLB miss fault/Data page fault */
615 /* Fall through */
616 case 16:
617 /* Non-access instruction TLB miss fault */
618 /* The instruction TLB entry needed for the target address of the FIC
619 is absent, and hardware can't find it, so we get to cleanup */
620 /* Fall through */
621 case 17:
622 /* Non-access data TLB miss fault/Non-access data page fault */
623 /* FIXME:
624 Still need to add slow path emulation code here!
625 If the insn used a non-shadow register, then the tlb
626 handlers could not have their side-effect (e.g. probe
627 writing to a target register) emulated since rfir would
628 erase the changes to said register. Instead we have to
629 setup everything, call this function we are in, and emulate
630 by hand. Technically we need to emulate:
631 fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw
632 */
633 fault_address = regs->ior;
634 fault_space = regs->isr;
635 break;
636
637 case 18:
638 /* PCXS only -- later cpu's split this into types 26,27 & 28 */
639 /* Check for unaligned access */
640 if (check_unaligned(regs)) {
641 handle_unaligned(regs);
642 return;
643 }
644 /* Fall Through */
645 case 26:
646 /* PCXL: Data memory access rights trap */
647 fault_address = regs->ior;
648 fault_space = regs->isr;
649 break;
650
651 case 19:
652 /* Data memory break trap */
653 regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
654 /* fall thru */
655 case 21:
656 /* Page reference trap */
657 handle_gdb_break(regs, TRAP_HWBKPT);
658 return;
659
660 case 25:
661 /* Taken branch trap */
662 regs->gr[0] &= ~PSW_T;
663 if (user_space(regs))
664 handle_gdb_break(regs, TRAP_BRANCH);
665 /* else this must be the start of a syscall - just let it
666 * run.
667 */
668 return;
669
670 case 7:
671 /* Instruction access rights */
672 /* PCXL: Instruction memory protection trap */
673
674 /*
675 * This could be caused by either: 1) a process attempting
676 * to execute within a vma that does not have execute
677 * permission, or 2) an access rights violation caused by a
678 * flush only translation set up by ptep_get_and_clear().
679 * So we check the vma permissions to differentiate the two.
680 * If the vma indicates we have execute permission, then
681 * the cause is the latter one. In this case, we need to
682 * call do_page_fault() to fix the problem.
683 */
684
685 if (user_mode(regs)) {
686 struct vm_area_struct *vma;
687
688 down_read(&current->mm->mmap_sem);
689 vma = find_vma(current->mm,regs->iaoq[0]);
690 if (vma && (regs->iaoq[0] >= vma->vm_start)
691 && (vma->vm_flags & VM_EXEC)) {
692
693 fault_address = regs->iaoq[0];
694 fault_space = regs->iasq[0];
695
696 up_read(&current->mm->mmap_sem);
697 break; /* call do_page_fault() */
698 }
699 up_read(&current->mm->mmap_sem);
700 }
701 /* Fall Through */
702 case 27:
703 /* Data memory protection ID trap */
704 die_if_kernel("Protection id trap", regs, code);
705 si.si_code = SEGV_MAPERR;
706 si.si_signo = SIGSEGV;
707 si.si_errno = 0;
708 if (code == 7)
709 si.si_addr = (void __user *) regs->iaoq[0];
710 else
711 si.si_addr = (void __user *) regs->ior;
712 force_sig_info(SIGSEGV, &si, current);
713 return;
714
715 case 28:
716 /* Unaligned data reference trap */
717 handle_unaligned(regs);
718 return;
719
720 default:
721 if (user_mode(regs)) {
722#ifdef PRINT_USER_FAULTS
723 printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n",
724 current->pid, current->comm);
725 show_regs(regs);
726#endif
727 /* SIGBUS, for lack of a better one. */
728 si.si_signo = SIGBUS;
729 si.si_code = BUS_OBJERR;
730 si.si_errno = 0;
731 si.si_addr = (void __user *) regs->ior;
732 force_sig_info(SIGBUS, &si, current);
733 return;
734 }
735 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
736
737 parisc_terminate("Unexpected interruption", regs, code, 0);
738 /* NOT REACHED */
739 }
740
741 if (user_mode(regs)) {
742 if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
743#ifdef PRINT_USER_FAULTS
744 if (fault_space == 0)
745 printk(KERN_DEBUG "User Fault on Kernel Space ");
746 else
747 printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
748 code);
749 printk("pid=%d command='%s'\n", current->pid, current->comm);
750 show_regs(regs);
751#endif
752 si.si_signo = SIGSEGV;
753 si.si_errno = 0;
754 si.si_code = SEGV_MAPERR;
755 si.si_addr = (void __user *) regs->ior;
756 force_sig_info(SIGSEGV, &si, current);
757 return;
758 }
759 }
760 else {
761
762 /*
763 * The kernel should never fault on its own address space.
764 */
765
766 if (fault_space == 0)
767 {
768 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
769 parisc_terminate("Kernel Fault", regs, code, fault_address);
770
771 }
772 }
773
774 do_page_fault(regs, code, fault_address);
775}
776
777
778int __init check_ivt(void *iva)
779{
780 int i;
781 u32 check = 0;
782 u32 *ivap;
783 u32 *hpmcp;
784 u32 length;
785 extern void os_hpmc(void);
786 extern void os_hpmc_end(void);
787
788 if (strcmp((char *)iva, "cows can fly"))
789 return -1;
790
791 ivap = (u32 *)iva;
792
793 for (i = 0; i < 8; i++)
794 *ivap++ = 0;
795
796 /* Compute Checksum for HPMC handler */
797
798 length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);
799 ivap[7] = length;
800
801 hpmcp = (u32 *)os_hpmc;
802
803 for (i=0; i<length/4; i++)
804 check += *hpmcp++;
805
806 for (i=0; i<8; i++)
807 check += ivap[i];
808
809 ivap[5] = -check;
810
811 return 0;
812}
813
814#ifndef __LP64__
815extern const void fault_vector_11;
816#endif
817extern const void fault_vector_20;
818
819void __init trap_init(void)
820{
821 void *iva;
822
823 if (boot_cpu_data.cpu_type >= pcxu)
824 iva = (void *) &fault_vector_20;
825 else
826#ifdef __LP64__
827 panic("Can't boot 64-bit OS on PA1.1 processor!");
828#else
829 iva = (void *) &fault_vector_11;
830#endif
831
832 if (check_ivt(iva))
833 panic("IVT invalid");
834}
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 @@
1/*
2 * Unaligned memory access handler
3 *
4 * Copyright (C) 2001 Randolph Chung <tausq@debian.org>
5 * Significantly tweaked by LaMont Jones <lamont@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
23#include <linux/config.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <asm/uaccess.h>
27
28/* #define DEBUG_UNALIGNED 1 */
29
30#ifdef DEBUG_UNALIGNED
31#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0)
32#else
33#define DPRINTF(fmt, args...)
34#endif
35
36#ifdef __LP64__
37#define RFMT "%016lx"
38#else
39#define RFMT "%08lx"
40#endif
41
42#define FIXUP_BRANCH(lbl) \
43 "\tldil L%%" #lbl ", %%r1\n" \
44 "\tldo R%%" #lbl "(%%r1), %%r1\n" \
45 "\tbv,n %%r0(%%r1)\n"
46
47/* 1111 1100 0000 0000 0001 0011 1100 0000 */
48#define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6)
49#define OPCODE2(a,b) ((a)<<26|(b)<<1)
50#define OPCODE3(a,b) ((a)<<26|(b)<<2)
51#define OPCODE4(a) ((a)<<26)
52#define OPCODE1_MASK OPCODE1(0x3f,1,0xf)
53#define OPCODE2_MASK OPCODE2(0x3f,1)
54#define OPCODE3_MASK OPCODE3(0x3f,1)
55#define OPCODE4_MASK OPCODE4(0x3f)
56
57/* skip LDB - never unaligned (index) */
58#define OPCODE_LDH_I OPCODE1(0x03,0,0x1)
59#define OPCODE_LDW_I OPCODE1(0x03,0,0x2)
60#define OPCODE_LDD_I OPCODE1(0x03,0,0x3)
61#define OPCODE_LDDA_I OPCODE1(0x03,0,0x4)
62#define OPCODE_LDCD_I OPCODE1(0x03,0,0x5)
63#define OPCODE_LDWA_I OPCODE1(0x03,0,0x6)
64#define OPCODE_LDCW_I OPCODE1(0x03,0,0x7)
65/* skip LDB - never unaligned (short) */
66#define OPCODE_LDH_S OPCODE1(0x03,1,0x1)
67#define OPCODE_LDW_S OPCODE1(0x03,1,0x2)
68#define OPCODE_LDD_S OPCODE1(0x03,1,0x3)
69#define OPCODE_LDDA_S OPCODE1(0x03,1,0x4)
70#define OPCODE_LDCD_S OPCODE1(0x03,1,0x5)
71#define OPCODE_LDWA_S OPCODE1(0x03,1,0x6)
72#define OPCODE_LDCW_S OPCODE1(0x03,1,0x7)
73/* skip STB - never unaligned */
74#define OPCODE_STH OPCODE1(0x03,1,0x9)
75#define OPCODE_STW OPCODE1(0x03,1,0xa)
76#define OPCODE_STD OPCODE1(0x03,1,0xb)
77/* skip STBY - never unaligned */
78/* skip STDBY - never unaligned */
79#define OPCODE_STWA OPCODE1(0x03,1,0xe)
80#define OPCODE_STDA OPCODE1(0x03,1,0xf)
81
82#define OPCODE_FLDWX OPCODE1(0x09,0,0x0)
83#define OPCODE_FLDWXR OPCODE1(0x09,0,0x1)
84#define OPCODE_FSTWX OPCODE1(0x09,0,0x8)
85#define OPCODE_FSTWXR OPCODE1(0x09,0,0x9)
86#define OPCODE_FLDWS OPCODE1(0x09,1,0x0)
87#define OPCODE_FLDWSR OPCODE1(0x09,1,0x1)
88#define OPCODE_FSTWS OPCODE1(0x09,1,0x8)
89#define OPCODE_FSTWSR OPCODE1(0x09,1,0x9)
90#define OPCODE_FLDDX OPCODE1(0x0b,0,0x0)
91#define OPCODE_FSTDX OPCODE1(0x0b,0,0x8)
92#define OPCODE_FLDDS OPCODE1(0x0b,1,0x0)
93#define OPCODE_FSTDS OPCODE1(0x0b,1,0x8)
94
95#define OPCODE_LDD_L OPCODE2(0x14,0)
96#define OPCODE_FLDD_L OPCODE2(0x14,1)
97#define OPCODE_STD_L OPCODE2(0x1c,0)
98#define OPCODE_FSTD_L OPCODE2(0x1c,1)
99
100#define OPCODE_LDW_M OPCODE3(0x17,1)
101#define OPCODE_FLDW_L OPCODE3(0x17,0)
102#define OPCODE_FSTW_L OPCODE3(0x1f,0)
103#define OPCODE_STW_M OPCODE3(0x1f,1)
104
105#define OPCODE_LDH_L OPCODE4(0x11)
106#define OPCODE_LDW_L OPCODE4(0x12)
107#define OPCODE_LDWM OPCODE4(0x13)
108#define OPCODE_STH_L OPCODE4(0x19)
109#define OPCODE_STW_L OPCODE4(0x1A)
110#define OPCODE_STWM OPCODE4(0x1B)
111
112#define MAJOR_OP(i) (((i)>>26)&0x3f)
113#define R1(i) (((i)>>21)&0x1f)
114#define R2(i) (((i)>>16)&0x1f)
115#define R3(i) ((i)&0x1f)
116#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
117#define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
118#define IM5_2(i) IM((i)>>16,5)
119#define IM5_3(i) IM((i),5)
120#define IM14(i) IM((i),14)
121
122#define ERR_NOTHANDLED -1
123#define ERR_PAGEFAULT -2
124
125int unaligned_enabled = 1;
126
127void die_if_kernel (char *str, struct pt_regs *regs, long err);
128
129static int emulate_ldh(struct pt_regs *regs, int toreg)
130{
131 unsigned long saddr = regs->ior;
132 unsigned long val = 0;
133 int ret;
134
135 DPRINTF("load " RFMT ":" RFMT " to r%d for 2 bytes\n",
136 regs->isr, regs->ior, toreg);
137
138 __asm__ __volatile__ (
139" mtsp %4, %%sr1\n"
140"1: ldbs 0(%%sr1,%3), %%r20\n"
141"2: ldbs 1(%%sr1,%3), %0\n"
142" depw %%r20, 23, 24, %0\n"
143" copy %%r0, %1\n"
144"3: \n"
145" .section .fixup,\"ax\"\n"
146"4: ldi -2, %1\n"
147 FIXUP_BRANCH(3b)
148" .previous\n"
149" .section __ex_table,\"aw\"\n"
150#ifdef __LP64__
151" .dword 1b,4b\n"
152" .dword 2b,4b\n"
153#else
154" .word 1b,4b\n"
155" .word 2b,4b\n"
156#endif
157" .previous\n"
158 : "=r" (val), "=r" (ret)
159 : "0" (val), "r" (saddr), "r" (regs->isr)
160 : "r20" );
161
162 DPRINTF("val = 0x" RFMT "\n", val);
163
164 if (toreg)
165 regs->gr[toreg] = val;
166
167 return ret;
168}
169
170static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
171{
172 unsigned long saddr = regs->ior;
173 unsigned long val = 0;
174 int ret;
175
176 DPRINTF("load " RFMT ":" RFMT " to r%d for 4 bytes\n",
177 regs->isr, regs->ior, toreg);
178
179 __asm__ __volatile__ (
180" zdep %3,28,2,%%r19\n" /* r19=(ofs&3)*8 */
181" mtsp %4, %%sr1\n"
182" depw %%r0,31,2,%3\n"
183"1: ldw 0(%%sr1,%3),%0\n"
184"2: ldw 4(%%sr1,%3),%%r20\n"
185" subi 32,%%r19,%%r19\n"
186" mtctl %%r19,11\n"
187" vshd %0,%%r20,%0\n"
188" copy %%r0, %1\n"
189"3: \n"
190" .section .fixup,\"ax\"\n"
191"4: ldi -2, %1\n"
192 FIXUP_BRANCH(3b)
193" .previous\n"
194" .section __ex_table,\"aw\"\n"
195#ifdef __LP64__
196" .dword 1b,4b\n"
197" .dword 2b,4b\n"
198#else
199" .word 1b,4b\n"
200" .word 2b,4b\n"
201#endif
202" .previous\n"
203 : "=r" (val), "=r" (ret)
204 : "0" (val), "r" (saddr), "r" (regs->isr)
205 : "r19", "r20" );
206
207 DPRINTF("val = 0x" RFMT "\n", val);
208
209 if (flop)
210 ((__u32*)(regs->fr))[toreg] = val;
211 else if (toreg)
212 regs->gr[toreg] = val;
213
214 return ret;
215}
216static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
217{
218 unsigned long saddr = regs->ior;
219 __u64 val = 0;
220 int ret;
221
222 DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n",
223 regs->isr, regs->ior, toreg);
224#ifdef CONFIG_PA20
225
226#ifndef __LP64__
227 if (!flop)
228 return -1;
229#endif
230 __asm__ __volatile__ (
231" depd,z %3,60,3,%%r19\n" /* r19=(ofs&7)*8 */
232" mtsp %4, %%sr1\n"
233" depd %%r0,63,3,%3\n"
234"1: ldd 0(%%sr1,%3),%0\n"
235"2: ldd 8(%%sr1,%3),%%r20\n"
236" subi 64,%%r19,%%r19\n"
237" mtsar %%r19\n"
238" shrpd %0,%%r20,%%sar,%0\n"
239" copy %%r0, %1\n"
240"3: \n"
241" .section .fixup,\"ax\"\n"
242"4: ldi -2, %1\n"
243 FIXUP_BRANCH(3b)
244" .previous\n"
245" .section __ex_table,\"aw\"\n"
246#ifdef __LP64__
247" .dword 1b,4b\n"
248" .dword 2b,4b\n"
249#else
250" .word 1b,4b\n"
251" .word 2b,4b\n"
252#endif
253" .previous\n"
254 : "=r" (val), "=r" (ret)
255 : "0" (val), "r" (saddr), "r" (regs->isr)
256 : "r19", "r20" );
257#else
258 {
259 unsigned long valh=0,vall=0;
260 __asm__ __volatile__ (
261" zdep %5,29,2,%%r19\n" /* r19=(ofs&3)*8 */
262" mtsp %6, %%sr1\n"
263" dep %%r0,31,2,%5\n"
264"1: ldw 0(%%sr1,%5),%0\n"
265"2: ldw 4(%%sr1,%5),%1\n"
266"3: ldw 8(%%sr1,%5),%%r20\n"
267" subi 32,%%r19,%%r19\n"
268" mtsar %%r19\n"
269" vshd %0,%1,%0\n"
270" vshd %1,%%r20,%1\n"
271" copy %%r0, %2\n"
272"4: \n"
273" .section .fixup,\"ax\"\n"
274"5: ldi -2, %2\n"
275 FIXUP_BRANCH(4b)
276" .previous\n"
277" .section __ex_table,\"aw\"\n"
278#ifdef __LP64__
279" .dword 1b,5b\n"
280" .dword 2b,5b\n"
281" .dword 3b,5b\n"
282#else
283" .word 1b,5b\n"
284" .word 2b,5b\n"
285" .word 3b,5b\n"
286#endif
287" .previous\n"
288 : "=r" (valh), "=r" (vall), "=r" (ret)
289 : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
290 : "r19", "r20" );
291 val=((__u64)valh<<32)|(__u64)vall;
292 }
293#endif
294
295 DPRINTF("val = 0x%llx\n", val);
296
297 if (flop)
298 regs->fr[toreg] = val;
299 else if (toreg)
300 regs->gr[toreg] = val;
301
302 return ret;
303}
304
305static int emulate_sth(struct pt_regs *regs, int frreg)
306{
307 unsigned long val = regs->gr[frreg];
308 int ret;
309
310 if (!frreg)
311 val = 0;
312
313 DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg,
314 val, regs->isr, regs->ior);
315
316 __asm__ __volatile__ (
317" mtsp %3, %%sr1\n"
318" extrw,u %1, 23, 8, %%r19\n"
319"1: stb %1, 1(%%sr1, %2)\n"
320"2: stb %%r19, 0(%%sr1, %2)\n"
321" copy %%r0, %0\n"
322"3: \n"
323" .section .fixup,\"ax\"\n"
324"4: ldi -2, %0\n"
325 FIXUP_BRANCH(3b)
326" .previous\n"
327" .section __ex_table,\"aw\"\n"
328#ifdef __LP64__
329" .dword 1b,4b\n"
330" .dword 2b,4b\n"
331#else
332" .word 1b,4b\n"
333" .word 2b,4b\n"
334#endif
335" .previous\n"
336 : "=r" (ret)
337 : "r" (val), "r" (regs->ior), "r" (regs->isr)
338 : "r19" );
339
340 return ret;
341}
342
343static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
344{
345 unsigned long val;
346 int ret;
347
348 if (flop)
349 val = ((__u32*)(regs->fr))[frreg];
350 else if (frreg)
351 val = regs->gr[frreg];
352 else
353 val = 0;
354
355 DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg,
356 val, regs->isr, regs->ior);
357
358
359 __asm__ __volatile__ (
360" mtsp %3, %%sr1\n"
361" zdep %2, 28, 2, %%r19\n"
362" dep %%r0, 31, 2, %2\n"
363" mtsar %%r19\n"
364" depwi,z -2, %%sar, 32, %%r19\n"
365"1: ldw 0(%%sr1,%2),%%r20\n"
366"2: ldw 4(%%sr1,%2),%%r21\n"
367" vshd %%r0, %1, %%r22\n"
368" vshd %1, %%r0, %%r1\n"
369" and %%r20, %%r19, %%r20\n"
370" andcm %%r21, %%r19, %%r21\n"
371" or %%r22, %%r20, %%r20\n"
372" or %%r1, %%r21, %%r21\n"
373" stw %%r20,0(%%sr1,%2)\n"
374" stw %%r21,4(%%sr1,%2)\n"
375" copy %%r0, %0\n"
376"3: \n"
377" .section .fixup,\"ax\"\n"
378"4: ldi -2, %0\n"
379 FIXUP_BRANCH(3b)
380" .previous\n"
381" .section __ex_table,\"aw\"\n"
382#ifdef __LP64__
383" .dword 1b,4b\n"
384" .dword 2b,4b\n"
385#else
386" .word 1b,4b\n"
387" .word 2b,4b\n"
388#endif
389" .previous\n"
390 : "=r" (ret)
391 : "r" (val), "r" (regs->ior), "r" (regs->isr)
392 : "r19", "r20", "r21", "r22", "r1" );
393
394 return 0;
395}
396static int emulate_std(struct pt_regs *regs, int frreg, int flop)
397{
398 __u64 val;
399 int ret;
400
401 if (flop)
402 val = regs->fr[frreg];
403 else if (frreg)
404 val = regs->gr[frreg];
405 else
406 val = 0;
407
408 DPRINTF("store r%d (0x%016llx) to " RFMT ":" RFMT " for 8 bytes\n", frreg,
409 val, regs->isr, regs->ior);
410
411#ifdef CONFIG_PA20
412#ifndef __LP64__
413 if (!flop)
414 return -1;
415#endif
416 __asm__ __volatile__ (
417" mtsp %3, %%sr1\n"
418" depd,z %2, 60, 3, %%r19\n"
419" depd %%r0, 63, 3, %2\n"
420" mtsar %%r19\n"
421" depdi,z -2, %%sar, 64, %%r19\n"
422"1: ldd 0(%%sr1,%2),%%r20\n"
423"2: ldd 8(%%sr1,%2),%%r21\n"
424" shrpd %%r0, %1, %%sar, %%r22\n"
425" shrpd %1, %%r0, %%sar, %%r1\n"
426" and %%r20, %%r19, %%r20\n"
427" andcm %%r21, %%r19, %%r21\n"
428" or %%r22, %%r20, %%r20\n"
429" or %%r1, %%r21, %%r21\n"
430"3: std %%r20,0(%%sr1,%2)\n"
431"4: std %%r21,8(%%sr1,%2)\n"
432" copy %%r0, %0\n"
433"5: \n"
434" .section .fixup,\"ax\"\n"
435"6: ldi -2, %0\n"
436 FIXUP_BRANCH(5b)
437" .previous\n"
438" .section __ex_table,\"aw\"\n"
439#ifdef __LP64__
440" .dword 1b,6b\n"
441" .dword 2b,6b\n"
442" .dword 3b,6b\n"
443" .dword 4b,6b\n"
444#else
445" .word 1b,6b\n"
446" .word 2b,6b\n"
447" .word 3b,6b\n"
448" .word 4b,6b\n"
449#endif
450" .previous\n"
451 : "=r" (ret)
452 : "r" (val), "r" (regs->ior), "r" (regs->isr)
453 : "r19", "r20", "r21", "r22", "r1" );
454#else
455 {
456 unsigned long valh=(val>>32),vall=(val&0xffffffffl);
457 __asm__ __volatile__ (
458" mtsp %4, %%sr1\n"
459" zdep %2, 29, 2, %%r19\n"
460" dep %%r0, 31, 2, %2\n"
461" mtsar %%r19\n"
462" zvdepi -2, 32, %%r19\n"
463"1: ldw 0(%%sr1,%3),%%r20\n"
464"2: ldw 8(%%sr1,%3),%%r21\n"
465" vshd %1, %2, %%r1\n"
466" vshd %%r0, %1, %1\n"
467" vshd %2, %%r0, %2\n"
468" and %%r20, %%r19, %%r20\n"
469" andcm %%r21, %%r19, %%r21\n"
470" or %1, %%r20, %1\n"
471" or %2, %%r21, %2\n"
472"3: stw %1,0(%%sr1,%1)\n"
473"4: stw %%r1,4(%%sr1,%3)\n"
474"5: stw %2,8(%%sr1,%3)\n"
475" copy %%r0, %0\n"
476"6: \n"
477" .section .fixup,\"ax\"\n"
478"7: ldi -2, %0\n"
479 FIXUP_BRANCH(6b)
480" .previous\n"
481" .section __ex_table,\"aw\"\n"
482#ifdef __LP64__
483" .dword 1b,7b\n"
484" .dword 2b,7b\n"
485" .dword 3b,7b\n"
486" .dword 4b,7b\n"
487" .dword 5b,7b\n"
488#else
489" .word 1b,7b\n"
490" .word 2b,7b\n"
491" .word 3b,7b\n"
492" .word 4b,7b\n"
493" .word 5b,7b\n"
494#endif
495" .previous\n"
496 : "=r" (ret)
497 : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
498 : "r19", "r20", "r21", "r1" );
499 }
500#endif
501
502 return ret;
503}
504
505void handle_unaligned(struct pt_regs *regs)
506{
507 static unsigned long unaligned_count = 0;
508 static unsigned long last_time = 0;
509 unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
510 int modify = 0;
511 int ret = ERR_NOTHANDLED;
512 struct siginfo si;
513 register int flop=0; /* true if this is a flop */
514
515 /* log a message with pacing */
516 if (user_mode(regs))
517 {
518 if (unaligned_count > 5 && jiffies - last_time > 5*HZ)
519 {
520 unaligned_count = 0;
521 last_time = jiffies;
522 }
523 if (++unaligned_count < 5)
524 {
525 char buf[256];
526 sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n",
527 current->comm, current->pid, regs->ior, regs->iaoq[0]);
528 printk(KERN_WARNING "%s", buf);
529#ifdef DEBUG_UNALIGNED
530 show_regs(regs);
531#endif
532 }
533 if (!unaligned_enabled)
534 goto force_sigbus;
535 }
536
537 /* handle modification - OK, it's ugly, see the instruction manual */
538 switch (MAJOR_OP(regs->iir))
539 {
540 case 0x03:
541 case 0x09:
542 case 0x0b:
543 if (regs->iir&0x20)
544 {
545 modify = 1;
546 if (regs->iir&0x1000) /* short loads */
547 if (regs->iir&0x200)
548 newbase += IM5_3(regs->iir);
549 else
550 newbase += IM5_2(regs->iir);
551 else if (regs->iir&0x2000) /* scaled indexed */
552 {
553 int shift=0;
554 switch (regs->iir & OPCODE1_MASK)
555 {
556 case OPCODE_LDH_I:
557 shift= 1; break;
558 case OPCODE_LDW_I:
559 shift= 2; break;
560 case OPCODE_LDD_I:
561 case OPCODE_LDDA_I:
562 shift= 3; break;
563 }
564 newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift;
565 } else /* simple indexed */
566 newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0);
567 }
568 break;
569 case 0x13:
570 case 0x1b:
571 modify = 1;
572 newbase += IM14(regs->iir);
573 break;
574 case 0x14:
575 case 0x1c:
576 if (regs->iir&8)
577 {
578 modify = 1;
579 newbase += IM14(regs->iir&~0xe);
580 }
581 break;
582 case 0x16:
583 case 0x1e:
584 modify = 1;
585 newbase += IM14(regs->iir&6);
586 break;
587 case 0x17:
588 case 0x1f:
589 if (regs->iir&4)
590 {
591 modify = 1;
592 newbase += IM14(regs->iir&~4);
593 }
594 break;
595 }
596
597 /* TODO: make this cleaner... */
598 switch (regs->iir & OPCODE1_MASK)
599 {
600 case OPCODE_LDH_I:
601 case OPCODE_LDH_S:
602 ret = emulate_ldh(regs, R3(regs->iir));
603 break;
604
605 case OPCODE_LDW_I:
606 case OPCODE_LDWA_I:
607 case OPCODE_LDW_S:
608 case OPCODE_LDWA_S:
609 ret = emulate_ldw(regs, R3(regs->iir),0);
610 break;
611
612 case OPCODE_STH:
613 ret = emulate_sth(regs, R2(regs->iir));
614 break;
615
616 case OPCODE_STW:
617 case OPCODE_STWA:
618 ret = emulate_stw(regs, R2(regs->iir),0);
619 break;
620
621#ifdef CONFIG_PA20
622 case OPCODE_LDD_I:
623 case OPCODE_LDDA_I:
624 case OPCODE_LDD_S:
625 case OPCODE_LDDA_S:
626 ret = emulate_ldd(regs, R3(regs->iir),0);
627 break;
628
629 case OPCODE_STD:
630 case OPCODE_STDA:
631 ret = emulate_std(regs, R2(regs->iir),0);
632 break;
633#endif
634
635 case OPCODE_FLDWX:
636 case OPCODE_FLDWS:
637 case OPCODE_FLDWXR:
638 case OPCODE_FLDWSR:
639 flop=1;
640 ret = emulate_ldw(regs,FR3(regs->iir),1);
641 break;
642
643 case OPCODE_FLDDX:
644 case OPCODE_FLDDS:
645 flop=1;
646 ret = emulate_ldd(regs,R3(regs->iir),1);
647 break;
648
649 case OPCODE_FSTWX:
650 case OPCODE_FSTWS:
651 case OPCODE_FSTWXR:
652 case OPCODE_FSTWSR:
653 flop=1;
654 ret = emulate_stw(regs,FR3(regs->iir),1);
655 break;
656
657 case OPCODE_FSTDX:
658 case OPCODE_FSTDS:
659 flop=1;
660 ret = emulate_std(regs,R3(regs->iir),1);
661 break;
662
663 case OPCODE_LDCD_I:
664 case OPCODE_LDCW_I:
665 case OPCODE_LDCD_S:
666 case OPCODE_LDCW_S:
667 ret = ERR_NOTHANDLED; /* "undefined", but lets kill them. */
668 break;
669 }
670#ifdef CONFIG_PA20
671 switch (regs->iir & OPCODE2_MASK)
672 {
673 case OPCODE_FLDD_L:
674 flop=1;
675 ret = emulate_ldd(regs,R2(regs->iir),1);
676 break;
677 case OPCODE_FSTD_L:
678 flop=1;
679 ret = emulate_std(regs, R2(regs->iir),1);
680 break;
681
682#ifdef CONFIG_PA20
683 case OPCODE_LDD_L:
684 ret = emulate_ldd(regs, R2(regs->iir),0);
685 break;
686 case OPCODE_STD_L:
687 ret = emulate_std(regs, R2(regs->iir),0);
688 break;
689#endif
690 }
691#endif
692 switch (regs->iir & OPCODE3_MASK)
693 {
694 case OPCODE_FLDW_L:
695 flop=1;
696 ret = emulate_ldw(regs, R2(regs->iir),0);
697 break;
698 case OPCODE_LDW_M:
699 ret = emulate_ldw(regs, R2(regs->iir),1);
700 break;
701
702 case OPCODE_FSTW_L:
703 flop=1;
704 ret = emulate_stw(regs, R2(regs->iir),1);
705 break;
706 case OPCODE_STW_M:
707 ret = emulate_stw(regs, R2(regs->iir),0);
708 break;
709 }
710 switch (regs->iir & OPCODE4_MASK)
711 {
712 case OPCODE_LDH_L:
713 ret = emulate_ldh(regs, R2(regs->iir));
714 break;
715 case OPCODE_LDW_L:
716 case OPCODE_LDWM:
717 ret = emulate_ldw(regs, R2(regs->iir),0);
718 break;
719 case OPCODE_STH_L:
720 ret = emulate_sth(regs, R2(regs->iir));
721 break;
722 case OPCODE_STW_L:
723 case OPCODE_STWM:
724 ret = emulate_stw(regs, R2(regs->iir),0);
725 break;
726 }
727
728 if (modify && R1(regs->iir))
729 regs->gr[R1(regs->iir)] = newbase;
730
731
732 if (ret == ERR_NOTHANDLED)
733 printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir);
734
735 DPRINTF("ret = %d\n", ret);
736
737 if (ret)
738 {
739 printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
740 die_if_kernel("Unaligned data reference", regs, 28);
741
742 if (ret == ERR_PAGEFAULT)
743 {
744 si.si_signo = SIGSEGV;
745 si.si_errno = 0;
746 si.si_code = SEGV_MAPERR;
747 si.si_addr = (void __user *)regs->ior;
748 force_sig_info(SIGSEGV, &si, current);
749 }
750 else
751 {
752force_sigbus:
753 /* couldn't handle it ... */
754 si.si_signo = SIGBUS;
755 si.si_errno = 0;
756 si.si_code = BUS_ADRALN;
757 si.si_addr = (void __user *)regs->ior;
758 force_sig_info(SIGBUS, &si, current);
759 }
760
761 return;
762 }
763
764 /* else we handled it, let life go on. */
765 regs->gr[0]|=PSW_N;
766}
767
768/*
769 * NB: check_unaligned() is only used for PCXS processors right
770 * now, so we only check for PA1.1 encodings at this point.
771 */
772
773int
774check_unaligned(struct pt_regs *regs)
775{
776 unsigned long align_mask;
777
778 /* Get alignment mask */
779
780 align_mask = 0UL;
781 switch (regs->iir & OPCODE1_MASK) {
782
783 case OPCODE_LDH_I:
784 case OPCODE_LDH_S:
785 case OPCODE_STH:
786 align_mask = 1UL;
787 break;
788
789 case OPCODE_LDW_I:
790 case OPCODE_LDWA_I:
791 case OPCODE_LDW_S:
792 case OPCODE_LDWA_S:
793 case OPCODE_STW:
794 case OPCODE_STWA:
795 align_mask = 3UL;
796 break;
797
798 default:
799 switch (regs->iir & OPCODE4_MASK) {
800 case OPCODE_LDH_L:
801 case OPCODE_STH_L:
802 align_mask = 1UL;
803 break;
804 case OPCODE_LDW_L:
805 case OPCODE_LDWM:
806 case OPCODE_STW_L:
807 case OPCODE_STWM:
808 align_mask = 3UL;
809 break;
810 }
811 break;
812 }
813
814 return (int)(regs->ior & align_mask);
815}
816
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 @@
1/*
2 * Kernel unwinding support
3 *
4 * (c) 2002-2004 Randolph Chung <tausq@debian.org>
5 *
6 * Derived partially from the IA64 implementation. The PA-RISC
7 * Runtime Architecture Document is also a useful reference to
8 * understand what is happening here
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/slab.h>
15#include <linux/kallsyms.h>
16
17#include <asm/uaccess.h>
18#include <asm/assembly.h>
19
20#include <asm/unwind.h>
21
22/* #define DEBUG 1 */
23#ifdef DEBUG
24#define dbg(x...) printk(x)
25#else
26#define dbg(x...)
27#endif
28
29extern struct unwind_table_entry __start___unwind[];
30extern struct unwind_table_entry __stop___unwind[];
31
32static spinlock_t unwind_lock;
33/*
34 * the kernel unwind block is not dynamically allocated so that
35 * we can call unwind_init as early in the bootup process as
36 * possible (before the slab allocator is initialized)
37 */
38static struct unwind_table kernel_unwind_table;
39static LIST_HEAD(unwind_tables);
40
41static inline const struct unwind_table_entry *
42find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
43{
44 const struct unwind_table_entry *e = NULL;
45 unsigned long lo, hi, mid;
46
47 lo = 0;
48 hi = table->length - 1;
49
50 while (lo <= hi) {
51 mid = (hi - lo) / 2 + lo;
52 e = &table->table[mid];
53 if (addr < e->region_start)
54 hi = mid - 1;
55 else if (addr > e->region_end)
56 lo = mid + 1;
57 else
58 return e;
59 }
60
61 return NULL;
62}
63
64static const struct unwind_table_entry *
65find_unwind_entry(unsigned long addr)
66{
67 struct unwind_table *table;
68 const struct unwind_table_entry *e = NULL;
69
70 if (addr >= kernel_unwind_table.start &&
71 addr <= kernel_unwind_table.end)
72 e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
73 else
74 list_for_each_entry(table, &unwind_tables, list) {
75 if (addr >= table->start &&
76 addr <= table->end)
77 e = find_unwind_entry_in_table(table, addr);
78 if (e)
79 break;
80 }
81
82 return e;
83}
84
85static void
86unwind_table_init(struct unwind_table *table, const char *name,
87 unsigned long base_addr, unsigned long gp,
88 void *table_start, void *table_end)
89{
90 struct unwind_table_entry *start = table_start;
91 struct unwind_table_entry *end =
92 (struct unwind_table_entry *)table_end - 1;
93
94 table->name = name;
95 table->base_addr = base_addr;
96 table->gp = gp;
97 table->start = base_addr + start->region_start;
98 table->end = base_addr + end->region_end;
99 table->table = (struct unwind_table_entry *)table_start;
100 table->length = end - start + 1;
101 INIT_LIST_HEAD(&table->list);
102
103 for (; start <= end; start++) {
104 if (start < end &&
105 start->region_end > (start+1)->region_start) {
106 printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1);
107 }
108
109 start->region_start += base_addr;
110 start->region_end += base_addr;
111 }
112}
113
114static void
115unwind_table_sort(struct unwind_table_entry *start,
116 struct unwind_table_entry *finish)
117{
118 struct unwind_table_entry el, *p, *q;
119
120 for (p = start + 1; p < finish; ++p) {
121 if (p[0].region_start < p[-1].region_start) {
122 el = *p;
123 q = p;
124 do {
125 q[0] = q[-1];
126 --q;
127 } while (q > start &&
128 el.region_start < q[-1].region_start);
129 *q = el;
130 }
131 }
132}
133
134struct unwind_table *
135unwind_table_add(const char *name, unsigned long base_addr,
136 unsigned long gp,
137 void *start, void *end)
138{
139 struct unwind_table *table;
140 unsigned long flags;
141 struct unwind_table_entry *s = (struct unwind_table_entry *)start;
142 struct unwind_table_entry *e = (struct unwind_table_entry *)end;
143
144 unwind_table_sort(s, e);
145
146 table = kmalloc(sizeof(struct unwind_table), GFP_USER);
147 if (table == NULL)
148 return NULL;
149 unwind_table_init(table, name, base_addr, gp, start, end);
150 spin_lock_irqsave(&unwind_lock, flags);
151 list_add_tail(&table->list, &unwind_tables);
152 spin_unlock_irqrestore(&unwind_lock, flags);
153
154 return table;
155}
156
157void unwind_table_remove(struct unwind_table *table)
158{
159 unsigned long flags;
160
161 spin_lock_irqsave(&unwind_lock, flags);
162 list_del(&table->list);
163 spin_unlock_irqrestore(&unwind_lock, flags);
164
165 kfree(table);
166}
167
168/* Called from setup_arch to import the kernel unwind info */
169static int unwind_init(void)
170{
171 long start, stop;
172 register unsigned long gp __asm__ ("r27");
173
174 start = (long)&__start___unwind[0];
175 stop = (long)&__stop___unwind[0];
176
177 spin_lock_init(&unwind_lock);
178
179 printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
180 start, stop,
181 (stop - start) / sizeof(struct unwind_table_entry));
182
183 unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
184 gp,
185 &__start___unwind[0], &__stop___unwind[0]);
186#if 0
187 {
188 int i;
189 for (i = 0; i < 10; i++)
190 {
191 printk("region 0x%x-0x%x\n",
192 __start___unwind[i].region_start,
193 __start___unwind[i].region_end);
194 }
195 }
196#endif
197 return 0;
198}
199
200static void unwind_frame_regs(struct unwind_frame_info *info)
201{
202 const struct unwind_table_entry *e;
203 unsigned long npc;
204 unsigned int insn;
205 long frame_size = 0;
206 int looking_for_rp, rpoffset = 0;
207
208 e = find_unwind_entry(info->ip);
209 if (e == NULL) {
210 unsigned long sp;
211 extern char _stext[], _etext[];
212
213 dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
214
215#ifdef CONFIG_KALLSYMS
216 /* Handle some frequent special cases.... */
217 {
218 char symname[KSYM_NAME_LEN+1];
219 char *modname;
220 unsigned long symsize, offset;
221
222 kallsyms_lookup(info->ip, &symsize, &offset,
223 &modname, symname);
224
225 dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname);
226
227 if (strcmp(symname, "_switch_to_ret") == 0) {
228 info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
229 info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
230 dbg("_switch_to_ret @ %lx - setting "
231 "prev_sp=%lx prev_ip=%lx\n",
232 info->ip, info->prev_sp,
233 info->prev_ip);
234 return;
235 } else if (strcmp(symname, "ret_from_kernel_thread") == 0 ||
236 strcmp(symname, "syscall_exit") == 0) {
237 info->prev_ip = info->prev_sp = 0;
238 return;
239 }
240 }
241#endif
242
243 /* Since we are doing the unwinding blind, we don't know if
244 we are adjusting the stack correctly or extracting the rp
245 correctly. The rp is checked to see if it belongs to the
246 kernel text section, if not we assume we don't have a
247 correct stack frame and we continue to unwind the stack.
248 This is not quite correct, and will fail for loadable
249 modules. */
250 sp = info->sp & ~63;
251 do {
252 unsigned long tmp;
253
254 info->prev_sp = sp - 64;
255 info->prev_ip = 0;
256 if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET)))
257 break;
258 info->prev_ip = tmp;
259 sp = info->prev_sp;
260 } while (info->prev_ip < (unsigned long)_stext ||
261 info->prev_ip > (unsigned long)_etext);
262
263 info->rp = 0;
264
265 dbg("analyzing func @ %lx with no unwind info, setting "
266 "prev_sp=%lx prev_ip=%lx\n", info->ip,
267 info->prev_sp, info->prev_ip);
268 } else {
269 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
270 "Save_RP = %d, Millicode = %d size = %u\n",
271 e->region_start, e->region_end, e->Save_SP, e->Save_RP,
272 e->Millicode, e->Total_frame_size);
273
274 looking_for_rp = e->Save_RP;
275
276 for (npc = e->region_start;
277 (frame_size < (e->Total_frame_size << 3) ||
278 looking_for_rp) &&
279 npc < info->ip;
280 npc += 4) {
281
282 insn = *(unsigned int *)npc;
283
284 if ((insn & 0xffffc000) == 0x37de0000 ||
285 (insn & 0xffe00000) == 0x6fc00000) {
286 /* ldo X(sp), sp, or stwm X,D(sp) */
287 frame_size += (insn & 0x1 ? -1 << 13 : 0) |
288 ((insn & 0x3fff) >> 1);
289 dbg("analyzing func @ %lx, insn=%08x @ "
290 "%lx, frame_size = %ld\n", info->ip,
291 insn, npc, frame_size);
292 } else if ((insn & 0xffe00008) == 0x73c00008) {
293 /* std,ma X,D(sp) */
294 frame_size += (insn & 0x1 ? -1 << 13 : 0) |
295 (((insn >> 4) & 0x3ff) << 3);
296 dbg("analyzing func @ %lx, insn=%08x @ "
297 "%lx, frame_size = %ld\n", info->ip,
298 insn, npc, frame_size);
299 } else if (insn == 0x6bc23fd9) {
300 /* stw rp,-20(sp) */
301 rpoffset = 20;
302 looking_for_rp = 0;
303 dbg("analyzing func @ %lx, insn=stw rp,"
304 "-20(sp) @ %lx\n", info->ip, npc);
305 } else if (insn == 0x0fc212c1) {
306 /* std rp,-16(sr0,sp) */
307 rpoffset = 16;
308 looking_for_rp = 0;
309 dbg("analyzing func @ %lx, insn=std rp,"
310 "-16(sp) @ %lx\n", info->ip, npc);
311 }
312 }
313
314 info->prev_sp = info->sp - frame_size;
315 if (e->Millicode)
316 info->rp = info->r31;
317 else if (rpoffset)
318 info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
319 info->prev_ip = info->rp;
320 info->rp = 0;
321
322 dbg("analyzing func @ %lx, setting prev_sp=%lx "
323 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
324 info->prev_ip, npc);
325 }
326}
327
328void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
329 struct pt_regs *regs)
330{
331 memset(info, 0, sizeof(struct unwind_frame_info));
332 info->t = t;
333 info->sp = regs->gr[30];
334 info->ip = regs->iaoq[0];
335 info->rp = regs->gr[2];
336 info->r31 = regs->gr[31];
337
338 dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
339 t ? (int)t->pid : -1, info->sp, info->ip);
340}
341
342void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
343{
344 struct pt_regs *r = &t->thread.regs;
345 struct pt_regs *r2;
346
347 r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
348 if (!r2)
349 return;
350 *r2 = *r;
351 r2->gr[30] = r->ksp;
352 r2->iaoq[0] = r->kpc;
353 unwind_frame_init(info, t, r2);
354 kfree(r2);
355}
356
357void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs)
358{
359 unwind_frame_init(info, current, regs);
360}
361
362int unwind_once(struct unwind_frame_info *next_frame)
363{
364 unwind_frame_regs(next_frame);
365
366 if (next_frame->prev_sp == 0 ||
367 next_frame->prev_ip == 0)
368 return -1;
369
370 next_frame->sp = next_frame->prev_sp;
371 next_frame->ip = next_frame->prev_ip;
372 next_frame->prev_sp = 0;
373 next_frame->prev_ip = 0;
374
375 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n",
376 next_frame->t ? (int)next_frame->t->pid : -1,
377 next_frame->sp, next_frame->ip);
378
379 return 0;
380}
381
382int unwind_to_user(struct unwind_frame_info *info)
383{
384 int ret;
385
386 do {
387 ret = unwind_once(info);
388 } while (!ret && !(info->ip & 3));
389
390 return ret;
391}
392
393module_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 @@
1/* Kernel link layout for various "sections"
2 *
3 * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
4 * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
5 * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
6 * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
7 * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
8 * Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25#include <linux/config.h>
26#include <asm-generic/vmlinux.lds.h>
27/* needed for the processor specific cache alignment size */
28#include <asm/cache.h>
29#include <asm/page.h>
30
31/* ld script to make hppa Linux kernel */
32#ifndef CONFIG_64BIT
33OUTPUT_FORMAT("elf32-hppa-linux")
34OUTPUT_ARCH(hppa)
35#else
36OUTPUT_FORMAT("elf64-hppa-linux")
37OUTPUT_ARCH(hppa:hppa2.0w)
38#endif
39
40ENTRY(_stext)
41#ifndef CONFIG_64BIT
42jiffies = jiffies_64 + 4;
43#else
44jiffies = jiffies_64;
45#endif
46SECTIONS
47{
48
49 . = KERNEL_BINARY_TEXT_START;
50
51 _text = .; /* Text and read-only data */
52 .text ALIGN(16) : {
53 *(.text)
54 SCHED_TEXT
55 LOCK_TEXT
56 *(.text.do_softirq)
57 *(.text.sys_exit)
58 *(.text.do_sigaltstack)
59 *(.text.do_fork)
60 *(.text.*)
61 *(.fixup)
62 *(.lock.text) /* out-of-line lock text */
63 *(.gnu.warning)
64 } = 0
65
66 _etext = .; /* End of text section */
67
68 RODATA
69
70 /* writeable */
71 . = ALIGN(4096); /* Make sure this is paged aligned so
72 that we can properly leave these
73 as writable */
74 data_start = .;
75
76 . = ALIGN(16); /* Exception table */
77 __start___ex_table = .;
78 __ex_table : { *(__ex_table) }
79 __stop___ex_table = .;
80
81 __start___unwind = .; /* unwind info */
82 .PARISC.unwind : { *(.PARISC.unwind) }
83 __stop___unwind = .;
84
85 .data : { /* Data */
86 *(.data)
87 *(.data.vm0.pmd)
88 *(.data.vm0.pgd)
89 *(.data.vm0.pte)
90 CONSTRUCTORS
91 }
92
93 . = ALIGN(4096);
94 /* nosave data is really only used for software suspend...it's here
95 * just in case we ever implement it */
96 __nosave_begin = .;
97 .data_nosave : { *(.data.nosave) }
98 . = ALIGN(4096);
99 __nosave_end = .;
100
101 . = ALIGN(L1_CACHE_BYTES);
102 .data.cacheline_aligned : { *(.data.cacheline_aligned) }
103
104 /* PA-RISC locks requires 16-byte alignment */
105 . = ALIGN(16);
106 .data.lock_aligned : { *(.data.lock_aligned) }
107
108 _edata = .; /* End of data section */
109
110 . = ALIGN(16384); /* init_task */
111 .data.init_task : { *(.data.init_task) }
112
113 /* The interrupt stack is currently partially coded, but not yet
114 * implemented */
115 . = ALIGN(16384);
116 init_istack : { *(init_istack) }
117
118#ifdef CONFIG_64BIT
119 . = ALIGN(16); /* Linkage tables */
120 .opd : { *(.opd) } PROVIDE (__gp = .);
121 .plt : { *(.plt) }
122 .dlt : { *(.dlt) }
123#endif
124
125 . = ALIGN(16384);
126 __init_begin = .;
127 .init.text : {
128 _sinittext = .;
129 *(.init.text)
130 _einittext = .;
131 }
132 .init.data : { *(.init.data) }
133 . = ALIGN(16);
134 __setup_start = .;
135 .init.setup : { *(.init.setup) }
136 __setup_end = .;
137 __initcall_start = .;
138 .initcall.init : {
139 *(.initcall1.init)
140 *(.initcall2.init)
141 *(.initcall3.init)
142 *(.initcall4.init)
143 *(.initcall5.init)
144 *(.initcall6.init)
145 *(.initcall7.init)
146 }
147 __initcall_end = .;
148 __con_initcall_start = .;
149 .con_initcall.init : { *(.con_initcall.init) }
150 __con_initcall_end = .;
151 SECURITY_INIT
152 /* alternate instruction replacement. This is a mechanism x86 uses
153 * to detect the CPU type and replace generic instruction sequences
154 * with CPU specific ones. We don't currently do this in PA, but
155 * it seems like a good idea... */
156 . = ALIGN(4);
157 __alt_instructions = .;
158 .altinstructions : { *(.altinstructions) }
159 __alt_instructions_end = .;
160 .altinstr_replacement : { *(.altinstr_replacement) }
161 /* .exit.text is discard at runtime, not link time, to deal with references
162 from .altinstructions and .eh_frame */
163 .exit.text : { *(.exit.text) }
164 .exit.data : { *(.exit.data) }
165 . = ALIGN(4096);
166 __initramfs_start = .;
167 .init.ramfs : { *(.init.ramfs) }
168 __initramfs_end = .;
169 . = ALIGN(32);
170 __per_cpu_start = .;
171 .data.percpu : { *(.data.percpu) }
172 __per_cpu_end = .;
173 . = ALIGN(4096);
174 __init_end = .;
175 /* freed after init ends here */
176
177 __bss_start = .; /* BSS */
178 .bss : { *(.bss) *(COMMON) }
179 __bss_stop = .;
180
181 _end = . ;
182
183 /* Sections to be discarded */
184 /DISCARD/ : {
185 *(.exitcall.exit)
186#ifdef CONFIG_64BIT
187 /* temporary hack until binutils is fixed to not emit these
188 for static binaries */
189 *(.interp)
190 *(.dynsym)
191 *(.dynstr)
192 *(.dynamic)
193 *(.hash)
194#endif
195 }
196
197 /* Stabs debugging sections. */
198 .stab 0 : { *(.stab) }
199 .stabstr 0 : { *(.stabstr) }
200 .stab.excl 0 : { *(.stab.excl) }
201 .stab.exclstr 0 : { *(.stab.exclstr) }
202 .stab.index 0 : { *(.stab.index) }
203 .stab.indexstr 0 : { *(.stab.indexstr) }
204 .comment 0 : { *(.comment) }
205 .note 0 : { *(.note) }
206
207}
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 @@
1#
2# Makefile for parisc-specific library files
3#
4
5lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
6
7obj-y := iomap.o
8
9lib-$(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 @@
1/*
2 * bitops.c: atomic operations which got too long to be inlined all over
3 * the place.
4 *
5 * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
6 * Copyright 2000 Grant Grundler (grundler@cup.hp.com)
7 */
8
9#include <linux/config.h>
10#include <linux/kernel.h>
11#include <linux/spinlock.h>
12#include <asm/system.h>
13#include <asm/atomic.h>
14
15#ifdef CONFIG_SMP
16spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
17 [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
18};
19#endif
20
21#ifdef __LP64__
22unsigned long __xchg64(unsigned long x, unsigned long *ptr)
23{
24 unsigned long temp, flags;
25
26 _atomic_spin_lock_irqsave(ptr, flags);
27 temp = *ptr;
28 *ptr = x;
29 _atomic_spin_unlock_irqrestore(ptr, flags);
30 return temp;
31}
32#endif
33
34unsigned long __xchg32(int x, int *ptr)
35{
36 unsigned long flags;
37 long temp;
38
39 _atomic_spin_lock_irqsave(ptr, flags);
40 temp = (long) *ptr; /* XXX - sign extension wanted? */
41 *ptr = x;
42 _atomic_spin_unlock_irqrestore(ptr, flags);
43 return (unsigned long)temp;
44}
45
46
47unsigned long __xchg8(char x, char *ptr)
48{
49 unsigned long flags;
50 long temp;
51
52 _atomic_spin_lock_irqsave(ptr, flags);
53 temp = (long) *ptr; /* XXX - sign extension wanted? */
54 *ptr = x;
55 _atomic_spin_unlock_irqrestore(ptr, flags);
56 return (unsigned long)temp;
57}
58
59
60#ifdef __LP64__
61unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new)
62{
63 unsigned long flags;
64 unsigned long prev;
65
66 _atomic_spin_lock_irqsave(ptr, flags);
67 if ((prev = *ptr) == old)
68 *ptr = new;
69 _atomic_spin_unlock_irqrestore(ptr, flags);
70 return prev;
71}
72#endif
73
74unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new)
75{
76 unsigned long flags;
77 unsigned int prev;
78
79 _atomic_spin_lock_irqsave(ptr, flags);
80 if ((prev = *ptr) == old)
81 *ptr = new;
82 _atomic_spin_unlock_irqrestore(ptr, flags);
83 return (unsigned long)prev;
84}
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 @@
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * MIPS specific IP/TCP/UDP checksumming routines
7 *
8 * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
9 * Lots of code moved from tcp.c and ip.c; see those files
10 * for more names.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * $Id: checksum.c,v 1.3 1997/12/01 17:57:34 ralf Exp $
18 */
19#include <linux/module.h>
20#include <linux/types.h>
21
22#include <net/checksum.h>
23#include <asm/byteorder.h>
24#include <asm/string.h>
25#include <asm/uaccess.h>
26
27#define addc(_t,_r) \
28 __asm__ __volatile__ ( \
29" add %0, %1, %0\n" \
30" addc %0, %%r0, %0\n" \
31 : "=r"(_t) \
32 : "r"(_r), "0"(_t));
33
34static inline unsigned short from32to16(unsigned int x)
35{
36 /* 32 bits --> 16 bits + carry */
37 x = (x & 0xffff) + (x >> 16);
38 /* 16 bits + carry --> 16 bits including carry */
39 x = (x & 0xffff) + (x >> 16);
40 return (unsigned short)x;
41}
42
43static inline unsigned int do_csum(const unsigned char * buff, int len)
44{
45 int odd, count;
46 unsigned int result = 0;
47
48 if (len <= 0)
49 goto out;
50 odd = 1 & (unsigned long) buff;
51 if (odd) {
52 result = be16_to_cpu(*buff);
53 len--;
54 buff++;
55 }
56 count = len >> 1; /* nr of 16-bit words.. */
57 if (count) {
58 if (2 & (unsigned long) buff) {
59 result += *(unsigned short *) buff;
60 count--;
61 len -= 2;
62 buff += 2;
63 }
64 count >>= 1; /* nr of 32-bit words.. */
65 if (count) {
66 while (count >= 4) {
67 unsigned int r1, r2, r3, r4;
68 r1 = *(unsigned int *)(buff + 0);
69 r2 = *(unsigned int *)(buff + 4);
70 r3 = *(unsigned int *)(buff + 8);
71 r4 = *(unsigned int *)(buff + 12);
72 addc(result, r1);
73 addc(result, r2);
74 addc(result, r3);
75 addc(result, r4);
76 count -= 4;
77 buff += 16;
78 }
79 while (count) {
80 unsigned int w = *(unsigned int *) buff;
81 count--;
82 buff += 4;
83 addc(result, w);
84 }
85 result = (result & 0xffff) + (result >> 16);
86 }
87 if (len & 2) {
88 result += *(unsigned short *) buff;
89 buff += 2;
90 }
91 }
92 if (len & 1)
93 result += le16_to_cpu(*buff);
94 result = from32to16(result);
95 if (odd)
96 result = swab16(result);
97out:
98 return result;
99}
100
101/*
102 * computes a partial checksum, e.g. for TCP/UDP fragments
103 */
104unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
105{
106 unsigned int result = do_csum(buff, len);
107 addc(result, sum);
108 return from32to16(result);
109}
110
111EXPORT_SYMBOL(csum_partial);
112
113/*
114 * copy while checksumming, otherwise like csum_partial
115 */
116unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
117 int len, unsigned int sum)
118{
119 /*
120 * It's 2:30 am and I don't feel like doing it real ...
121 * This is lots slower than the real thing (tm)
122 */
123 sum = csum_partial(src, len, sum);
124 memcpy(dst, src, len);
125
126 return sum;
127}
128EXPORT_SYMBOL(csum_partial_copy_nocheck);
129
130/*
131 * Copy from userspace and compute checksum. If we catch an exception
132 * then zero the rest of the buffer.
133 */
134unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
135 unsigned char *dst, int len,
136 unsigned int sum, int *err_ptr)
137{
138 int missing;
139
140 missing = copy_from_user(dst, src, len);
141 if (missing) {
142 memset(dst + len - missing, 0, missing);
143 *err_ptr = -EFAULT;
144 }
145
146 return csum_partial(dst, len, sum);
147}
148EXPORT_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 @@
1/*
2 * Debugging versions of SMP locking primitives.
3 *
4 * Copyright (C) 2004 Thibaut VARENE <varenet@parisc-linux.org>
5 *
6 * Some code stollen from alpha & sparc64 ;)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * We use pdc_printf() throughout the file for all output messages, to avoid
23 * losing messages because of disabled interrupts. Since we're using these
24 * messages for debugging purposes, it makes sense not to send them to the
25 * linux console.
26 */
27
28
29#include <linux/config.h>
30#include <linux/kernel.h>
31#include <linux/sched.h>
32#include <linux/spinlock.h>
33#include <linux/hardirq.h> /* in_interrupt() */
34#include <asm/system.h>
35#include <asm/hardirq.h> /* in_interrupt() */
36#include <asm/pdc.h>
37
38#undef INIT_STUCK
39#define INIT_STUCK 1L << 30
40
41#ifdef CONFIG_DEBUG_SPINLOCK
42
43
44void _dbg_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
45{
46 volatile unsigned int *a;
47 long stuck = INIT_STUCK;
48 void *inline_pc = __builtin_return_address(0);
49 unsigned long started = jiffies;
50 int printed = 0;
51 int cpu = smp_processor_id();
52
53try_again:
54
55 /* Do the actual locking */
56 /* <T-Bone> ggg: we can't get stuck on the outter loop?
57 * <ggg> T-Bone: We can hit the outer loop
58 * alot if multiple CPUs are constantly racing for a lock
59 * and the backplane is NOT fair about which CPU sees
60 * the update first. But it won't hang since every failed
61 * attempt will drop us back into the inner loop and
62 * decrement `stuck'.
63 * <ggg> K-class and some of the others are NOT fair in the HW
64 * implementation so we could see false positives.
65 * But fixing the lock contention is easier than
66 * fixing the HW to be fair.
67 * <tausq> __ldcw() returns 1 if we get the lock; otherwise we
68 * spin until the value of the lock changes, or we time out.
69 */
70 mb();
71 a = __ldcw_align(lock);
72 while (stuck && (__ldcw(a) == 0))
73 while ((*a == 0) && --stuck);
74 mb();
75
76 if (unlikely(stuck <= 0)) {
77 pdc_printf(
78 "%s:%d: spin_lock(%s/%p) stuck in %s at %p(%d)"
79 " owned by %s:%d in %s at %p(%d)\n",
80 base_file, line_no, lock->module, lock,
81 current->comm, inline_pc, cpu,
82 lock->bfile, lock->bline, lock->task->comm,
83 lock->previous, lock->oncpu);
84 stuck = INIT_STUCK;
85 printed = 1;
86 goto try_again;
87 }
88
89 /* Exiting. Got the lock. */
90 lock->oncpu = cpu;
91 lock->previous = inline_pc;
92 lock->task = current;
93 lock->bfile = (char *)base_file;
94 lock->bline = line_no;
95
96 if (unlikely(printed)) {
97 pdc_printf(
98 "%s:%d: spin_lock grabbed in %s at %p(%d) %ld ticks\n",
99 base_file, line_no, current->comm, inline_pc,
100 cpu, jiffies - started);
101 }
102}
103
104void _dbg_spin_unlock(spinlock_t * lock, const char *base_file, int line_no)
105{
106 CHECK_LOCK(lock);
107 volatile unsigned int *a;
108 mb();
109 a = __ldcw_align(lock);
110 if (unlikely((*a != 0) && lock->babble)) {
111 lock->babble--;
112 pdc_printf(
113 "%s:%d: spin_unlock(%s:%p) not locked\n",
114 base_file, line_no, lock->module, lock);
115 }
116 *a = 1;
117 mb();
118}
119
120int _dbg_spin_trylock(spinlock_t * lock, const char *base_file, int line_no)
121{
122 int ret;
123 volatile unsigned int *a;
124 mb();
125 a = __ldcw_align(lock);
126 ret = (__ldcw(a) != 0);
127 mb();
128 if (ret) {
129 lock->oncpu = smp_processor_id();
130 lock->previous = __builtin_return_address(0);
131 lock->task = current;
132 } else {
133 lock->bfile = (char *)base_file;
134 lock->bline = line_no;
135 }
136 return ret;
137}
138
139#endif /* CONFIG_DEBUG_SPINLOCK */
140
141#ifdef CONFIG_DEBUG_RWLOCK
142
143/* Interrupts trouble detailed explanation, thx Grant:
144 *
145 * o writer (wants to modify data) attempts to acquire the rwlock
146 * o He gets the write lock.
147 * o Interupts are still enabled, we take an interrupt with the
148 * write still holding the lock.
149 * o interrupt handler tries to acquire the rwlock for read.
150 * o deadlock since the writer can't release it at this point.
151 *
152 * In general, any use of spinlocks that competes between "base"
153 * level and interrupt level code will risk deadlock. Interrupts
154 * need to be disabled in the base level routines to avoid it.
155 * Or more precisely, only the IRQ the base level routine
156 * is competing with for the lock. But it's more efficient/faster
157 * to just disable all interrupts on that CPU to guarantee
158 * once it gets the lock it can release it quickly too.
159 */
160
161void _dbg_write_lock(rwlock_t *rw, const char *bfile, int bline)
162{
163 void *inline_pc = __builtin_return_address(0);
164 unsigned long started = jiffies;
165 long stuck = INIT_STUCK;
166 int printed = 0;
167 int cpu = smp_processor_id();
168
169 if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */
170 pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
171 BUG();
172 }
173
174 /* Note: if interrupts are disabled (which is most likely), the printk
175 will never show on the console. We might need a polling method to flush
176 the dmesg buffer anyhow. */
177
178retry:
179 _raw_spin_lock(&rw->lock);
180
181 if(rw->counter != 0) {
182 /* this basically never happens */
183 _raw_spin_unlock(&rw->lock);
184
185 stuck--;
186 if ((unlikely(stuck <= 0)) && (rw->counter < 0)) {
187 pdc_printf(
188 "%s:%d: write_lock stuck on writer"
189 " in %s at %p(%d) %ld ticks\n",
190 bfile, bline, current->comm, inline_pc,
191 cpu, jiffies - started);
192 stuck = INIT_STUCK;
193 printed = 1;
194 }
195 else if (unlikely(stuck <= 0)) {
196 pdc_printf(
197 "%s:%d: write_lock stuck on reader"
198 " in %s at %p(%d) %ld ticks\n",
199 bfile, bline, current->comm, inline_pc,
200 cpu, jiffies - started);
201 stuck = INIT_STUCK;
202 printed = 1;
203 }
204
205 while(rw->counter != 0);
206
207 goto retry;
208 }
209
210 /* got it. now leave without unlocking */
211 rw->counter = -1; /* remember we are locked */
212
213 if (unlikely(printed)) {
214 pdc_printf(
215 "%s:%d: write_lock grabbed in %s at %p(%d) %ld ticks\n",
216 bfile, bline, current->comm, inline_pc,
217 cpu, jiffies - started);
218 }
219}
220
221int _dbg_write_trylock(rwlock_t *rw, const char *bfile, int bline)
222{
223#if 0
224 void *inline_pc = __builtin_return_address(0);
225 int cpu = smp_processor_id();
226#endif
227
228 if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */
229 pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
230 BUG();
231 }
232
233 /* Note: if interrupts are disabled (which is most likely), the printk
234 will never show on the console. We might need a polling method to flush
235 the dmesg buffer anyhow. */
236
237 _raw_spin_lock(&rw->lock);
238
239 if(rw->counter != 0) {
240 /* this basically never happens */
241 _raw_spin_unlock(&rw->lock);
242 return 0;
243 }
244
245 /* got it. now leave without unlocking */
246 rw->counter = -1; /* remember we are locked */
247#if 0
248 pdc_printf("%s:%d: try write_lock grabbed in %s at %p(%d)\n",
249 bfile, bline, current->comm, inline_pc, cpu);
250#endif
251 return 1;
252}
253
254void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline)
255{
256#if 0
257 void *inline_pc = __builtin_return_address(0);
258 unsigned long started = jiffies;
259 int cpu = smp_processor_id();
260#endif
261 unsigned long flags;
262
263 local_irq_save(flags);
264 _raw_spin_lock(&rw->lock);
265
266 rw->counter++;
267#if 0
268 pdc_printf(
269 "%s:%d: read_lock grabbed in %s at %p(%d) %ld ticks\n",
270 bfile, bline, current->comm, inline_pc,
271 cpu, jiffies - started);
272#endif
273 _raw_spin_unlock(&rw->lock);
274 local_irq_restore(flags);
275}
276
277#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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Copyright (C) 2004 Randolph Chung <tausq@debian.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * Fixup routines for kernel exception handling.
21 */
22#include <linux/config.h>
23#include <asm/offsets.h>
24#include <asm/assembly.h>
25#include <asm/errno.h>
26
27#ifdef CONFIG_SMP
28 .macro get_fault_ip t1 t2
29 addil LT%__per_cpu_offset,%r27
30 LDREG RT%__per_cpu_offset(%r1),\t1
31 /* t2 = smp_processor_id() */
32 mfctl 30,\t2
33 ldw TI_CPU(\t2),\t2
34#ifdef __LP64__
35 extrd,u \t2,63,32,\t2
36#endif
37 /* t2 = &__per_cpu_offset[smp_processor_id()]; */
38 LDREG,s \t2(\t1),\t2
39 addil LT%per_cpu__exception_data,%r27
40 LDREG RT%per_cpu__exception_data(%r1),\t1
41 /* t1 = &__get_cpu_var(exception_data) */
42 add,l \t1,\t2,\t1
43 /* t1 = t1->fault_ip */
44 LDREG EXCDATA_IP(\t1), \t1
45 .endm
46#else
47 .macro get_fault_ip t1 t2
48 /* t1 = &__get_cpu_var(exception_data) */
49 addil LT%per_cpu__exception_data,%r27
50 LDREG RT%per_cpu__exception_data(%r1),\t2
51 /* t1 = t2->fault_ip */
52 LDREG EXCDATA_IP(\t2), \t1
53 .endm
54#endif
55
56 .text
57 .section .fixup, "ax"
58
59 /* get_user() fixups, store -EFAULT in r8, and 0 in r9 */
60 .export fixup_get_user_skip_1
61fixup_get_user_skip_1:
62 get_fault_ip %r1,%r8
63 ldo 4(%r1), %r1
64 ldi -EFAULT, %r8
65 bv %r0(%r1)
66 copy %r0, %r9
67
68 .export fixup_get_user_skip_2
69fixup_get_user_skip_2:
70 get_fault_ip %r1,%r8
71 ldo 8(%r1), %r1
72 ldi -EFAULT, %r8
73 bv %r0(%r1)
74 copy %r0, %r9
75
76 /* put_user() fixups, store -EFAULT in r8 */
77 .export fixup_put_user_skip_1
78fixup_put_user_skip_1:
79 get_fault_ip %r1,%r8
80 ldo 4(%r1), %r1
81 bv %r0(%r1)
82 ldi -EFAULT, %r8
83
84 .export fixup_put_user_skip_2
85fixup_put_user_skip_2:
86 get_fault_ip %r1,%r8
87 ldo 8(%r1), %r1
88 bv %r0(%r1)
89 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 @@
1/*
2 * arch/parisc/lib/io.c
3 *
4 * Copyright (c) Matthew Wilcox 2001 for Hewlett-Packard
5 * Copyright (c) Randolph Chung 2001 <tausq@debian.org>
6 *
7 * IO accessing functions which shouldn't be inlined because they're too big
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <asm/io.h>
13
14/* Copies a block of memory to a device in an efficient manner.
15 * Assumes the device can cope with 32-bit transfers. If it can't,
16 * don't use this function.
17 */
18void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
19{
20 if (((unsigned long)dst & 3) != ((unsigned long)src & 3))
21 goto bytecopy;
22 while ((unsigned long)dst & 3) {
23 writeb(*(char *)src, dst++);
24 src++;
25 count--;
26 }
27 while (count > 3) {
28 __raw_writel(*(u32 *)src, dst);
29 src += 4;
30 dst += 4;
31 count -= 4;
32 }
33 bytecopy:
34 while (count--) {
35 writeb(*(char *)src, dst++);
36 src++;
37 }
38}
39
40/*
41** Copies a block of memory from a device in an efficient manner.
42** Assumes the device can cope with 32-bit transfers. If it can't,
43** don't use this function.
44**
45** CR16 counts on C3000 reading 256 bytes from Symbios 896 RAM:
46** 27341/64 = 427 cyc per int
47** 61311/128 = 478 cyc per short
48** 122637/256 = 479 cyc per byte
49** Ergo bus latencies dominant (not transfer size).
50** Minimize total number of transfers at cost of CPU cycles.
51** TODO: only look at src alignment and adjust the stores to dest.
52*/
53void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
54{
55 /* first compare alignment of src/dst */
56 if ( (((unsigned long)dst ^ (unsigned long)src) & 1) || (count < 2) )
57 goto bytecopy;
58
59 if ( (((unsigned long)dst ^ (unsigned long)src) & 2) || (count < 4) )
60 goto shortcopy;
61
62 /* Then check for misaligned start address */
63 if ((unsigned long)src & 1) {
64 *(u8 *)dst = readb(src);
65 src++;
66 dst++;
67 count--;
68 if (count < 2) goto bytecopy;
69 }
70
71 if ((unsigned long)src & 2) {
72 *(u16 *)dst = __raw_readw(src);
73 src += 2;
74 dst += 2;
75 count -= 2;
76 }
77
78 while (count > 3) {
79 *(u32 *)dst = __raw_readl(src);
80 dst += 4;
81 src += 4;
82 count -= 4;
83 }
84
85 shortcopy:
86 while (count > 1) {
87 *(u16 *)dst = __raw_readw(src);
88 src += 2;
89 dst += 2;
90 count -= 2;
91 }
92
93 bytecopy:
94 while (count--) {
95 *(char *)dst = readb(src);
96 src++;
97 dst++;
98 }
99}
100
101/* Sets a block of memory on a device to a given value.
102 * Assumes the device can cope with 32-bit transfers. If it can't,
103 * don't use this function.
104 */
105void memset_io(volatile void __iomem *addr, unsigned char val, int count)
106{
107 u32 val32 = (val << 24) | (val << 16) | (val << 8) | val;
108 while ((unsigned long)addr & 3) {
109 writeb(val, addr++);
110 count--;
111 }
112 while (count > 3) {
113 __raw_writel(val32, addr);
114 addr += 4;
115 count -= 4;
116 }
117 while (count--) {
118 writeb(val, addr++);
119 }
120}
121
122/*
123 * Read COUNT 8-bit bytes from port PORT into memory starting at
124 * SRC.
125 */
126void insb (unsigned long port, void *dst, unsigned long count)
127{
128 unsigned char *p;
129
130 p = (unsigned char *)dst;
131
132 while (((unsigned long)p) & 0x3) {
133 if (!count)
134 return;
135 count--;
136 *p = inb(port);
137 p++;
138 }
139
140 while (count >= 4) {
141 unsigned int w;
142 count -= 4;
143 w = inb(port) << 24;
144 w |= inb(port) << 16;
145 w |= inb(port) << 8;
146 w |= inb(port);
147 *(unsigned int *) p = w;
148 p += 4;
149 }
150
151 while (count) {
152 --count;
153 *p = inb(port);
154 p++;
155 }
156}
157
158
159/*
160 * Read COUNT 16-bit words from port PORT into memory starting at
161 * SRC. SRC must be at least short aligned. This is used by the
162 * IDE driver to read disk sectors. Performance is important, but
163 * the interfaces seems to be slow: just using the inlined version
164 * of the inw() breaks things.
165 */
166void insw (unsigned long port, void *dst, unsigned long count)
167{
168 unsigned int l = 0, l2;
169 unsigned char *p;
170
171 p = (unsigned char *)dst;
172
173 if (!count)
174 return;
175
176 switch (((unsigned long)p) & 0x3)
177 {
178 case 0x00: /* Buffer 32-bit aligned */
179 while (count>=2) {
180
181 count -= 2;
182 l = cpu_to_le16(inw(port)) << 16;
183 l |= cpu_to_le16(inw(port));
184 *(unsigned int *)p = l;
185 p += 4;
186 }
187 if (count) {
188 *(unsigned short *)p = cpu_to_le16(inw(port));
189 }
190 break;
191
192 case 0x02: /* Buffer 16-bit aligned */
193 *(unsigned short *)p = cpu_to_le16(inw(port));
194 p += 2;
195 count--;
196 while (count>=2) {
197
198 count -= 2;
199 l = cpu_to_le16(inw(port)) << 16;
200 l |= cpu_to_le16(inw(port));
201 *(unsigned int *)p = l;
202 p += 4;
203 }
204 if (count) {
205 *(unsigned short *)p = cpu_to_le16(inw(port));
206 }
207 break;
208
209 case 0x01: /* Buffer 8-bit aligned */
210 case 0x03:
211 /* I don't bother with 32bit transfers
212 * in this case, 16bit will have to do -- DE */
213 --count;
214
215 l = cpu_to_le16(inw(port));
216 *p = l >> 8;
217 p++;
218 while (count--)
219 {
220 l2 = cpu_to_le16(inw(port));
221 *(unsigned short *)p = (l & 0xff) << 8 | (l2 >> 8);
222 p += 2;
223 l = l2;
224 }
225 *p = l & 0xff;
226 break;
227 }
228}
229
230
231
232/*
233 * Read COUNT 32-bit words from port PORT into memory starting at
234 * SRC. Now works with any alignment in SRC. Performance is important,
235 * but the interfaces seems to be slow: just using the inlined version
236 * of the inl() breaks things.
237 */
238void insl (unsigned long port, void *dst, unsigned long count)
239{
240 unsigned int l = 0, l2;
241 unsigned char *p;
242
243 p = (unsigned char *)dst;
244
245 if (!count)
246 return;
247
248 switch (((unsigned long) dst) & 0x3)
249 {
250 case 0x00: /* Buffer 32-bit aligned */
251 while (count--)
252 {
253 *(unsigned int *)p = cpu_to_le32(inl(port));
254 p += 4;
255 }
256 break;
257
258 case 0x02: /* Buffer 16-bit aligned */
259 --count;
260
261 l = cpu_to_le32(inl(port));
262 *(unsigned short *)p = l >> 16;
263 p += 2;
264
265 while (count--)
266 {
267 l2 = cpu_to_le32(inl(port));
268 *(unsigned int *)p = (l & 0xffff) << 16 | (l2 >> 16);
269 p += 4;
270 l = l2;
271 }
272 *(unsigned short *)p = l & 0xffff;
273 break;
274 case 0x01: /* Buffer 8-bit aligned */
275 --count;
276
277 l = cpu_to_le32(inl(port));
278 *(unsigned char *)p = l >> 24;
279 p++;
280 *(unsigned short *)p = (l >> 8) & 0xffff;
281 p += 2;
282 while (count--)
283 {
284 l2 = cpu_to_le32(inl(port));
285 *(unsigned int *)p = (l & 0xff) << 24 | (l2 >> 8);
286 p += 4;
287 l = l2;
288 }
289 *p = l & 0xff;
290 break;
291 case 0x03: /* Buffer 8-bit aligned */
292 --count;
293
294 l = cpu_to_le32(inl(port));
295 *p = l >> 24;
296 p++;
297 while (count--)
298 {
299 l2 = cpu_to_le32(inl(port));
300 *(unsigned int *)p = (l & 0xffffff) << 8 | l2 >> 24;
301 p += 4;
302 l = l2;
303 }
304 *(unsigned short *)p = (l >> 8) & 0xffff;
305 p += 2;
306 *p = l & 0xff;
307 break;
308 }
309}
310
311
312/*
313 * Like insb but in the opposite direction.
314 * Don't worry as much about doing aligned memory transfers:
315 * doing byte reads the "slow" way isn't nearly as slow as
316 * doing byte writes the slow way (no r-m-w cycle).
317 */
318void outsb(unsigned long port, const void * src, unsigned long count)
319{
320 const unsigned char *p;
321
322 p = (const unsigned char *)src;
323 while (count) {
324 count--;
325 outb(*p, port);
326 p++;
327 }
328}
329
330/*
331 * Like insw but in the opposite direction. This is used by the IDE
332 * driver to write disk sectors. Performance is important, but the
333 * interfaces seems to be slow: just using the inlined version of the
334 * outw() breaks things.
335 */
336void outsw (unsigned long port, const void *src, unsigned long count)
337{
338 unsigned int l = 0, l2;
339 const unsigned char *p;
340
341 p = (const unsigned char *)src;
342
343 if (!count)
344 return;
345
346 switch (((unsigned long)p) & 0x3)
347 {
348 case 0x00: /* Buffer 32-bit aligned */
349 while (count>=2) {
350 count -= 2;
351 l = *(unsigned int *)p;
352 p += 4;
353 outw(le16_to_cpu(l >> 16), port);
354 outw(le16_to_cpu(l & 0xffff), port);
355 }
356 if (count) {
357 outw(le16_to_cpu(*(unsigned short*)p), port);
358 }
359 break;
360
361 case 0x02: /* Buffer 16-bit aligned */
362
363 outw(le16_to_cpu(*(unsigned short*)p), port);
364 p += 2;
365 count--;
366
367 while (count>=2) {
368 count -= 2;
369 l = *(unsigned int *)p;
370 p += 4;
371 outw(le16_to_cpu(l >> 16), port);
372 outw(le16_to_cpu(l & 0xffff), port);
373 }
374 if (count) {
375 outw(le16_to_cpu(*(unsigned short *)p), port);
376 }
377 break;
378
379 case 0x01: /* Buffer 8-bit aligned */
380 /* I don't bother with 32bit transfers
381 * in this case, 16bit will have to do -- DE */
382
383 l = *p << 8;
384 p++;
385 count--;
386 while (count)
387 {
388 count--;
389 l2 = *(unsigned short *)p;
390 p += 2;
391 outw(le16_to_cpu(l | l2 >> 8), port);
392 l = l2 << 8;
393 }
394 l2 = *(unsigned char *)p;
395 outw (le16_to_cpu(l | l2>>8), port);
396 break;
397
398 }
399}
400
401
402/*
403 * Like insl but in the opposite direction. This is used by the IDE
404 * driver to write disk sectors. Works with any alignment in SRC.
405 * Performance is important, but the interfaces seems to be slow:
406 * just using the inlined version of the outl() breaks things.
407 */
408void outsl (unsigned long port, const void *src, unsigned long count)
409{
410 unsigned int l = 0, l2;
411 const unsigned char *p;
412
413 p = (const unsigned char *)src;
414
415 if (!count)
416 return;
417
418 switch (((unsigned long)p) & 0x3)
419 {
420 case 0x00: /* Buffer 32-bit aligned */
421 while (count--)
422 {
423 outl(le32_to_cpu(*(unsigned int *)p), port);
424 p += 4;
425 }
426 break;
427
428 case 0x02: /* Buffer 16-bit aligned */
429 --count;
430
431 l = *(unsigned short *)p;
432 p += 2;
433
434 while (count--)
435 {
436 l2 = *(unsigned int *)p;
437 p += 4;
438 outl (le32_to_cpu(l << 16 | l2 >> 16), port);
439 l = l2;
440 }
441 l2 = *(unsigned short *)p;
442 outl (le32_to_cpu(l << 16 | l2), port);
443 break;
444 case 0x01: /* Buffer 8-bit aligned */
445 --count;
446
447 l = *p << 24;
448 p++;
449 l |= *(unsigned short *)p << 8;
450 p += 2;
451
452 while (count--)
453 {
454 l2 = *(unsigned int *)p;
455 p += 4;
456 outl (le32_to_cpu(l | l2 >> 24), port);
457 l = l2 << 8;
458 }
459 l2 = *p;
460 outl (le32_to_cpu(l | l2), port);
461 break;
462 case 0x03: /* Buffer 8-bit aligned */
463 --count;
464
465 l = *p << 24;
466 p++;
467
468 while (count--)
469 {
470 l2 = *(unsigned int *)p;
471 p += 4;
472 outl (le32_to_cpu(l | l2 >> 8), port);
473 l = l2 << 24;
474 }
475 l2 = *(unsigned short *)p << 16;
476 p += 2;
477 l2 |= *p;
478 outl (le32_to_cpu(l | l2), port);
479 break;
480 }
481}
482
483EXPORT_SYMBOL(insb);
484EXPORT_SYMBOL(insw);
485EXPORT_SYMBOL(insl);
486EXPORT_SYMBOL(outsb);
487EXPORT_SYMBOL(outsw);
488EXPORT_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 @@
1/*
2 * iomap.c - Implement iomap interface for PA-RISC
3 * Copyright (c) 2004 Matthew Wilcox
4 */
5
6#include <linux/ioport.h>
7#include <linux/pci.h>
8#include <asm/io.h>
9
10/*
11 * The iomap space on 32-bit PA-RISC is intended to look like this:
12 * 00000000-7fffffff virtual mapped IO
13 * 80000000-8fffffff ISA/EISA port space that can't be virtually mapped
14 * 90000000-9fffffff Dino port space
15 * a0000000-afffffff Astro port space
16 * b0000000-bfffffff PAT port space
17 * c0000000-cfffffff non-swapped memory IO
18 * f0000000-ffffffff legacy IO memory pointers
19 *
20 * For the moment, here's what it looks like:
21 * 80000000-8fffffff All ISA/EISA port space
22 * f0000000-ffffffff legacy IO memory pointers
23 *
24 * On 64-bit, everything is extended, so:
25 * 8000000000000000-8fffffffffffffff All ISA/EISA port space
26 * f000000000000000-ffffffffffffffff legacy IO memory pointers
27 */
28
29/*
30 * Technically, this should be 'if (VMALLOC_START < addr < VMALLOC_END),
31 * but that's slow and we know it'll be within the first 2GB.
32 */
33#ifdef CONFIG_64BIT
34#define INDIRECT_ADDR(addr) (((unsigned long)(addr) & 1UL<<63) != 0)
35#define ADDR_TO_REGION(addr) (((unsigned long)addr >> 60) & 7)
36#define IOPORT_MAP_BASE (8UL << 60)
37#else
38#define INDIRECT_ADDR(addr) (((unsigned long)(addr) & 1UL<<31) != 0)
39#define ADDR_TO_REGION(addr) (((unsigned long)addr >> 28) & 7)
40#define IOPORT_MAP_BASE (8UL << 28)
41#endif
42
43struct iomap_ops {
44 unsigned int (*read8)(void __iomem *);
45 unsigned int (*read16)(void __iomem *);
46 unsigned int (*read32)(void __iomem *);
47 void (*write8)(u8, void __iomem *);
48 void (*write16)(u16, void __iomem *);
49 void (*write32)(u32, void __iomem *);
50 void (*read8r)(void __iomem *, void *, unsigned long);
51 void (*read16r)(void __iomem *, void *, unsigned long);
52 void (*read32r)(void __iomem *, void *, unsigned long);
53 void (*write8r)(void __iomem *, const void *, unsigned long);
54 void (*write16r)(void __iomem *, const void *, unsigned long);
55 void (*write32r)(void __iomem *, const void *, unsigned long);
56};
57
58/* Generic ioport ops. To be replaced later by specific dino/elroy/wax code */
59
60#define ADDR2PORT(addr) ((unsigned long __force)(addr) & 0xffffff)
61
62static unsigned int ioport_read8(void __iomem *addr)
63{
64 return inb(ADDR2PORT(addr));
65}
66
67static unsigned int ioport_read16(void __iomem *addr)
68{
69 return inw(ADDR2PORT(addr));
70}
71
72static unsigned int ioport_read32(void __iomem *addr)
73{
74 return inl(ADDR2PORT(addr));
75}
76
77static void ioport_write8(u8 datum, void __iomem *addr)
78{
79 outb(datum, ADDR2PORT(addr));
80}
81
82static void ioport_write16(u16 datum, void __iomem *addr)
83{
84 outw(datum, ADDR2PORT(addr));
85}
86
87static void ioport_write32(u32 datum, void __iomem *addr)
88{
89 outl(datum, ADDR2PORT(addr));
90}
91
92static void ioport_read8r(void __iomem *addr, void *dst, unsigned long count)
93{
94 insb(ADDR2PORT(addr), dst, count);
95}
96
97static void ioport_read16r(void __iomem *addr, void *dst, unsigned long count)
98{
99 insw(ADDR2PORT(addr), dst, count);
100}
101
102static void ioport_read32r(void __iomem *addr, void *dst, unsigned long count)
103{
104 insl(ADDR2PORT(addr), dst, count);
105}
106
107static void ioport_write8r(void __iomem *addr, const void *s, unsigned long n)
108{
109 outsb(ADDR2PORT(addr), s, n);
110}
111
112static void ioport_write16r(void __iomem *addr, const void *s, unsigned long n)
113{
114 outsw(ADDR2PORT(addr), s, n);
115}
116
117static void ioport_write32r(void __iomem *addr, const void *s, unsigned long n)
118{
119 outsl(ADDR2PORT(addr), s, n);
120}
121
122static const struct iomap_ops ioport_ops = {
123 ioport_read8,
124 ioport_read16,
125 ioport_read32,
126 ioport_write8,
127 ioport_write16,
128 ioport_write32,
129 ioport_read8r,
130 ioport_read16r,
131 ioport_read32r,
132 ioport_write8r,
133 ioport_write16r,
134 ioport_write32r,
135};
136
137/* Legacy I/O memory ops */
138
139static unsigned int iomem_read8(void __iomem *addr)
140{
141 return readb(addr);
142}
143
144static unsigned int iomem_read16(void __iomem *addr)
145{
146 return readw(addr);
147}
148
149static unsigned int iomem_read32(void __iomem *addr)
150{
151 return readl(addr);
152}
153
154static void iomem_write8(u8 datum, void __iomem *addr)
155{
156 writeb(datum, addr);
157}
158
159static void iomem_write16(u16 datum, void __iomem *addr)
160{
161 writew(datum, addr);
162}
163
164static void iomem_write32(u32 datum, void __iomem *addr)
165{
166 writel(datum, addr);
167}
168
169static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count)
170{
171 while (count--) {
172 *(u8 *)dst = __raw_readb(addr);
173 dst++;
174 }
175}
176
177static void iomem_read16r(void __iomem *addr, void *dst, unsigned long count)
178{
179 while (count--) {
180 *(u16 *)dst = __raw_readw(addr);
181 dst += 2;
182 }
183}
184
185static void iomem_read32r(void __iomem *addr, void *dst, unsigned long count)
186{
187 while (count--) {
188 *(u32 *)dst = __raw_readl(addr);
189 dst += 4;
190 }
191}
192
193static void iomem_write8r(void __iomem *addr, const void *s, unsigned long n)
194{
195 while (n--) {
196 __raw_writeb(*(u8 *)s, addr);
197 s++;
198 }
199}
200
201static void iomem_write16r(void __iomem *addr, const void *s, unsigned long n)
202{
203 while (n--) {
204 __raw_writew(*(u16 *)s, addr);
205 s += 2;
206 }
207}
208
209static void iomem_write32r(void __iomem *addr, const void *s, unsigned long n)
210{
211 while (n--) {
212 __raw_writel(*(u32 *)s, addr);
213 s += 4;
214 }
215}
216
217static const struct iomap_ops iomem_ops = {
218 iomem_read8,
219 iomem_read16,
220 iomem_read32,
221 iomem_write8,
222 iomem_write16,
223 iomem_write32,
224 iomem_read8r,
225 iomem_read16r,
226 iomem_read32r,
227 iomem_write8r,
228 iomem_write16r,
229 iomem_write32r,
230};
231
232const struct iomap_ops *iomap_ops[8] = {
233 [0] = &ioport_ops,
234#ifdef CONFIG_DEBUG_IOREMAP
235 [6] = &iomem_ops,
236#else
237 [7] = &iomem_ops
238#endif
239};
240
241
242unsigned int ioread8(void __iomem *addr)
243{
244 if (unlikely(INDIRECT_ADDR(addr)))
245 return iomap_ops[ADDR_TO_REGION(addr)]->read8(addr);
246 return *((u8 *)addr);
247}
248
249unsigned int ioread16(void __iomem *addr)
250{
251 if (unlikely(INDIRECT_ADDR(addr)))
252 return iomap_ops[ADDR_TO_REGION(addr)]->read16(addr);
253 return le16_to_cpup((u16 *)addr);
254}
255
256unsigned int ioread32(void __iomem *addr)
257{
258 if (unlikely(INDIRECT_ADDR(addr)))
259 return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr);
260 return le32_to_cpup((u32 *)addr);
261}
262
263void iowrite8(u8 datum, void __iomem *addr)
264{
265 if (unlikely(INDIRECT_ADDR(addr))) {
266 iomap_ops[ADDR_TO_REGION(addr)]->write8(datum, addr);
267 } else {
268 *((u8 *)addr) = datum;
269 }
270}
271
272void iowrite16(u16 datum, void __iomem *addr)
273{
274 if (unlikely(INDIRECT_ADDR(addr))) {
275 iomap_ops[ADDR_TO_REGION(addr)]->write16(datum, addr);
276 } else {
277 *((u16 *)addr) = cpu_to_le16(datum);
278 }
279}
280
281void iowrite32(u32 datum, void __iomem *addr)
282{
283 if (unlikely(INDIRECT_ADDR(addr))) {
284 iomap_ops[ADDR_TO_REGION(addr)]->write32(datum, addr);
285 } else {
286 *((u32 *)addr) = cpu_to_le32(datum);
287 }
288}
289
290/* Repeating interfaces */
291
292void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
293{
294 if (unlikely(INDIRECT_ADDR(addr))) {
295 iomap_ops[ADDR_TO_REGION(addr)]->read8r(addr, dst, count);
296 } else {
297 while (count--) {
298 *(u8 *)dst = *(u8 *)addr;
299 dst++;
300 }
301 }
302}
303
304void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
305{
306 if (unlikely(INDIRECT_ADDR(addr))) {
307 iomap_ops[ADDR_TO_REGION(addr)]->read16r(addr, dst, count);
308 } else {
309 while (count--) {
310 *(u16 *)dst = *(u16 *)addr;
311 dst += 2;
312 }
313 }
314}
315
316void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
317{
318 if (unlikely(INDIRECT_ADDR(addr))) {
319 iomap_ops[ADDR_TO_REGION(addr)]->read32r(addr, dst, count);
320 } else {
321 while (count--) {
322 *(u32 *)dst = *(u32 *)addr;
323 dst += 4;
324 }
325 }
326}
327
328void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
329{
330 if (unlikely(INDIRECT_ADDR(addr))) {
331 iomap_ops[ADDR_TO_REGION(addr)]->write8r(addr, src, count);
332 } else {
333 while (count--) {
334 *(u8 *)addr = *(u8 *)src;
335 src++;
336 }
337 }
338}
339
340void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
341{
342 if (unlikely(INDIRECT_ADDR(addr))) {
343 iomap_ops[ADDR_TO_REGION(addr)]->write16r(addr, src, count);
344 } else {
345 while (count--) {
346 *(u16 *)addr = *(u16 *)src;
347 src += 2;
348 }
349 }
350}
351
352void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
353{
354 if (unlikely(INDIRECT_ADDR(addr))) {
355 iomap_ops[ADDR_TO_REGION(addr)]->write32r(addr, src, count);
356 } else {
357 while (count--) {
358 *(u32 *)addr = *(u32 *)src;
359 src += 4;
360 }
361 }
362}
363
364/* Mapping interfaces */
365
366void __iomem *ioport_map(unsigned long port, unsigned int nr)
367{
368 return (void __iomem *)(IOPORT_MAP_BASE | port);
369}
370
371void ioport_unmap(void __iomem *addr)
372{
373 if (!INDIRECT_ADDR(addr)) {
374 iounmap(addr);
375 }
376}
377
378/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
379void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
380{
381 unsigned long start = pci_resource_start(dev, bar);
382 unsigned long len = pci_resource_len(dev, bar);
383 unsigned long flags = pci_resource_flags(dev, bar);
384
385 if (!len || !start)
386 return NULL;
387 if (maxlen && len > maxlen)
388 len = maxlen;
389 if (flags & IORESOURCE_IO)
390 return ioport_map(start, len);
391 if (flags & IORESOURCE_MEM) {
392 if (flags & IORESOURCE_CACHEABLE)
393 return ioremap(start, len);
394 return ioremap_nocache(start, len);
395 }
396 /* What? */
397 return NULL;
398}
399
400void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
401{
402 if (!INDIRECT_ADDR(addr)) {
403 iounmap(addr);
404 }
405}
406
407EXPORT_SYMBOL(ioread8);
408EXPORT_SYMBOL(ioread16);
409EXPORT_SYMBOL(ioread32);
410EXPORT_SYMBOL(iowrite8);
411EXPORT_SYMBOL(iowrite16);
412EXPORT_SYMBOL(iowrite32);
413EXPORT_SYMBOL(ioread8_rep);
414EXPORT_SYMBOL(ioread16_rep);
415EXPORT_SYMBOL(ioread32_rep);
416EXPORT_SYMBOL(iowrite8_rep);
417EXPORT_SYMBOL(iowrite16_rep);
418EXPORT_SYMBOL(iowrite32_rep);
419EXPORT_SYMBOL(ioport_map);
420EXPORT_SYMBOL(ioport_unmap);
421EXPORT_SYMBOL(pci_iomap);
422EXPORT_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 @@
1/*
2 * User Space Access Routines
3 *
4 * Copyright (C) 2000-2002 Hewlett-Packard (John Marvin)
5 * Copyright (C) 2000 Richard Hirst <rhirst with parisc-linux.org>
6 * Copyright (C) 2001 Matthieu Delahaye <delahaym at esiee.fr>
7 * Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25/*
26 * These routines still have plenty of room for optimization
27 * (word & doubleword load/store, dual issue, store hints, etc.).
28 */
29
30/*
31 * The following routines assume that space register 3 (sr3) contains
32 * the space id associated with the current users address space.
33 */
34
35
36 .text
37
38#include <asm/assembly.h>
39#include <asm/errno.h>
40
41 /*
42 * get_sr gets the appropriate space value into
43 * sr1 for kernel/user space access, depending
44 * on the flag stored in the task structure.
45 */
46
47 .macro get_sr
48 mfctl %cr30,%r1
49 ldw TI_SEGMENT(%r1),%r22
50 mfsp %sr3,%r1
51 or,<> %r22,%r0,%r0
52 copy %r0,%r1
53 mtsp %r1,%sr1
54 .endm
55
56 .macro fixup_branch lbl
57 ldil L%\lbl, %r1
58 ldo R%\lbl(%r1), %r1
59 bv %r0(%r1)
60 .endm
61
62 /*
63 * long lstrncpy_from_user(char *dst, const char *src, long n)
64 *
65 * Returns -EFAULT if exception before terminator,
66 * N if the entire buffer filled,
67 * otherwise strlen (i.e. excludes zero byte)
68 */
69
70 .export lstrncpy_from_user,code
71lstrncpy_from_user:
72 .proc
73 .callinfo NO_CALLS
74 .entry
75 comib,= 0,%r24,$lsfu_done
76 copy %r24,%r23
77 get_sr
781: ldbs,ma 1(%sr1,%r25),%r1
79$lsfu_loop:
80 stbs,ma %r1,1(%r26)
81 comib,=,n 0,%r1,$lsfu_done
82 addib,<>,n -1,%r24,$lsfu_loop
832: ldbs,ma 1(%sr1,%r25),%r1
84$lsfu_done:
85 sub %r23,%r24,%r28
86$lsfu_exit:
87 bv %r0(%r2)
88 nop
89 .exit
90
91 .section .fixup,"ax"
923: fixup_branch $lsfu_exit
93 ldi -EFAULT,%r28
94 .previous
95
96 .section __ex_table,"aw"
97#ifdef __LP64__
98 .dword 1b,3b
99 .dword 2b,3b
100#else
101 .word 1b,3b
102 .word 2b,3b
103#endif
104 .previous
105
106 .procend
107
108 /*
109 * unsigned long lclear_user(void *to, unsigned long n)
110 *
111 * Returns 0 for success.
112 * otherwise, returns number of bytes not transferred.
113 */
114
115 .export lclear_user,code
116lclear_user:
117 .proc
118 .callinfo NO_CALLS
119 .entry
120 comib,=,n 0,%r25,$lclu_done
121 get_sr
122$lclu_loop:
123 addib,<> -1,%r25,$lclu_loop
1241: stbs,ma %r0,1(%sr1,%r26)
125
126$lclu_done:
127 bv %r0(%r2)
128 copy %r25,%r28
129 .exit
130
131 .section .fixup,"ax"
1322: fixup_branch $lclu_done
133 ldo 1(%r25),%r25
134 .previous
135
136 .section __ex_table,"aw"
137#ifdef __LP64__
138 .dword 1b,2b
139#else
140 .word 1b,2b
141#endif
142 .previous
143
144 .procend
145
146 /*
147 * long lstrnlen_user(char *s, long n)
148 *
149 * Returns 0 if exception before zero byte or reaching N,
150 * N+1 if N would be exceeded,
151 * else strlen + 1 (i.e. includes zero byte).
152 */
153
154 .export lstrnlen_user,code
155lstrnlen_user:
156 .proc
157 .callinfo NO_CALLS
158 .entry
159 comib,= 0,%r25,$lslen_nzero
160 copy %r26,%r24
161 get_sr
1621: ldbs,ma 1(%sr1,%r26),%r1
163$lslen_loop:
164 comib,=,n 0,%r1,$lslen_done
165 addib,<> -1,%r25,$lslen_loop
1662: ldbs,ma 1(%sr1,%r26),%r1
167$lslen_done:
168 bv %r0(%r2)
169 sub %r26,%r24,%r28
170 .exit
171
172$lslen_nzero:
173 b $lslen_done
174 ldo 1(%r26),%r26 /* special case for N == 0 */
175
176 .section .fixup,"ax"
1773: fixup_branch $lslen_done
178 copy %r24,%r26 /* reset r26 so 0 is returned on fault */
179 .previous
180
181 .section __ex_table,"aw"
182#ifdef __LP64__
183 .dword 1b,3b
184 .dword 2b,3b
185#else
186 .word 1b,3b
187 .word 2b,3b
188#endif
189 .previous
190
191 .procend
192
193 .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 @@
1/*
2 * Optimized memory copy routines.
3 *
4 * Copyright (C) 2004 Randolph Chung <tausq@debian.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * Portions derived from the GNU C Library
21 * Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
22 *
23 * Several strategies are tried to try to get the best performance for various
24 * conditions. In the optimal case, we copy 64-bytes in an unrolled loop using
25 * fp regs. This is followed by loops that copy 32- or 16-bytes at a time using
26 * general registers. Unaligned copies are handled either by aligning the
27 * destination and then using shift-and-write method, or in a few cases by
28 * falling back to a byte-at-a-time copy.
29 *
30 * I chose to implement this in C because it is easier to maintain and debug,
31 * and in my experiments it appears that the C code generated by gcc (3.3/3.4
32 * at the time of writing) is fairly optimal. Unfortunately some of the
33 * semantics of the copy routine (exception handling) is difficult to express
34 * in C, so we have to play some tricks to get it to work.
35 *
36 * All the loads and stores are done via explicit asm() code in order to use
37 * the right space registers.
38 *
39 * Testing with various alignments and buffer sizes shows that this code is
40 * often >10x faster than a simple byte-at-a-time copy, even for strangely
41 * aligned operands. It is interesting to note that the glibc version
42 * of memcpy (written in C) is actually quite fast already. This routine is
43 * able to beat it by 30-40% for aligned copies because of the loop unrolling,
44 * but in some cases the glibc version is still slightly faster. This lends
45 * more credibility that gcc can generate very good code as long as we are
46 * careful.
47 *
48 * TODO:
49 * - cache prefetching needs more experimentation to get optimal settings
50 * - try not to use the post-increment address modifiers; they create additional
51 * interlocks
52 * - replace byte-copy loops with stybs sequences
53 */
54
55#ifdef __KERNEL__
56#include <linux/config.h>
57#include <linux/module.h>
58#include <linux/compiler.h>
59#include <asm/uaccess.h>
60#define s_space "%%sr1"
61#define d_space "%%sr2"
62#else
63#include "memcpy.h"
64#define s_space "%%sr0"
65#define d_space "%%sr0"
66#define pa_memcpy new2_copy
67#endif
68
69DECLARE_PER_CPU(struct exception_data, exception_data);
70
71#define preserve_branch(label) do { \
72 volatile int dummy; \
73 /* The following branch is never taken, it's just here to */ \
74 /* prevent gcc from optimizing away our exception code. */ \
75 if (unlikely(dummy != dummy)) \
76 goto label; \
77} while (0)
78
79#define get_user_space() (segment_eq(get_fs(), KERNEL_DS) ? 0 : mfsp(3))
80#define get_kernel_space() (0)
81
82#define MERGE(w0, sh_1, w1, sh_2) ({ \
83 unsigned int _r; \
84 asm volatile ( \
85 "mtsar %3\n" \
86 "shrpw %1, %2, %%sar, %0\n" \
87 : "=r"(_r) \
88 : "r"(w0), "r"(w1), "r"(sh_2) \
89 ); \
90 _r; \
91})
92#define THRESHOLD 16
93
94#ifdef DEBUG_MEMCPY
95#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0)
96#else
97#define DPRINTF(fmt, args...)
98#endif
99
100#ifndef __LP64__
101#define EXC_WORD ".word"
102#else
103#define EXC_WORD ".dword"
104#endif
105
106#define def_load_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e) \
107 __asm__ __volatile__ ( \
108 "1:\t" #_insn ",ma " #_sz "(" _s ",%1), %0\n" \
109 "\t.section __ex_table,\"aw\"\n" \
110 "\t" EXC_WORD "\t1b\n" \
111 "\t" EXC_WORD "\t" #_e "\n" \
112 "\t.previous\n" \
113 : _tt(_t), "+r"(_a) \
114 : \
115 : "r8")
116
117#define def_store_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e) \
118 __asm__ __volatile__ ( \
119 "1:\t" #_insn ",ma %1, " #_sz "(" _s ",%0)\n" \
120 "\t.section __ex_table,\"aw\"\n" \
121 "\t" EXC_WORD "\t1b\n" \
122 "\t" EXC_WORD "\t" #_e "\n" \
123 "\t.previous\n" \
124 : "+r"(_a) \
125 : _tt(_t) \
126 : "r8")
127
128#define ldbma(_s, _a, _t, _e) def_load_ai_insn(ldbs,1,"=r",_s,_a,_t,_e)
129#define stbma(_s, _t, _a, _e) def_store_ai_insn(stbs,1,"r",_s,_a,_t,_e)
130#define ldwma(_s, _a, _t, _e) def_load_ai_insn(ldw,4,"=r",_s,_a,_t,_e)
131#define stwma(_s, _t, _a, _e) def_store_ai_insn(stw,4,"r",_s,_a,_t,_e)
132#define flddma(_s, _a, _t, _e) def_load_ai_insn(fldd,8,"=f",_s,_a,_t,_e)
133#define fstdma(_s, _t, _a, _e) def_store_ai_insn(fstd,8,"f",_s,_a,_t,_e)
134
135#define def_load_insn(_insn,_tt,_s,_o,_a,_t,_e) \
136 __asm__ __volatile__ ( \
137 "1:\t" #_insn " " #_o "(" _s ",%1), %0\n" \
138 "\t.section __ex_table,\"aw\"\n" \
139 "\t" EXC_WORD "\t1b\n" \
140 "\t" EXC_WORD "\t" #_e "\n" \
141 "\t.previous\n" \
142 : _tt(_t) \
143 : "r"(_a) \
144 : "r8")
145
146#define def_store_insn(_insn,_tt,_s,_t,_o,_a,_e) \
147 __asm__ __volatile__ ( \
148 "1:\t" #_insn " %0, " #_o "(" _s ",%1)\n" \
149 "\t.section __ex_table,\"aw\"\n" \
150 "\t" EXC_WORD "\t1b\n" \
151 "\t" EXC_WORD "\t" #_e "\n" \
152 "\t.previous\n" \
153 : \
154 : _tt(_t), "r"(_a) \
155 : "r8")
156
157#define ldw(_s,_o,_a,_t,_e) def_load_insn(ldw,"=r",_s,_o,_a,_t,_e)
158#define stw(_s,_t,_o,_a,_e) def_store_insn(stw,"r",_s,_t,_o,_a,_e)
159
160#ifdef CONFIG_PREFETCH
161extern inline void prefetch_src(const void *addr)
162{
163 __asm__("ldw 0(" s_space ",%0), %%r0" : : "r" (addr));
164}
165
166extern inline void prefetch_dst(const void *addr)
167{
168 __asm__("ldd 0(" d_space ",%0), %%r0" : : "r" (addr));
169}
170#else
171#define prefetch_src(addr)
172#define prefetch_dst(addr)
173#endif
174
175/* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
176 * per loop. This code is derived from glibc.
177 */
178static 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)
179{
180 /* gcc complains that a2 and a3 may be uninitialized, but actually
181 * they cannot be. Initialize a2/a3 to shut gcc up.
182 */
183 register unsigned int a0, a1, a2 = 0, a3 = 0;
184 int sh_1, sh_2;
185 struct exception_data *d;
186
187 /* prefetch_src((const void *)src); */
188
189 /* Calculate how to shift a word read at the memory operation
190 aligned srcp to make it aligned for copy. */
191 sh_1 = 8 * (src % sizeof(unsigned int));
192 sh_2 = 8 * sizeof(unsigned int) - sh_1;
193
194 /* Make src aligned by rounding it down. */
195 src &= -sizeof(unsigned int);
196
197 switch (len % 4)
198 {
199 case 2:
200 /* a1 = ((unsigned int *) src)[0];
201 a2 = ((unsigned int *) src)[1]; */
202 ldw(s_space, 0, src, a1, cda_ldw_exc);
203 ldw(s_space, 4, src, a2, cda_ldw_exc);
204 src -= 1 * sizeof(unsigned int);
205 dst -= 3 * sizeof(unsigned int);
206 len += 2;
207 goto do1;
208 case 3:
209 /* a0 = ((unsigned int *) src)[0];
210 a1 = ((unsigned int *) src)[1]; */
211 ldw(s_space, 0, src, a0, cda_ldw_exc);
212 ldw(s_space, 4, src, a1, cda_ldw_exc);
213 src -= 0 * sizeof(unsigned int);
214 dst -= 2 * sizeof(unsigned int);
215 len += 1;
216 goto do2;
217 case 0:
218 if (len == 0)
219 return 0;
220 /* a3 = ((unsigned int *) src)[0];
221 a0 = ((unsigned int *) src)[1]; */
222 ldw(s_space, 0, src, a3, cda_ldw_exc);
223 ldw(s_space, 4, src, a0, cda_ldw_exc);
224 src -=-1 * sizeof(unsigned int);
225 dst -= 1 * sizeof(unsigned int);
226 len += 0;
227 goto do3;
228 case 1:
229 /* a2 = ((unsigned int *) src)[0];
230 a3 = ((unsigned int *) src)[1]; */
231 ldw(s_space, 0, src, a2, cda_ldw_exc);
232 ldw(s_space, 4, src, a3, cda_ldw_exc);
233 src -=-2 * sizeof(unsigned int);
234 dst -= 0 * sizeof(unsigned int);
235 len -= 1;
236 if (len == 0)
237 goto do0;
238 goto do4; /* No-op. */
239 }
240
241 do
242 {
243 /* prefetch_src((const void *)(src + 4 * sizeof(unsigned int))); */
244do4:
245 /* a0 = ((unsigned int *) src)[0]; */
246 ldw(s_space, 0, src, a0, cda_ldw_exc);
247 /* ((unsigned int *) dst)[0] = MERGE (a2, sh_1, a3, sh_2); */
248 stw(d_space, MERGE (a2, sh_1, a3, sh_2), 0, dst, cda_stw_exc);
249do3:
250 /* a1 = ((unsigned int *) src)[1]; */
251 ldw(s_space, 4, src, a1, cda_ldw_exc);
252 /* ((unsigned int *) dst)[1] = MERGE (a3, sh_1, a0, sh_2); */
253 stw(d_space, MERGE (a3, sh_1, a0, sh_2), 4, dst, cda_stw_exc);
254do2:
255 /* a2 = ((unsigned int *) src)[2]; */
256 ldw(s_space, 8, src, a2, cda_ldw_exc);
257 /* ((unsigned int *) dst)[2] = MERGE (a0, sh_1, a1, sh_2); */
258 stw(d_space, MERGE (a0, sh_1, a1, sh_2), 8, dst, cda_stw_exc);
259do1:
260 /* a3 = ((unsigned int *) src)[3]; */
261 ldw(s_space, 12, src, a3, cda_ldw_exc);
262 /* ((unsigned int *) dst)[3] = MERGE (a1, sh_1, a2, sh_2); */
263 stw(d_space, MERGE (a1, sh_1, a2, sh_2), 12, dst, cda_stw_exc);
264
265 src += 4 * sizeof(unsigned int);
266 dst += 4 * sizeof(unsigned int);
267 len -= 4;
268 }
269 while (len != 0);
270
271do0:
272 /* ((unsigned int *) dst)[0] = MERGE (a2, sh_1, a3, sh_2); */
273 stw(d_space, MERGE (a2, sh_1, a3, sh_2), 0, dst, cda_stw_exc);
274
275 preserve_branch(handle_load_error);
276 preserve_branch(handle_store_error);
277
278 return 0;
279
280handle_load_error:
281 __asm__ __volatile__ ("cda_ldw_exc:\n");
282 d = &__get_cpu_var(exception_data);
283 DPRINTF("cda_ldw_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
284 o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
285 return o_len * 4 - d->fault_addr + o_src;
286
287handle_store_error:
288 __asm__ __volatile__ ("cda_stw_exc:\n");
289 d = &__get_cpu_var(exception_data);
290 DPRINTF("cda_stw_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
291 o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
292 return o_len * 4 - d->fault_addr + o_dst;
293}
294
295
296/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
297unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
298{
299 register unsigned long src, dst, t1, t2, t3;
300 register unsigned char *pcs, *pcd;
301 register unsigned int *pws, *pwd;
302 register double *pds, *pdd;
303 unsigned long ret = 0;
304 unsigned long o_dst, o_src, o_len;
305 struct exception_data *d;
306
307 src = (unsigned long)srcp;
308 dst = (unsigned long)dstp;
309 pcs = (unsigned char *)srcp;
310 pcd = (unsigned char *)dstp;
311
312 o_dst = dst; o_src = src; o_len = len;
313
314 /* prefetch_src((const void *)srcp); */
315
316 if (len < THRESHOLD)
317 goto byte_copy;
318
319 /* Check alignment */
320 t1 = (src ^ dst);
321 if (unlikely(t1 & (sizeof(double)-1)))
322 goto unaligned_copy;
323
324 /* src and dst have same alignment. */
325
326 /* Copy bytes till we are double-aligned. */
327 t2 = src & (sizeof(double) - 1);
328 if (unlikely(t2 != 0)) {
329 t2 = sizeof(double) - t2;
330 while (t2 && len) {
331 /* *pcd++ = *pcs++; */
332 ldbma(s_space, pcs, t3, pmc_load_exc);
333 len--;
334 stbma(d_space, t3, pcd, pmc_store_exc);
335 t2--;
336 }
337 }
338
339 pds = (double *)pcs;
340 pdd = (double *)pcd;
341
342 /* Copy 8 doubles at a time */
343 while (len >= 8*sizeof(double)) {
344 register double r1, r2, r3, r4, r5, r6, r7, r8;
345 /* prefetch_src((char *)pds + L1_CACHE_BYTES); */
346 flddma(s_space, pds, r1, pmc_load_exc);
347 flddma(s_space, pds, r2, pmc_load_exc);
348 flddma(s_space, pds, r3, pmc_load_exc);
349 flddma(s_space, pds, r4, pmc_load_exc);
350 fstdma(d_space, r1, pdd, pmc_store_exc);
351 fstdma(d_space, r2, pdd, pmc_store_exc);
352 fstdma(d_space, r3, pdd, pmc_store_exc);
353 fstdma(d_space, r4, pdd, pmc_store_exc);
354
355#if 0
356 if (L1_CACHE_BYTES <= 32)
357 prefetch_src((char *)pds + L1_CACHE_BYTES);
358#endif
359 flddma(s_space, pds, r5, pmc_load_exc);
360 flddma(s_space, pds, r6, pmc_load_exc);
361 flddma(s_space, pds, r7, pmc_load_exc);
362 flddma(s_space, pds, r8, pmc_load_exc);
363 fstdma(d_space, r5, pdd, pmc_store_exc);
364 fstdma(d_space, r6, pdd, pmc_store_exc);
365 fstdma(d_space, r7, pdd, pmc_store_exc);
366 fstdma(d_space, r8, pdd, pmc_store_exc);
367 len -= 8*sizeof(double);
368 }
369
370 pws = (unsigned int *)pds;
371 pwd = (unsigned int *)pdd;
372
373word_copy:
374 while (len >= 8*sizeof(unsigned int)) {
375 register unsigned int r1,r2,r3,r4,r5,r6,r7,r8;
376 /* prefetch_src((char *)pws + L1_CACHE_BYTES); */
377 ldwma(s_space, pws, r1, pmc_load_exc);
378 ldwma(s_space, pws, r2, pmc_load_exc);
379 ldwma(s_space, pws, r3, pmc_load_exc);
380 ldwma(s_space, pws, r4, pmc_load_exc);
381 stwma(d_space, r1, pwd, pmc_store_exc);
382 stwma(d_space, r2, pwd, pmc_store_exc);
383 stwma(d_space, r3, pwd, pmc_store_exc);
384 stwma(d_space, r4, pwd, pmc_store_exc);
385
386 ldwma(s_space, pws, r5, pmc_load_exc);
387 ldwma(s_space, pws, r6, pmc_load_exc);
388 ldwma(s_space, pws, r7, pmc_load_exc);
389 ldwma(s_space, pws, r8, pmc_load_exc);
390 stwma(d_space, r5, pwd, pmc_store_exc);
391 stwma(d_space, r6, pwd, pmc_store_exc);
392 stwma(d_space, r7, pwd, pmc_store_exc);
393 stwma(d_space, r8, pwd, pmc_store_exc);
394 len -= 8*sizeof(unsigned int);
395 }
396
397 while (len >= 4*sizeof(unsigned int)) {
398 register unsigned int r1,r2,r3,r4;
399 ldwma(s_space, pws, r1, pmc_load_exc);
400 ldwma(s_space, pws, r2, pmc_load_exc);
401 ldwma(s_space, pws, r3, pmc_load_exc);
402 ldwma(s_space, pws, r4, pmc_load_exc);
403 stwma(d_space, r1, pwd, pmc_store_exc);
404 stwma(d_space, r2, pwd, pmc_store_exc);
405 stwma(d_space, r3, pwd, pmc_store_exc);
406 stwma(d_space, r4, pwd, pmc_store_exc);
407 len -= 4*sizeof(unsigned int);
408 }
409
410 pcs = (unsigned char *)pws;
411 pcd = (unsigned char *)pwd;
412
413byte_copy:
414 while (len) {
415 /* *pcd++ = *pcs++; */
416 ldbma(s_space, pcs, t3, pmc_load_exc);
417 stbma(d_space, t3, pcd, pmc_store_exc);
418 len--;
419 }
420
421 return 0;
422
423unaligned_copy:
424 /* possibly we are aligned on a word, but not on a double... */
425 if (likely(t1 & (sizeof(unsigned int)-1)) == 0) {
426 t2 = src & (sizeof(unsigned int) - 1);
427
428 if (unlikely(t2 != 0)) {
429 t2 = sizeof(unsigned int) - t2;
430 while (t2) {
431 /* *pcd++ = *pcs++; */
432 ldbma(s_space, pcs, t3, pmc_load_exc);
433 stbma(d_space, t3, pcd, pmc_store_exc);
434 len--;
435 t2--;
436 }
437 }
438
439 pws = (unsigned int *)pcs;
440 pwd = (unsigned int *)pcd;
441 goto word_copy;
442 }
443
444 /* Align the destination. */
445 if (unlikely((dst & (sizeof(unsigned int) - 1)) != 0)) {
446 t2 = sizeof(unsigned int) - (dst & (sizeof(unsigned int) - 1));
447 while (t2) {
448 /* *pcd++ = *pcs++; */
449 ldbma(s_space, pcs, t3, pmc_load_exc);
450 stbma(d_space, t3, pcd, pmc_store_exc);
451 len--;
452 t2--;
453 }
454 dst = (unsigned long)pcd;
455 src = (unsigned long)pcs;
456 }
457
458 ret = copy_dstaligned(dst, src, len / sizeof(unsigned int),
459 o_dst, o_src, o_len);
460 if (ret)
461 return ret;
462
463 pcs += (len & -sizeof(unsigned int));
464 pcd += (len & -sizeof(unsigned int));
465 len %= sizeof(unsigned int);
466
467 preserve_branch(handle_load_error);
468 preserve_branch(handle_store_error);
469
470 goto byte_copy;
471
472handle_load_error:
473 __asm__ __volatile__ ("pmc_load_exc:\n");
474 d = &__get_cpu_var(exception_data);
475 DPRINTF("pmc_load_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
476 o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
477 return o_len - d->fault_addr + o_src;
478
479handle_store_error:
480 __asm__ __volatile__ ("pmc_store_exc:\n");
481 d = &__get_cpu_var(exception_data);
482 DPRINTF("pmc_store_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
483 o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
484 return o_len - d->fault_addr + o_dst;
485}
486
487#ifdef __KERNEL__
488unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len)
489{
490 mtsp(get_kernel_space(), 1);
491 mtsp(get_user_space(), 2);
492 return pa_memcpy((void __force *)dst, src, len);
493}
494
495unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len)
496{
497 mtsp(get_user_space(), 1);
498 mtsp(get_kernel_space(), 2);
499 return pa_memcpy(dst, (void __force *)src, len);
500}
501
502unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len)
503{
504 mtsp(get_user_space(), 1);
505 mtsp(get_user_space(), 2);
506 return pa_memcpy((void __force *)dst, (void __force *)src, len);
507}
508
509
510void * memcpy(void * dst,const void *src, size_t count)
511{
512 mtsp(get_kernel_space(), 1);
513 mtsp(get_kernel_space(), 2);
514 pa_memcpy(dst, src, count);
515 return dst;
516}
517
518EXPORT_SYMBOL(copy_to_user);
519EXPORT_SYMBOL(copy_from_user);
520EXPORT_SYMBOL(copy_in_user);
521EXPORT_SYMBOL(memcpy);
522#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 @@
1/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19/* Slight modifications for pa-risc linux - Paul Bame <bame@debian.org> */
20
21#include <linux/types.h>
22#include <asm/string.h>
23
24#define OPSIZ (BITS_PER_LONG/8)
25typedef unsigned long op_t;
26
27void *
28memset (void *dstpp, int sc, size_t len)
29{
30 unsigned int c = sc;
31 long int dstp = (long int) dstpp;
32
33 if (len >= 8)
34 {
35 size_t xlen;
36 op_t cccc;
37
38 cccc = (unsigned char) c;
39 cccc |= cccc << 8;
40 cccc |= cccc << 16;
41 if (OPSIZ > 4)
42 /* Do the shift in two steps to avoid warning if long has 32 bits. */
43 cccc |= (cccc << 16) << 16;
44
45 /* There are at least some bytes to set.
46 No need to test for LEN == 0 in this alignment loop. */
47 while (dstp % OPSIZ != 0)
48 {
49 ((unsigned char *) dstp)[0] = c;
50 dstp += 1;
51 len -= 1;
52 }
53
54 /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */
55 xlen = len / (OPSIZ * 8);
56 while (xlen > 0)
57 {
58 ((op_t *) dstp)[0] = cccc;
59 ((op_t *) dstp)[1] = cccc;
60 ((op_t *) dstp)[2] = cccc;
61 ((op_t *) dstp)[3] = cccc;
62 ((op_t *) dstp)[4] = cccc;
63 ((op_t *) dstp)[5] = cccc;
64 ((op_t *) dstp)[6] = cccc;
65 ((op_t *) dstp)[7] = cccc;
66 dstp += 8 * OPSIZ;
67 xlen -= 1;
68 }
69 len %= OPSIZ * 8;
70
71 /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */
72 xlen = len / OPSIZ;
73 while (xlen > 0)
74 {
75 ((op_t *) dstp)[0] = cccc;
76 dstp += OPSIZ;
77 xlen -= 1;
78 }
79 len %= OPSIZ;
80 }
81
82 /* Write the last few bytes. */
83 while (len > 0)
84 {
85 ((unsigned char *) dstp)[0] = c;
86 dstp += 1;
87 len -= 1;
88 }
89
90 return dstpp;
91}
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 @@
1#
2# Makefile for the linux/parisc floating point code
3#
4
5# See arch/parisc/math-emu/README
6CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \
7 -Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \
8 -Wno-implicit-int
9
10obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \
11 dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \
12 sfadd.o dfsub.o sfsub.o fcnvfxt.o fcnvff.o fcnvxf.o \
13 fcnvfx.o fcnvuf.o fcnvfu.o fcnvfut.o dfdiv.o sfdiv.o \
14 dfrem.o sfrem.o dfcmp.o sfcmp.o
15
16# Math emulation code beyond the FRND is required for 712/80i and
17# other very old or stripped-down PA-RISC CPUs -- not currently supported
18
19obj-$(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 @@
1All files except driver.c are snapshots from the HP-UX kernel. They've
2been modified as little as possible. Even though they don't fit the
3Linux coding style, please leave them in their funny format just in case
4someone in the future, with access to HP-UX source code, is generous
5enough to update our copies with later changes from HP-UX -- it'll
6make their 'diff' job easier if our code is relatively unmodified.
7
8Required Disclaimer: Hewlett-Packard makes no implied or expressed
9warranties about this code nor any promises to maintain or test it
10in any way. This copy of this snapshot is no longer the property
11of 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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifdef __NO_PA_HDRS
23 PA header file -- do not include this header file for non-PA builds.
24#endif
25
26/*
27 * Some more constants
28 */
29#define SGL_FX_MAX_EXP 30
30#define DBL_FX_MAX_EXP 62
31#define QUAD_FX_MAX_EXP 126
32
33#define Dintp1(object) (object)
34#define Dintp2(object) (object)
35
36#define Duintp1(object) (object)
37#define Duintp2(object) (object)
38
39#define Qintp0(object) (object)
40#define Qintp1(object) (object)
41#define Qintp2(object) (object)
42#define Qintp3(object) (object)
43
44
45/*
46 * These macros will be used specifically by the convert instructions.
47 *
48 *
49 * Single format macros
50 */
51
52#define Sgl_to_dbl_exponent(src_exponent,dest) \
53 Deposit_dexponent(dest,src_exponent+(DBL_BIAS-SGL_BIAS))
54
55#define Sgl_to_dbl_mantissa(src_mantissa,destA,destB) \
56 Deposit_dmantissap1(destA,src_mantissa>>3); \
57 Dmantissap2(destB) = src_mantissa << 29
58
59#define Sgl_isinexact_to_fix(sgl_value,exponent) \
60 ((exponent < (SGL_P - 1)) ? \
61 (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE)
62
63#define Int_isinexact_to_sgl(int_value) (int_value << 33 - SGL_EXP_LENGTH)
64
65#define Sgl_roundnearest_from_int(int_value,sgl_value) \
66 if (int_value & 1<<(SGL_EXP_LENGTH - 2)) /* round bit */ \
67 if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value)) \
68 Sall(sgl_value)++
69
70#define Dint_isinexact_to_sgl(dint_valueA,dint_valueB) \
71 ((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB))
72
73#define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value) \
74 if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2)) \
75 if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) || \
76 Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
77
78#define Dint_isinexact_to_dbl(dint_value) \
79 (Dintp2(dint_value) << 33 - DBL_EXP_LENGTH)
80
81#define Dbl_roundnearest_from_dint(dint_opndB,dbl_opndA,dbl_opndB) \
82 if (Dintp2(dint_opndB) & 1<<(DBL_EXP_LENGTH - 2)) \
83 if ((Dintp2(dint_opndB) << 34 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \
84 if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
85
86#define Sgl_isone_roundbit(sgl_value,exponent) \
87 ((Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) >> 31)
88
89#define Sgl_isone_stickybit(sgl_value,exponent) \
90 (exponent < (SGL_P - 2) ? \
91 Sall(sgl_value) << (SGL_EXP_LENGTH + 2 + exponent) : FALSE)
92
93
94/*
95 * Double format macros
96 */
97
98#define Dbl_to_sgl_exponent(src_exponent,dest) \
99 dest = src_exponent + (SGL_BIAS - DBL_BIAS)
100
101#define Dbl_to_sgl_mantissa(srcA,srcB,dest,inexact,guard,sticky,odd) \
102 Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \
103 guard = Dbit3p2(srcB); \
104 sticky = Dallp2(srcB)<<4; \
105 inexact = guard | sticky; \
106 odd = Dbit2p2(srcB)
107
108#define Dbl_to_sgl_denormalized(srcA,srcB,exp,dest,inexact,guard,sticky,odd,tiny) \
109 Deposit_dexponent(srcA,1); \
110 tiny = TRUE; \
111 if (exp >= -2) { \
112 if (exp == 0) { \
113 inexact = Dallp2(srcB) << 3; \
114 guard = inexact >> 31; \
115 sticky = inexact << 1; \
116 Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \
117 odd = dest << 31; \
118 if (inexact) { \
119 switch(Rounding_mode()) { \
120 case ROUNDPLUS: \
121 if (Dbl_iszero_sign(srcA)) { \
122 dest++; \
123 if (Sgl_isone_hidden(dest)) \
124 tiny = FALSE; \
125 dest--; \
126 } \
127 break; \
128 case ROUNDMINUS: \
129 if (Dbl_isone_sign(srcA)) { \
130 dest++; \
131 if (Sgl_isone_hidden(dest)) \
132 tiny = FALSE; \
133 dest--; \
134 } \
135 break; \
136 case ROUNDNEAREST: \
137 if (guard && (sticky || odd)) { \
138 dest++; \
139 if (Sgl_isone_hidden(dest)) \
140 tiny = FALSE; \
141 dest--; \
142 } \
143 break; \
144 } \
145 } \
146 /* shift right by one to get correct result */ \
147 guard = odd; \
148 sticky = inexact; \
149 inexact |= guard; \
150 dest >>= 1; \
151 Deposit_dsign(srcA,0); \
152 Shiftdouble(Dallp1(srcA),Dallp2(srcB),30,dest); \
153 odd = dest << 31; \
154 } \
155 else { \
156 inexact = Dallp2(srcB) << (2 + exp); \
157 guard = inexact >> 31; \
158 sticky = inexact << 1; \
159 Deposit_dsign(srcA,0); \
160 if (exp == -2) dest = Dallp1(srcA); \
161 else Variable_shift_double(Dallp1(srcA),Dallp2(srcB),30-exp,dest); \
162 odd = dest << 31; \
163 } \
164 } \
165 else { \
166 Deposit_dsign(srcA,0); \
167 if (exp > (1 - SGL_P)) { \
168 dest = Dallp1(srcA) >> (- 2 - exp); \
169 inexact = Dallp1(srcA) << (34 + exp); \
170 guard = inexact >> 31; \
171 sticky = (inexact << 1) | Dallp2(srcB); \
172 inexact |= Dallp2(srcB); \
173 odd = dest << 31; \
174 } \
175 else { \
176 dest = 0; \
177 inexact = Dallp1(srcA) | Dallp2(srcB); \
178 if (exp == (1 - SGL_P)) { \
179 guard = Dhidden(srcA); \
180 sticky = Dmantissap1(srcA) | Dallp2(srcB); \
181 } \
182 else { \
183 guard = 0; \
184 sticky = inexact; \
185 } \
186 odd = 0; \
187 } \
188 } \
189 exp = 0
190
191#define Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) \
192 (exponent < (DBL_P-33) ? \
193 Dallp2(dbl_valueB) || Dallp1(dbl_valueA) << (DBL_EXP_LENGTH+1+exponent) : \
194 (exponent < (DBL_P-1) ? Dallp2(dbl_valueB) << (exponent + (33-DBL_P)) : \
195 FALSE))
196
197#define Dbl_isoverflow_to_int(exponent,dbl_valueA,dbl_valueB) \
198 ((exponent > SGL_FX_MAX_EXP + 1) || Dsign(dbl_valueA)==0 || \
199 Dmantissap1(dbl_valueA)!=0 || (Dallp2(dbl_valueB)>>21)!=0 )
200
201#define Dbl_isone_roundbit(dbl_valueA,dbl_valueB,exponent) \
202 ((exponent < (DBL_P - 33) ? \
203 Dallp1(dbl_valueA) >> ((30 - DBL_EXP_LENGTH) - exponent) : \
204 Dallp2(dbl_valueB) >> ((DBL_P - 2) - exponent)) & 1)
205
206#define Dbl_isone_stickybit(dbl_valueA,dbl_valueB,exponent) \
207 (exponent < (DBL_P-34) ? \
208 (Dallp2(dbl_valueB) || Dallp1(dbl_valueA)<<(DBL_EXP_LENGTH+2+exponent)) : \
209 (exponent<(DBL_P-2) ? (Dallp2(dbl_valueB) << (exponent + (34-DBL_P))) : \
210 FALSE))
211
212
213/* Int macros */
214
215#define Int_from_sgl_mantissa(sgl_value,exponent) \
216 Sall(sgl_value) = \
217 (unsigned)(Sall(sgl_value) << SGL_EXP_LENGTH)>>(31 - exponent)
218
219#define Int_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent) \
220 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),22,Dallp1(dbl_valueA)); \
221 if (exponent < 31) Dallp1(dbl_valueA) >>= 30 - exponent; \
222 else Dallp1(dbl_valueA) <<= 1
223
224#define Int_negate(int_value) int_value = -int_value
225
226
227/* Dint macros */
228
229#define Dint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \
230 {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \
231 if (exponent <= 31) { \
232 Dintp1(dresultA) = 0; \
233 Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
234 } \
235 else { \
236 Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \
237 Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \
238 }}
239
240
241#define Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
242 {if (exponent < 32) { \
243 Dintp1(destA) = 0; \
244 if (exponent <= 20) \
245 Dintp2(destB) = Dallp1(dbl_valueA) >> 20-exponent; \
246 else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
247 52-exponent,Dintp2(destB)); \
248 } \
249 else { \
250 if (exponent <= 52) { \
251 Dintp1(destA) = Dallp1(dbl_valueA) >> 52-exponent; \
252 if (exponent == 52) Dintp2(destB) = Dallp2(dbl_valueB); \
253 else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
254 52-exponent,Dintp2(destB)); \
255 } \
256 else { \
257 Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
258 84-exponent,Dintp1(destA)); \
259 Dintp2(destB) = Dallp2(dbl_valueB) << exponent-52; \
260 } \
261 }}
262
263#define Dint_setzero(dresultA,dresultB) \
264 Dintp1(dresultA) = 0; \
265 Dintp2(dresultB) = 0
266
267#define Dint_setone_sign(dresultA,dresultB) \
268 Dintp1(dresultA) = ~Dintp1(dresultA); \
269 if ((Dintp2(dresultB) = -Dintp2(dresultB)) == 0) Dintp1(dresultA)++
270
271#define Dint_set_minint(dresultA,dresultB) \
272 Dintp1(dresultA) = (unsigned int)1<<31; \
273 Dintp2(dresultB) = 0
274
275#define Dint_isone_lowp2(dresultB) (Dintp2(dresultB) & 01)
276
277#define Dint_increment(dresultA,dresultB) \
278 if ((++Dintp2(dresultB))==0) Dintp1(dresultA)++
279
280#define Dint_decrement(dresultA,dresultB) \
281 if ((Dintp2(dresultB)--)==0) Dintp1(dresultA)--
282
283#define Dint_negate(dresultA,dresultB) \
284 Dintp1(dresultA) = ~Dintp1(dresultA); \
285 if ((Dintp2(dresultB) = -Dintp2(dresultB))==0) Dintp1(dresultA)++
286
287#define Dint_copyfromptr(src,destA,destB) \
288 Dintp1(destA) = src->wd0; \
289 Dintp2(destB) = src->wd1
290#define Dint_copytoptr(srcA,srcB,dest) \
291 dest->wd0 = Dintp1(srcA); \
292 dest->wd1 = Dintp2(srcB)
293
294
295/* other macros */
296
297#define Find_ms_one_bit(value, position) \
298 { \
299 int var; \
300 for (var=8; var >=1; var >>= 1) { \
301 if (value >> 32 - position) \
302 position -= var; \
303 else position += var; \
304 } \
305 if ((value >> 32 - position) == 0) \
306 position--; \
307 else position -= 2; \
308 }
309
310
311/*
312 * Unsigned int macros
313 */
314#define Duint_copyfromptr(src,destA,destB) \
315 Dint_copyfromptr(src,destA,destB)
316#define Duint_copytoptr(srcA,srcB,dest) \
317 Dint_copytoptr(srcA,srcB,dest)
318
319#define Suint_isinexact_to_sgl(int_value) \
320 (int_value << 32 - SGL_EXP_LENGTH)
321
322#define Sgl_roundnearest_from_suint(suint_value,sgl_value) \
323 if (suint_value & 1<<(SGL_EXP_LENGTH - 1)) /* round bit */ \
324 if ((suint_value << 33 - SGL_EXP_LENGTH) || Slow(sgl_value)) \
325 Sall(sgl_value)++
326
327#define Duint_isinexact_to_sgl(duint_valueA,duint_valueB) \
328 ((Duintp1(duint_valueA) << 32 - SGL_EXP_LENGTH) || Duintp2(duint_valueB))
329
330#define Sgl_roundnearest_from_duint(duint_valueA,duint_valueB,sgl_value) \
331 if (Duintp1(duint_valueA) & 1<<(SGL_EXP_LENGTH - 1)) \
332 if ((Duintp1(duint_valueA) << 33 - SGL_EXP_LENGTH) || \
333 Duintp2(duint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
334
335#define Duint_isinexact_to_dbl(duint_value) \
336 (Duintp2(duint_value) << 32 - DBL_EXP_LENGTH)
337
338#define Dbl_roundnearest_from_duint(duint_opndB,dbl_opndA,dbl_opndB) \
339 if (Duintp2(duint_opndB) & 1<<(DBL_EXP_LENGTH - 1)) \
340 if ((Duintp2(duint_opndB) << 33 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \
341 if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
342
343#define Suint_from_sgl_mantissa(src,exponent,result) \
344 Sall(result) = (unsigned)(Sall(src) << SGL_EXP_LENGTH)>>(31 - exponent)
345
346#define Sgl_isinexact_to_unsigned(sgl_value,exponent) \
347 Sgl_isinexact_to_fix(sgl_value,exponent)
348
349#define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \
350 {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \
351 if (exponent <= 31) { \
352 Dintp1(dresultA) = 0; \
353 Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
354 } \
355 else { \
356 Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \
357 Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \
358 } \
359 Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \
360 }
361
362#define Duint_setzero(dresultA,dresultB) \
363 Dint_setzero(dresultA,dresultB)
364
365#define Duint_increment(dresultA,dresultB) Dint_increment(dresultA,dresultB)
366
367#define Duint_isone_lowp2(dresultB) Dint_isone_lowp2(dresultB)
368
369#define Suint_from_dbl_mantissa(srcA,srcB,exponent,dest) \
370 Shiftdouble(Dallp1(srcA),Dallp2(srcB),21,dest); \
371 dest = (unsigned)dest >> 31 - exponent
372
373#define Dbl_isinexact_to_unsigned(dbl_valueA,dbl_valueB,exponent) \
374 Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent)
375
376#define Duint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
377 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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#ifdef __NO_PA_HDRS
22 PA header file -- do not include this header file for non-PA builds.
23#endif
24
25/* 32-bit word grabing functions */
26#define Dbl_firstword(value) Dallp1(value)
27#define Dbl_secondword(value) Dallp2(value)
28#define Dbl_thirdword(value) dummy_location
29#define Dbl_fourthword(value) dummy_location
30
31#define Dbl_sign(object) Dsign(object)
32#define Dbl_exponent(object) Dexponent(object)
33#define Dbl_signexponent(object) Dsignexponent(object)
34#define Dbl_mantissap1(object) Dmantissap1(object)
35#define Dbl_mantissap2(object) Dmantissap2(object)
36#define Dbl_exponentmantissap1(object) Dexponentmantissap1(object)
37#define Dbl_allp1(object) Dallp1(object)
38#define Dbl_allp2(object) Dallp2(object)
39
40/* dbl_and_signs ands the sign bits of each argument and puts the result
41 * into the first argument. dbl_or_signs ors those same sign bits */
42#define Dbl_and_signs( src1dst, src2) \
43 Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst)
44#define Dbl_or_signs( src1dst, src2) \
45 Dallp1(src1dst) = (Dallp1(src2)&((unsigned int)1<<31)) | Dallp1(src1dst)
46
47/* The hidden bit is always the low bit of the exponent */
48#define Dbl_clear_exponent_set_hidden(srcdst) Deposit_dexponent(srcdst,1)
49#define Dbl_clear_signexponent_set_hidden(srcdst) \
50 Deposit_dsignexponent(srcdst,1)
51#define Dbl_clear_sign(srcdst) Dallp1(srcdst) &= ~((unsigned int)1<<31)
52#define Dbl_clear_signexponent(srcdst) \
53 Dallp1(srcdst) &= Dmantissap1((unsigned int)-1)
54
55/* Exponent field for doubles has already been cleared and may be
56 * included in the shift. Here we need to generate two double width
57 * variable shifts. The insignificant bits can be ignored.
58 * MTSAR f(varamount)
59 * VSHD srcdst.high,srcdst.low => srcdst.low
60 * VSHD 0,srcdst.high => srcdst.high
61 * This is very difficult to model with C expressions since the shift amount
62 * could exceed 32. */
63/* varamount must be less than 64 */
64#define Dbl_rightshift(srcdstA, srcdstB, varamount) \
65 {if((varamount) >= 32) { \
66 Dallp2(srcdstB) = Dallp1(srcdstA) >> (varamount-32); \
67 Dallp1(srcdstA)=0; \
68 } \
69 else if(varamount > 0) { \
70 Variable_shift_double(Dallp1(srcdstA), Dallp2(srcdstB), \
71 (varamount), Dallp2(srcdstB)); \
72 Dallp1(srcdstA) >>= varamount; \
73 } }
74/* varamount must be less than 64 */
75#define Dbl_rightshift_exponentmantissa(srcdstA, srcdstB, varamount) \
76 {if((varamount) >= 32) { \
77 Dallp2(srcdstB) = Dexponentmantissap1(srcdstA) >> (varamount-32); \
78 Dallp1(srcdstA) &= ((unsigned int)1<<31); /* clear expmant field */ \
79 } \
80 else if(varamount > 0) { \
81 Variable_shift_double(Dexponentmantissap1(srcdstA), Dallp2(srcdstB), \
82 (varamount), Dallp2(srcdstB)); \
83 Deposit_dexponentmantissap1(srcdstA, \
84 (Dexponentmantissap1(srcdstA)>>varamount)); \
85 } }
86/* varamount must be less than 64 */
87#define Dbl_leftshift(srcdstA, srcdstB, varamount) \
88 {if((varamount) >= 32) { \
89 Dallp1(srcdstA) = Dallp2(srcdstB) << (varamount-32); \
90 Dallp2(srcdstB)=0; \
91 } \
92 else { \
93 if ((varamount) > 0) { \
94 Dallp1(srcdstA) = (Dallp1(srcdstA) << (varamount)) | \
95 (Dallp2(srcdstB) >> (32-(varamount))); \
96 Dallp2(srcdstB) <<= varamount; \
97 } \
98 } }
99#define Dbl_leftshiftby1_withextent(lefta,leftb,right,resulta,resultb) \
100 Shiftdouble(Dallp1(lefta), Dallp2(leftb), 31, Dallp1(resulta)); \
101 Shiftdouble(Dallp2(leftb), Extall(right), 31, Dallp2(resultb))
102
103#define Dbl_rightshiftby1_withextent(leftb,right,dst) \
104 Extall(dst) = (Dallp2(leftb) << 31) | ((unsigned int)Extall(right) >> 1) | \
105 Extlow(right)
106
107#define Dbl_arithrightshiftby1(srcdstA,srcdstB) \
108 Shiftdouble(Dallp1(srcdstA),Dallp2(srcdstB),1,Dallp2(srcdstB));\
109 Dallp1(srcdstA) = (int)Dallp1(srcdstA) >> 1
110
111/* Sign extend the sign bit with an integer destination */
112#define Dbl_signextendedsign(value) Dsignedsign(value)
113
114#define Dbl_isone_hidden(dbl_value) (Is_dhidden(dbl_value)!=0)
115/* Singles and doubles may include the sign and exponent fields. The
116 * hidden bit and the hidden overflow must be included. */
117#define Dbl_increment(dbl_valueA,dbl_valueB) \
118 if( (Dallp2(dbl_valueB) += 1) == 0 ) Dallp1(dbl_valueA) += 1
119#define Dbl_increment_mantissa(dbl_valueA,dbl_valueB) \
120 if( (Dmantissap2(dbl_valueB) += 1) == 0 ) \
121 Deposit_dmantissap1(dbl_valueA,dbl_valueA+1)
122#define Dbl_decrement(dbl_valueA,dbl_valueB) \
123 if( Dallp2(dbl_valueB) == 0 ) Dallp1(dbl_valueA) -= 1; \
124 Dallp2(dbl_valueB) -= 1
125
126#define Dbl_isone_sign(dbl_value) (Is_dsign(dbl_value)!=0)
127#define Dbl_isone_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)!=0)
128#define Dbl_isone_lowmantissap1(dbl_valueA) (Is_dlowp1(dbl_valueA)!=0)
129#define Dbl_isone_lowmantissap2(dbl_valueB) (Is_dlowp2(dbl_valueB)!=0)
130#define Dbl_isone_signaling(dbl_value) (Is_dsignaling(dbl_value)!=0)
131#define Dbl_is_signalingnan(dbl_value) (Dsignalingnan(dbl_value)==0xfff)
132#define Dbl_isnotzero(dbl_valueA,dbl_valueB) \
133 (Dallp1(dbl_valueA) || Dallp2(dbl_valueB))
134#define Dbl_isnotzero_hiddenhigh7mantissa(dbl_value) \
135 (Dhiddenhigh7mantissa(dbl_value)!=0)
136#define Dbl_isnotzero_exponent(dbl_value) (Dexponent(dbl_value)!=0)
137#define Dbl_isnotzero_mantissa(dbl_valueA,dbl_valueB) \
138 (Dmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB))
139#define Dbl_isnotzero_mantissap1(dbl_valueA) (Dmantissap1(dbl_valueA)!=0)
140#define Dbl_isnotzero_mantissap2(dbl_valueB) (Dmantissap2(dbl_valueB)!=0)
141#define Dbl_isnotzero_exponentmantissa(dbl_valueA,dbl_valueB) \
142 (Dexponentmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB))
143#define Dbl_isnotzero_low4p2(dbl_value) (Dlow4p2(dbl_value)!=0)
144#define Dbl_iszero(dbl_valueA,dbl_valueB) (Dallp1(dbl_valueA)==0 && \
145 Dallp2(dbl_valueB)==0)
146#define Dbl_iszero_allp1(dbl_value) (Dallp1(dbl_value)==0)
147#define Dbl_iszero_allp2(dbl_value) (Dallp2(dbl_value)==0)
148#define Dbl_iszero_hidden(dbl_value) (Is_dhidden(dbl_value)==0)
149#define Dbl_iszero_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)==0)
150#define Dbl_iszero_hiddenhigh3mantissa(dbl_value) \
151 (Dhiddenhigh3mantissa(dbl_value)==0)
152#define Dbl_iszero_hiddenhigh7mantissa(dbl_value) \
153 (Dhiddenhigh7mantissa(dbl_value)==0)
154#define Dbl_iszero_sign(dbl_value) (Is_dsign(dbl_value)==0)
155#define Dbl_iszero_exponent(dbl_value) (Dexponent(dbl_value)==0)
156#define Dbl_iszero_mantissa(dbl_valueA,dbl_valueB) \
157 (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
158#define Dbl_iszero_exponentmantissa(dbl_valueA,dbl_valueB) \
159 (Dexponentmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
160#define Dbl_isinfinity_exponent(dbl_value) \
161 (Dexponent(dbl_value)==DBL_INFINITY_EXPONENT)
162#define Dbl_isnotinfinity_exponent(dbl_value) \
163 (Dexponent(dbl_value)!=DBL_INFINITY_EXPONENT)
164#define Dbl_isinfinity(dbl_valueA,dbl_valueB) \
165 (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \
166 Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
167#define Dbl_isnan(dbl_valueA,dbl_valueB) \
168 (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \
169 (Dmantissap1(dbl_valueA)!=0 || Dmantissap2(dbl_valueB)!=0))
170#define Dbl_isnotnan(dbl_valueA,dbl_valueB) \
171 (Dexponent(dbl_valueA)!=DBL_INFINITY_EXPONENT || \
172 (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0))
173
174#define Dbl_islessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
175 (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \
176 (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
177 Dallp2(dbl_op1b) < Dallp2(dbl_op2b)))
178#define Dbl_isgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
179 (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \
180 (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
181 Dallp2(dbl_op1b) > Dallp2(dbl_op2b)))
182#define Dbl_isnotlessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
183 (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \
184 (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
185 Dallp2(dbl_op1b) >= Dallp2(dbl_op2b)))
186#define Dbl_isnotgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
187 (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \
188 (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
189 Dallp2(dbl_op1b) <= Dallp2(dbl_op2b)))
190#define Dbl_isequal(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
191 ((Dallp1(dbl_op1a) == Dallp1(dbl_op2a)) && \
192 (Dallp2(dbl_op1b) == Dallp2(dbl_op2b)))
193
194#define Dbl_leftshiftby8(dbl_valueA,dbl_valueB) \
195 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),24,Dallp1(dbl_valueA)); \
196 Dallp2(dbl_valueB) <<= 8
197#define Dbl_leftshiftby7(dbl_valueA,dbl_valueB) \
198 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),25,Dallp1(dbl_valueA)); \
199 Dallp2(dbl_valueB) <<= 7
200#define Dbl_leftshiftby4(dbl_valueA,dbl_valueB) \
201 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),28,Dallp1(dbl_valueA)); \
202 Dallp2(dbl_valueB) <<= 4
203#define Dbl_leftshiftby3(dbl_valueA,dbl_valueB) \
204 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),29,Dallp1(dbl_valueA)); \
205 Dallp2(dbl_valueB) <<= 3
206#define Dbl_leftshiftby2(dbl_valueA,dbl_valueB) \
207 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),30,Dallp1(dbl_valueA)); \
208 Dallp2(dbl_valueB) <<= 2
209#define Dbl_leftshiftby1(dbl_valueA,dbl_valueB) \
210 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),31,Dallp1(dbl_valueA)); \
211 Dallp2(dbl_valueB) <<= 1
212
213#define Dbl_rightshiftby8(dbl_valueA,dbl_valueB) \
214 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),8,Dallp2(dbl_valueB)); \
215 Dallp1(dbl_valueA) >>= 8
216#define Dbl_rightshiftby4(dbl_valueA,dbl_valueB) \
217 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),4,Dallp2(dbl_valueB)); \
218 Dallp1(dbl_valueA) >>= 4
219#define Dbl_rightshiftby2(dbl_valueA,dbl_valueB) \
220 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),2,Dallp2(dbl_valueB)); \
221 Dallp1(dbl_valueA) >>= 2
222#define Dbl_rightshiftby1(dbl_valueA,dbl_valueB) \
223 Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),1,Dallp2(dbl_valueB)); \
224 Dallp1(dbl_valueA) >>= 1
225
226/* This magnitude comparison uses the signless first words and
227 * the regular part2 words. The comparison is graphically:
228 *
229 * 1st greater? -------------
230 * |
231 * 1st less?-----------------+---------
232 * | |
233 * 2nd greater or equal----->| |
234 * False True
235 */
236#define Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \
237 ((signlessleft <= signlessright) && \
238 ( (signlessleft < signlessright) || (Dallp2(leftB)<Dallp2(rightB)) ))
239
240#define Dbl_copytoint_exponentmantissap1(src,dest) \
241 dest = Dexponentmantissap1(src)
242
243/* A quiet NaN has the high mantissa bit clear and at least on other (in this
244 * case the adjacent bit) bit set. */
245#define Dbl_set_quiet(dbl_value) Deposit_dhigh2mantissa(dbl_value,1)
246#define Dbl_set_exponent(dbl_value, exp) Deposit_dexponent(dbl_value,exp)
247
248#define Dbl_set_mantissa(desta,destb,valuea,valueb) \
249 Deposit_dmantissap1(desta,valuea); \
250 Dmantissap2(destb) = Dmantissap2(valueb)
251#define Dbl_set_mantissap1(desta,valuea) \
252 Deposit_dmantissap1(desta,valuea)
253#define Dbl_set_mantissap2(destb,valueb) \
254 Dmantissap2(destb) = Dmantissap2(valueb)
255
256#define Dbl_set_exponentmantissa(desta,destb,valuea,valueb) \
257 Deposit_dexponentmantissap1(desta,valuea); \
258 Dmantissap2(destb) = Dmantissap2(valueb)
259#define Dbl_set_exponentmantissap1(dest,value) \
260 Deposit_dexponentmantissap1(dest,value)
261
262#define Dbl_copyfromptr(src,desta,destb) \
263 Dallp1(desta) = src->wd0; \
264 Dallp2(destb) = src->wd1
265#define Dbl_copytoptr(srca,srcb,dest) \
266 dest->wd0 = Dallp1(srca); \
267 dest->wd1 = Dallp2(srcb)
268
269/* An infinity is represented with the max exponent and a zero mantissa */
270#define Dbl_setinfinity_exponent(dbl_value) \
271 Deposit_dexponent(dbl_value,DBL_INFINITY_EXPONENT)
272#define Dbl_setinfinity_exponentmantissa(dbl_valueA,dbl_valueB) \
273 Deposit_dexponentmantissap1(dbl_valueA, \
274 (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)))); \
275 Dmantissap2(dbl_valueB) = 0
276#define Dbl_setinfinitypositive(dbl_valueA,dbl_valueB) \
277 Dallp1(dbl_valueA) \
278 = (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
279 Dmantissap2(dbl_valueB) = 0
280#define Dbl_setinfinitynegative(dbl_valueA,dbl_valueB) \
281 Dallp1(dbl_valueA) = ((unsigned int)1<<31) | \
282 (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
283 Dmantissap2(dbl_valueB) = 0
284#define Dbl_setinfinity(dbl_valueA,dbl_valueB,sign) \
285 Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \
286 (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
287 Dmantissap2(dbl_valueB) = 0
288
289#define Dbl_sethigh4bits(dbl_value, extsign) Deposit_dhigh4p1(dbl_value,extsign)
290#define Dbl_set_sign(dbl_value,sign) Deposit_dsign(dbl_value,sign)
291#define Dbl_invert_sign(dbl_value) Deposit_dsign(dbl_value,~Dsign(dbl_value))
292#define Dbl_setone_sign(dbl_value) Deposit_dsign(dbl_value,1)
293#define Dbl_setone_lowmantissap2(dbl_value) Deposit_dlowp2(dbl_value,1)
294#define Dbl_setzero_sign(dbl_value) Dallp1(dbl_value) &= 0x7fffffff
295#define Dbl_setzero_exponent(dbl_value) \
296 Dallp1(dbl_value) &= 0x800fffff
297#define Dbl_setzero_mantissa(dbl_valueA,dbl_valueB) \
298 Dallp1(dbl_valueA) &= 0xfff00000; \
299 Dallp2(dbl_valueB) = 0
300#define Dbl_setzero_mantissap1(dbl_value) Dallp1(dbl_value) &= 0xfff00000
301#define Dbl_setzero_mantissap2(dbl_value) Dallp2(dbl_value) = 0
302#define Dbl_setzero_exponentmantissa(dbl_valueA,dbl_valueB) \
303 Dallp1(dbl_valueA) &= 0x80000000; \
304 Dallp2(dbl_valueB) = 0
305#define Dbl_setzero_exponentmantissap1(dbl_valueA) \
306 Dallp1(dbl_valueA) &= 0x80000000
307#define Dbl_setzero(dbl_valueA,dbl_valueB) \
308 Dallp1(dbl_valueA) = 0; Dallp2(dbl_valueB) = 0
309#define Dbl_setzerop1(dbl_value) Dallp1(dbl_value) = 0
310#define Dbl_setzerop2(dbl_value) Dallp2(dbl_value) = 0
311#define Dbl_setnegativezero(dbl_value) \
312 Dallp1(dbl_value) = (unsigned int)1 << 31; Dallp2(dbl_value) = 0
313#define Dbl_setnegativezerop1(dbl_value) Dallp1(dbl_value) = (unsigned int)1<<31
314
315/* Use the following macro for both overflow & underflow conditions */
316#define ovfl -
317#define unfl +
318#define Dbl_setwrapped_exponent(dbl_value,exponent,op) \
319 Deposit_dexponent(dbl_value,(exponent op DBL_WRAP))
320
321#define Dbl_setlargestpositive(dbl_valueA,dbl_valueB) \
322 Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
323 | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ); \
324 Dallp2(dbl_valueB) = 0xFFFFFFFF
325#define Dbl_setlargestnegative(dbl_valueA,dbl_valueB) \
326 Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
327 | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ) \
328 | ((unsigned int)1<<31); \
329 Dallp2(dbl_valueB) = 0xFFFFFFFF
330#define Dbl_setlargest_exponentmantissa(dbl_valueA,dbl_valueB) \
331 Deposit_dexponentmantissap1(dbl_valueA, \
332 (((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
333 | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ))); \
334 Dallp2(dbl_valueB) = 0xFFFFFFFF
335
336#define Dbl_setnegativeinfinity(dbl_valueA,dbl_valueB) \
337 Dallp1(dbl_valueA) = ((1<<DBL_EXP_LENGTH) | DBL_INFINITY_EXPONENT) \
338 << (32-(1+DBL_EXP_LENGTH)) ; \
339 Dallp2(dbl_valueB) = 0
340#define Dbl_setlargest(dbl_valueA,dbl_valueB,sign) \
341 Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \
342 ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) | \
343 ((1 << (32-(1+DBL_EXP_LENGTH))) - 1 ); \
344 Dallp2(dbl_valueB) = 0xFFFFFFFF
345
346
347/* The high bit is always zero so arithmetic or logical shifts will work. */
348#define Dbl_right_align(srcdstA,srcdstB,shift,extent) \
349 if( shift >= 32 ) \
350 { \
351 /* Big shift requires examining the portion shift off \
352 the end to properly set inexact. */ \
353 if(shift < 64) \
354 { \
355 if(shift > 32) \
356 { \
357 Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB), \
358 shift-32, Extall(extent)); \
359 if(Dallp2(srcdstB) << 64 - (shift)) Ext_setone_low(extent); \
360 } \
361 else Extall(extent) = Dallp2(srcdstB); \
362 Dallp2(srcdstB) = Dallp1(srcdstA) >> (shift - 32); \
363 } \
364 else \
365 { \
366 Extall(extent) = Dallp1(srcdstA); \
367 if(Dallp2(srcdstB)) Ext_setone_low(extent); \
368 Dallp2(srcdstB) = 0; \
369 } \
370 Dallp1(srcdstA) = 0; \
371 } \
372 else \
373 { \
374 /* Small alignment is simpler. Extension is easily set. */ \
375 if (shift > 0) \
376 { \
377 Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \
378 Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB),shift, \
379 Dallp2(srcdstB)); \
380 Dallp1(srcdstA) >>= shift; \
381 } \
382 else Extall(extent) = 0; \
383 }
384
385/*
386 * Here we need to shift the result right to correct for an overshift
387 * (due to the exponent becoming negative) during normalization.
388 */
389#define Dbl_fix_overshift(srcdstA,srcdstB,shift,extent) \
390 Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \
391 Dallp2(srcdstB) = (Dallp1(srcdstA) << 32 - (shift)) | \
392 (Dallp2(srcdstB) >> (shift)); \
393 Dallp1(srcdstA) = Dallp1(srcdstA) >> shift
394
395#define Dbl_hiddenhigh3mantissa(dbl_value) Dhiddenhigh3mantissa(dbl_value)
396#define Dbl_hidden(dbl_value) Dhidden(dbl_value)
397#define Dbl_lowmantissap2(dbl_value) Dlowp2(dbl_value)
398
399/* The left argument is never smaller than the right argument */
400#define Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb) \
401 if( Dallp2(rightb) > Dallp2(leftb) ) Dallp1(lefta)--; \
402 Dallp2(resultb) = Dallp2(leftb) - Dallp2(rightb); \
403 Dallp1(resulta) = Dallp1(lefta) - Dallp1(righta)
404
405/* Subtract right augmented with extension from left augmented with zeros and
406 * store into result and extension. */
407#define Dbl_subtract_withextension(lefta,leftb,righta,rightb,extent,resulta,resultb) \
408 Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb); \
409 if( (Extall(extent) = 0-Extall(extent)) ) \
410 { \
411 if((Dallp2(resultb)--) == 0) Dallp1(resulta)--; \
412 }
413
414#define Dbl_addition(lefta,leftb,righta,rightb,resulta,resultb) \
415 /* If the sum of the low words is less than either source, then \
416 * an overflow into the next word occurred. */ \
417 Dallp1(resulta) = Dallp1(lefta) + Dallp1(righta); \
418 if((Dallp2(resultb) = Dallp2(leftb) + Dallp2(rightb)) < Dallp2(rightb)) \
419 Dallp1(resulta)++
420
421#define Dbl_xortointp1(left,right,result) \
422 result = Dallp1(left) XOR Dallp1(right)
423
424#define Dbl_xorfromintp1(left,right,result) \
425 Dallp1(result) = left XOR Dallp1(right)
426
427#define Dbl_swap_lower(left,right) \
428 Dallp2(left) = Dallp2(left) XOR Dallp2(right); \
429 Dallp2(right) = Dallp2(left) XOR Dallp2(right); \
430 Dallp2(left) = Dallp2(left) XOR Dallp2(right)
431
432/* Need to Initialize */
433#define Dbl_makequietnan(desta,destb) \
434 Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \
435 | (1<<(32-(1+DBL_EXP_LENGTH+2))); \
436 Dallp2(destb) = 0
437#define Dbl_makesignalingnan(desta,destb) \
438 Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \
439 | (1<<(32-(1+DBL_EXP_LENGTH+1))); \
440 Dallp2(destb) = 0
441
442#define Dbl_normalize(dbl_opndA,dbl_opndB,exponent) \
443 while(Dbl_iszero_hiddenhigh7mantissa(dbl_opndA)) { \
444 Dbl_leftshiftby8(dbl_opndA,dbl_opndB); \
445 exponent -= 8; \
446 } \
447 if(Dbl_iszero_hiddenhigh3mantissa(dbl_opndA)) { \
448 Dbl_leftshiftby4(dbl_opndA,dbl_opndB); \
449 exponent -= 4; \
450 } \
451 while(Dbl_iszero_hidden(dbl_opndA)) { \
452 Dbl_leftshiftby1(dbl_opndA,dbl_opndB); \
453 exponent -= 1; \
454 }
455
456#define Twoword_add(src1dstA,src1dstB,src2A,src2B) \
457 /* \
458 * want this macro to generate: \
459 * ADD src1dstB,src2B,src1dstB; \
460 * ADDC src1dstA,src2A,src1dstA; \
461 */ \
462 if ((src1dstB) + (src2B) < (src1dstB)) Dallp1(src1dstA)++; \
463 Dallp1(src1dstA) += (src2A); \
464 Dallp2(src1dstB) += (src2B)
465
466#define Twoword_subtract(src1dstA,src1dstB,src2A,src2B) \
467 /* \
468 * want this macro to generate: \
469 * SUB src1dstB,src2B,src1dstB; \
470 * SUBB src1dstA,src2A,src1dstA; \
471 */ \
472 if ((src1dstB) < (src2B)) Dallp1(src1dstA)--; \
473 Dallp1(src1dstA) -= (src2A); \
474 Dallp2(src1dstB) -= (src2B)
475
476#define Dbl_setoverflow(resultA,resultB) \
477 /* set result to infinity or largest number */ \
478 switch (Rounding_mode()) { \
479 case ROUNDPLUS: \
480 if (Dbl_isone_sign(resultA)) { \
481 Dbl_setlargestnegative(resultA,resultB); \
482 } \
483 else { \
484 Dbl_setinfinitypositive(resultA,resultB); \
485 } \
486 break; \
487 case ROUNDMINUS: \
488 if (Dbl_iszero_sign(resultA)) { \
489 Dbl_setlargestpositive(resultA,resultB); \
490 } \
491 else { \
492 Dbl_setinfinitynegative(resultA,resultB); \
493 } \
494 break; \
495 case ROUNDNEAREST: \
496 Dbl_setinfinity_exponentmantissa(resultA,resultB); \
497 break; \
498 case ROUNDZERO: \
499 Dbl_setlargest_exponentmantissa(resultA,resultB); \
500 }
501
502#define Dbl_denormalize(opndp1,opndp2,exponent,guard,sticky,inexact) \
503 Dbl_clear_signexponent_set_hidden(opndp1); \
504 if (exponent >= (1-DBL_P)) { \
505 if (exponent >= -31) { \
506 guard = (Dallp2(opndp2) >> -exponent) & 1; \
507 if (exponent < 0) sticky |= Dallp2(opndp2) << (32+exponent); \
508 if (exponent > -31) { \
509 Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \
510 Dallp1(opndp1) >>= 1-exponent; \
511 } \
512 else { \
513 Dallp2(opndp2) = Dallp1(opndp1); \
514 Dbl_setzerop1(opndp1); \
515 } \
516 } \
517 else { \
518 guard = (Dallp1(opndp1) >> -32-exponent) & 1; \
519 if (exponent == -32) sticky |= Dallp2(opndp2); \
520 else sticky |= (Dallp2(opndp2) | Dallp1(opndp1) << 64+exponent); \
521 Dallp2(opndp2) = Dallp1(opndp1) >> -31-exponent; \
522 Dbl_setzerop1(opndp1); \
523 } \
524 inexact = guard | sticky; \
525 } \
526 else { \
527 guard = 0; \
528 sticky |= (Dallp1(opndp1) | Dallp2(opndp2)); \
529 Dbl_setzero(opndp1,opndp2); \
530 inexact = sticky; \
531 }
532
533/*
534 * The fused multiply add instructions requires a double extended format,
535 * with 106 bits of mantissa.
536 */
537#define DBLEXT_THRESHOLD 106
538
539#define Dblext_setzero(valA,valB,valC,valD) \
540 Dextallp1(valA) = 0; Dextallp2(valB) = 0; \
541 Dextallp3(valC) = 0; Dextallp4(valD) = 0
542
543
544#define Dblext_isnotzero_mantissap3(valC) (Dextallp3(valC)!=0)
545#define Dblext_isnotzero_mantissap4(valD) (Dextallp3(valD)!=0)
546#define Dblext_isone_lowp2(val) (Dextlowp2(val)!=0)
547#define Dblext_isone_highp3(val) (Dexthighp3(val)!=0)
548#define Dblext_isnotzero_low31p3(val) (Dextlow31p3(val)!=0)
549#define Dblext_iszero(valA,valB,valC,valD) (Dextallp1(valA)==0 && \
550 Dextallp2(valB)==0 && Dextallp3(valC)==0 && Dextallp4(valD)==0)
551
552#define Dblext_copy(srca,srcb,srcc,srcd,desta,destb,destc,destd) \
553 Dextallp1(desta) = Dextallp4(srca); \
554 Dextallp2(destb) = Dextallp4(srcb); \
555 Dextallp3(destc) = Dextallp4(srcc); \
556 Dextallp4(destd) = Dextallp4(srcd)
557
558#define Dblext_swap_lower(leftp2,leftp3,leftp4,rightp2,rightp3,rightp4) \
559 Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
560 Dextallp2(rightp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
561 Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
562 Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
563 Dextallp3(rightp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
564 Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
565 Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \
566 Dextallp4(rightp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \
567 Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4)
568
569#define Dblext_setone_lowmantissap4(dbl_value) Deposit_dextlowp4(dbl_value,1)
570
571/* The high bit is always zero so arithmetic or logical shifts will work. */
572#define Dblext_right_align(srcdstA,srcdstB,srcdstC,srcdstD,shift) \
573 {int shiftamt, sticky; \
574 shiftamt = shift % 32; \
575 sticky = 0; \
576 switch (shift/32) { \
577 case 0: if (shiftamt > 0) { \
578 sticky = Dextallp4(srcdstD) << 32 - (shiftamt); \
579 Variable_shift_double(Dextallp3(srcdstC), \
580 Dextallp4(srcdstD),shiftamt,Dextallp4(srcdstD)); \
581 Variable_shift_double(Dextallp2(srcdstB), \
582 Dextallp3(srcdstC),shiftamt,Dextallp3(srcdstC)); \
583 Variable_shift_double(Dextallp1(srcdstA), \
584 Dextallp2(srcdstB),shiftamt,Dextallp2(srcdstB)); \
585 Dextallp1(srcdstA) >>= shiftamt; \
586 } \
587 break; \
588 case 1: if (shiftamt > 0) { \
589 sticky = (Dextallp3(srcdstC) << 31 - shiftamt) | \
590 Dextallp4(srcdstD); \
591 Variable_shift_double(Dextallp2(srcdstB), \
592 Dextallp3(srcdstC),shiftamt,Dextallp4(srcdstD)); \
593 Variable_shift_double(Dextallp1(srcdstA), \
594 Dextallp2(srcdstB),shiftamt,Dextallp3(srcdstC)); \
595 } \
596 else { \
597 sticky = Dextallp4(srcdstD); \
598 Dextallp4(srcdstD) = Dextallp3(srcdstC); \
599 Dextallp3(srcdstC) = Dextallp2(srcdstB); \
600 } \
601 Dextallp2(srcdstB) = Dextallp1(srcdstA) >> shiftamt; \
602 Dextallp1(srcdstA) = 0; \
603 break; \
604 case 2: if (shiftamt > 0) { \
605 sticky = (Dextallp2(srcdstB) << 31 - shiftamt) | \
606 Dextallp3(srcdstC) | Dextallp4(srcdstD); \
607 Variable_shift_double(Dextallp1(srcdstA), \
608 Dextallp2(srcdstB),shiftamt,Dextallp4(srcdstD)); \
609 } \
610 else { \
611 sticky = Dextallp3(srcdstC) | Dextallp4(srcdstD); \
612 Dextallp4(srcdstD) = Dextallp2(srcdstB); \
613 } \
614 Dextallp3(srcdstC) = Dextallp1(srcdstA) >> shiftamt; \
615 Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \
616 break; \
617 case 3: if (shiftamt > 0) { \
618 sticky = (Dextallp1(srcdstA) << 31 - shiftamt) | \
619 Dextallp2(srcdstB) | Dextallp3(srcdstC) | \
620 Dextallp4(srcdstD); \
621 } \
622 else { \
623 sticky = Dextallp2(srcdstB) | Dextallp3(srcdstC) | \
624 Dextallp4(srcdstD); \
625 } \
626 Dextallp4(srcdstD) = Dextallp1(srcdstA) >> shiftamt; \
627 Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \
628 Dextallp3(srcdstC) = 0; \
629 break; \
630 } \
631 if (sticky) Dblext_setone_lowmantissap4(srcdstD); \
632 }
633
634/* The left argument is never smaller than the right argument */
635#define Dblext_subtract(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \
636 if( Dextallp4(rightd) > Dextallp4(leftd) ) \
637 if( (Dextallp3(leftc)--) == 0) \
638 if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \
639 Dextallp4(resultd) = Dextallp4(leftd) - Dextallp4(rightd); \
640 if( Dextallp3(rightc) > Dextallp3(leftc) ) \
641 if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \
642 Dextallp3(resultc) = Dextallp3(leftc) - Dextallp3(rightc); \
643 if( Dextallp2(rightb) > Dextallp2(leftb) ) Dextallp1(lefta)--; \
644 Dextallp2(resultb) = Dextallp2(leftb) - Dextallp2(rightb); \
645 Dextallp1(resulta) = Dextallp1(lefta) - Dextallp1(righta)
646
647#define Dblext_addition(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \
648 /* If the sum of the low words is less than either source, then \
649 * an overflow into the next word occurred. */ \
650 if ((Dextallp4(resultd) = Dextallp4(leftd)+Dextallp4(rightd)) < \
651 Dextallp4(rightd)) \
652 if((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)+1) <= \
653 Dextallp3(rightc)) \
654 if((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \
655 <= Dextallp2(rightb)) \
656 Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
657 else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
658 else \
659 if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \
660 Dextallp2(rightb)) \
661 Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
662 else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
663 else \
664 if ((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)) < \
665 Dextallp3(rightc)) \
666 if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \
667 <= Dextallp2(rightb)) \
668 Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
669 else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
670 else \
671 if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \
672 Dextallp2(rightb)) \
673 Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
674 else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)
675
676
677#define Dblext_arithrightshiftby1(srcdstA,srcdstB,srcdstC,srcdstD) \
678 Shiftdouble(Dextallp3(srcdstC),Dextallp4(srcdstD),1,Dextallp4(srcdstD)); \
679 Shiftdouble(Dextallp2(srcdstB),Dextallp3(srcdstC),1,Dextallp3(srcdstC)); \
680 Shiftdouble(Dextallp1(srcdstA),Dextallp2(srcdstB),1,Dextallp2(srcdstB)); \
681 Dextallp1(srcdstA) = (int)Dextallp1(srcdstA) >> 1
682
683#define Dblext_leftshiftby8(valA,valB,valC,valD) \
684 Shiftdouble(Dextallp1(valA),Dextallp2(valB),24,Dextallp1(valA)); \
685 Shiftdouble(Dextallp2(valB),Dextallp3(valC),24,Dextallp2(valB)); \
686 Shiftdouble(Dextallp3(valC),Dextallp4(valD),24,Dextallp3(valC)); \
687 Dextallp4(valD) <<= 8
688#define Dblext_leftshiftby4(valA,valB,valC,valD) \
689 Shiftdouble(Dextallp1(valA),Dextallp2(valB),28,Dextallp1(valA)); \
690 Shiftdouble(Dextallp2(valB),Dextallp3(valC),28,Dextallp2(valB)); \
691 Shiftdouble(Dextallp3(valC),Dextallp4(valD),28,Dextallp3(valC)); \
692 Dextallp4(valD) <<= 4
693#define Dblext_leftshiftby3(valA,valB,valC,valD) \
694 Shiftdouble(Dextallp1(valA),Dextallp2(valB),29,Dextallp1(valA)); \
695 Shiftdouble(Dextallp2(valB),Dextallp3(valC),29,Dextallp2(valB)); \
696 Shiftdouble(Dextallp3(valC),Dextallp4(valD),29,Dextallp3(valC)); \
697 Dextallp4(valD) <<= 3
698#define Dblext_leftshiftby2(valA,valB,valC,valD) \
699 Shiftdouble(Dextallp1(valA),Dextallp2(valB),30,Dextallp1(valA)); \
700 Shiftdouble(Dextallp2(valB),Dextallp3(valC),30,Dextallp2(valB)); \
701 Shiftdouble(Dextallp3(valC),Dextallp4(valD),30,Dextallp3(valC)); \
702 Dextallp4(valD) <<= 2
703#define Dblext_leftshiftby1(valA,valB,valC,valD) \
704 Shiftdouble(Dextallp1(valA),Dextallp2(valB),31,Dextallp1(valA)); \
705 Shiftdouble(Dextallp2(valB),Dextallp3(valC),31,Dextallp2(valB)); \
706 Shiftdouble(Dextallp3(valC),Dextallp4(valD),31,Dextallp3(valC)); \
707 Dextallp4(valD) <<= 1
708
709#define Dblext_rightshiftby4(valueA,valueB,valueC,valueD) \
710 Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),4,Dextallp4(valueD)); \
711 Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),4,Dextallp3(valueC)); \
712 Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),4,Dextallp2(valueB)); \
713 Dextallp1(valueA) >>= 4
714#define Dblext_rightshiftby1(valueA,valueB,valueC,valueD) \
715 Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),1,Dextallp4(valueD)); \
716 Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),1,Dextallp3(valueC)); \
717 Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),1,Dextallp2(valueB)); \
718 Dextallp1(valueA) >>= 1
719
720#define Dblext_xortointp1(left,right,result) Dbl_xortointp1(left,right,result)
721
722#define Dblext_xorfromintp1(left,right,result) \
723 Dbl_xorfromintp1(left,right,result)
724
725#define Dblext_copytoint_exponentmantissap1(src,dest) \
726 Dbl_copytoint_exponentmantissap1(src,dest)
727
728#define Dblext_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \
729 Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright)
730
731#define Dbl_copyto_dblext(src1,src2,dest1,dest2,dest3,dest4) \
732 Dextallp1(dest1) = Dallp1(src1); Dextallp2(dest2) = Dallp2(src2); \
733 Dextallp3(dest3) = 0; Dextallp4(dest4) = 0
734
735#define Dblext_set_sign(dbl_value,sign) Dbl_set_sign(dbl_value,sign)
736#define Dblext_clear_signexponent_set_hidden(srcdst) \
737 Dbl_clear_signexponent_set_hidden(srcdst)
738#define Dblext_clear_signexponent(srcdst) Dbl_clear_signexponent(srcdst)
739#define Dblext_clear_sign(srcdst) Dbl_clear_sign(srcdst)
740#define Dblext_isone_hidden(dbl_value) Dbl_isone_hidden(dbl_value)
741
742/*
743 * The Fourword_add() macro assumes that integers are 4 bytes in size.
744 * It will break if this is not the case.
745 */
746
747#define Fourword_add(src1dstA,src1dstB,src1dstC,src1dstD,src2A,src2B,src2C,src2D) \
748 /* \
749 * want this macro to generate: \
750 * ADD src1dstD,src2D,src1dstD; \
751 * ADDC src1dstC,src2C,src1dstC; \
752 * ADDC src1dstB,src2B,src1dstB; \
753 * ADDC src1dstA,src2A,src1dstA; \
754 */ \
755 if ((unsigned int)(src1dstD += (src2D)) < (unsigned int)(src2D)) { \
756 if ((unsigned int)(src1dstC += (src2C) + 1) <= \
757 (unsigned int)(src2C)) { \
758 if ((unsigned int)(src1dstB += (src2B) + 1) <= \
759 (unsigned int)(src2B)) src1dstA++; \
760 } \
761 else if ((unsigned int)(src1dstB += (src2B)) < \
762 (unsigned int)(src2B)) src1dstA++; \
763 } \
764 else { \
765 if ((unsigned int)(src1dstC += (src2C)) < \
766 (unsigned int)(src2C)) { \
767 if ((unsigned int)(src1dstB += (src2B) + 1) <= \
768 (unsigned int)(src2B)) src1dstA++; \
769 } \
770 else if ((unsigned int)(src1dstB += (src2B)) < \
771 (unsigned int)(src2B)) src1dstA++; \
772 } \
773 src1dstA += (src2A)
774
775#define Dblext_denormalize(opndp1,opndp2,opndp3,opndp4,exponent,is_tiny) \
776 {int shiftamt, sticky; \
777 is_tiny = TRUE; \
778 if (exponent == 0 && (Dextallp3(opndp3) || Dextallp4(opndp4))) { \
779 switch (Rounding_mode()) { \
780 case ROUNDPLUS: \
781 if (Dbl_iszero_sign(opndp1)) { \
782 Dbl_increment(opndp1,opndp2); \
783 if (Dbl_isone_hiddenoverflow(opndp1)) \
784 is_tiny = FALSE; \
785 Dbl_decrement(opndp1,opndp2); \
786 } \
787 break; \
788 case ROUNDMINUS: \
789 if (Dbl_isone_sign(opndp1)) { \
790 Dbl_increment(opndp1,opndp2); \
791 if (Dbl_isone_hiddenoverflow(opndp1)) \
792 is_tiny = FALSE; \
793 Dbl_decrement(opndp1,opndp2); \
794 } \
795 break; \
796 case ROUNDNEAREST: \
797 if (Dblext_isone_highp3(opndp3) && \
798 (Dblext_isone_lowp2(opndp2) || \
799 Dblext_isnotzero_low31p3(opndp3))) { \
800 Dbl_increment(opndp1,opndp2); \
801 if (Dbl_isone_hiddenoverflow(opndp1)) \
802 is_tiny = FALSE; \
803 Dbl_decrement(opndp1,opndp2); \
804 } \
805 break; \
806 } \
807 } \
808 Dblext_clear_signexponent_set_hidden(opndp1); \
809 if (exponent >= (1-QUAD_P)) { \
810 shiftamt = (1-exponent) % 32; \
811 switch((1-exponent)/32) { \
812 case 0: sticky = Dextallp4(opndp4) << 32-(shiftamt); \
813 Variableshiftdouble(opndp3,opndp4,shiftamt,opndp4); \
814 Variableshiftdouble(opndp2,opndp3,shiftamt,opndp3); \
815 Variableshiftdouble(opndp1,opndp2,shiftamt,opndp2); \
816 Dextallp1(opndp1) >>= shiftamt; \
817 break; \
818 case 1: sticky = (Dextallp3(opndp3) << 32-(shiftamt)) | \
819 Dextallp4(opndp4); \
820 Variableshiftdouble(opndp2,opndp3,shiftamt,opndp4); \
821 Variableshiftdouble(opndp1,opndp2,shiftamt,opndp3); \
822 Dextallp2(opndp2) = Dextallp1(opndp1) >> shiftamt; \
823 Dextallp1(opndp1) = 0; \
824 break; \
825 case 2: sticky = (Dextallp2(opndp2) << 32-(shiftamt)) | \
826 Dextallp3(opndp3) | Dextallp4(opndp4); \
827 Variableshiftdouble(opndp1,opndp2,shiftamt,opndp4); \
828 Dextallp3(opndp3) = Dextallp1(opndp1) >> shiftamt; \
829 Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \
830 break; \
831 case 3: sticky = (Dextallp1(opndp1) << 32-(shiftamt)) | \
832 Dextallp2(opndp2) | Dextallp3(opndp3) | \
833 Dextallp4(opndp4); \
834 Dextallp4(opndp4) = Dextallp1(opndp1) >> shiftamt; \
835 Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \
836 Dextallp3(opndp3) = 0; \
837 break; \
838 } \
839 } \
840 else { \
841 sticky = Dextallp1(opndp1) | Dextallp2(opndp2) | \
842 Dextallp3(opndp3) | Dextallp4(opndp4); \
843 Dblext_setzero(opndp1,opndp2,opndp3,opndp4); \
844 } \
845 if (sticky) Dblext_setone_lowmantissap4(opndp4); \
846 exponent = 0; \
847 }
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/fp/decode_exc.c $ Revision: $
26 *
27 * Purpose:
28 * <<please update with a synopsis of the functionality provided by this file>>
29 *
30 * External Interfaces:
31 * <<the following list was autogenerated, please review>>
32 * decode_fpu(Fpu_register, trap_counts)
33 *
34 * Internal Interfaces:
35 * <<please update>>
36 *
37 * Theory:
38 * <<please update with a overview of the operation of this file>>
39 *
40 * END_DESC
41*/
42
43
44#include "float.h"
45#include "sgl_float.h"
46#include "dbl_float.h"
47#include "cnv_float.h"
48/* #include "types.h" */
49#include <asm/signal.h>
50#include <asm/siginfo.h>
51/* #include <machine/sys/mdep_private.h> */
52
53#undef Fpustatus_register
54#define Fpustatus_register Fpu_register[0]
55
56/* General definitions */
57#define DOESTRAP 1
58#define NOTRAP 0
59#define SIGNALCODE(signal, code) ((signal) << 24 | (code));
60#define copropbit 1<<31-2 /* bit position 2 */
61#define opclass 9 /* bits 21 & 22 */
62#define fmt 11 /* bits 19 & 20 */
63#define df 13 /* bits 17 & 18 */
64#define twobits 3 /* mask low-order 2 bits */
65#define fivebits 31 /* mask low-order 5 bits */
66#define MAX_EXCP_REG 7 /* number of excpeption registers to check */
67
68/* Exception register definitions */
69#define Excp_type(index) Exceptiontype(Fpu_register[index])
70#define Excp_instr(index) Instructionfield(Fpu_register[index])
71#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
72#define Excp_format() \
73 (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)
74
75/* Miscellaneous definitions */
76#define Fpu_sgl(index) Fpu_register[index*2]
77
78#define Fpu_dblp1(index) Fpu_register[index*2]
79#define Fpu_dblp2(index) Fpu_register[(index*2)+1]
80
81#define Fpu_quadp1(index) Fpu_register[index*2]
82#define Fpu_quadp2(index) Fpu_register[(index*2)+1]
83#define Fpu_quadp3(index) Fpu_register[(index*2)+2]
84#define Fpu_quadp4(index) Fpu_register[(index*2)+3]
85
86/* Single precision floating-point definitions */
87#ifndef Sgl_decrement
88# define Sgl_decrement(sgl_value) Sall(sgl_value)--
89#endif
90
91/* Double precision floating-point definitions */
92#ifndef Dbl_decrement
93# define Dbl_decrement(dbl_valuep1,dbl_valuep2) \
94 if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)--
95#endif
96
97
98#define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) { \
99 aflags=(Fpu_register[0])>>27; /* assumes zero fill. 32 bit */ \
100 Fpu_register[0] |= bflags; \
101}
102
103u_int
104decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[])
105{
106 unsigned int current_ir, excp;
107 int target, exception_index = 1;
108 boolean inexact;
109 unsigned int aflags;
110 unsigned int bflags;
111 unsigned int excptype;
112
113
114 /* Keep stats on how many floating point exceptions (based on type)
115 * that happen. Want to keep this overhead low, but still provide
116 * some information to the customer. All exits from this routine
117 * need to restore Fpu_register[0]
118 */
119
120 bflags=(Fpu_register[0] & 0xf8000000);
121 Fpu_register[0] &= 0x07ffffff;
122
123 /* exception_index is used to index the exception register queue. It
124 * always points at the last register that contains a valid exception. A
125 * zero value implies no exceptions (also the initialized value). Setting
126 * the T-bit resets the exception_index to zero.
127 */
128
129 /*
130 * Check for reserved-op exception. A reserved-op exception does not
131 * set any exception registers nor does it set the T-bit. If the T-bit
132 * is not set then a reserved-op exception occurred.
133 *
134 * At some point, we may want to report reserved op exceptions as
135 * illegal instructions.
136 */
137
138 if (!Is_tbit_set()) {
139 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
140 return SIGNALCODE(SIGILL, ILL_COPROC);
141 }
142
143 /*
144 * Is a coprocessor op.
145 *
146 * Now we need to determine what type of exception occurred.
147 */
148 for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {
149 current_ir = Excp_instr(exception_index);
150 /*
151 * On PA89: there are 5 different unimplemented exception
152 * codes: 0x1, 0x9, 0xb, 0x3, and 0x23. PA-RISC 2.0 adds
153 * another, 0x2b. Only these have the low order bit set.
154 */
155 excptype = Excp_type(exception_index);
156 if (excptype & UNIMPLEMENTEDEXCEPTION) {
157 /*
158 * Clear T-bit and exception register so that
159 * we can tell if a trap really occurs while
160 * emulating the instruction.
161 */
162 Clear_tbit();
163 Clear_excp_register(exception_index);
164 /*
165 * Now emulate this instruction. If a trap occurs,
166 * fpudispatch will return a non-zero number
167 */
168 excp = fpudispatch(current_ir,excptype,0,Fpu_register);
169 /* accumulate the status flags, don't lose them as in hpux */
170 if (excp) {
171 /*
172 * We now need to make sure that the T-bit and the
173 * exception register contain the correct values
174 * before continuing.
175 */
176 /*
177 * Set t-bit since it might still be needed for a
178 * subsequent real trap (I don't understand fully -PB)
179 */
180 Set_tbit();
181 /* some of the following code uses
182 * Excp_type(exception_index) so fix that up */
183 Set_exceptiontype_and_instr_field(excp,current_ir,
184 Fpu_register[exception_index]);
185 if (excp == UNIMPLEMENTEDEXCEPTION) {
186 /*
187 * it is really unimplemented, so restore the
188 * TIMEX extended unimplemented exception code
189 */
190 excp = excptype;
191 update_trap_counts(Fpu_register, aflags, bflags,
192 trap_counts);
193 return SIGNALCODE(SIGILL, ILL_COPROC);
194 }
195 /* some of the following code uses excptype, so
196 * fix that up too */
197 excptype = excp;
198 }
199 /* handle exceptions other than the real UNIMPLIMENTED the
200 * same way as if the hardware had caused them */
201 if (excp == NOEXCEPTION)
202 /* For now use 'break', should technically be 'continue' */
203 break;
204 }
205
206 /*
207 * In PA89, the underflow exception has been extended to encode
208 * additional information. The exception looks like pp01x0,
209 * where x is 1 if inexact and pp represent the inexact bit (I)
210 * and the round away bit (RA)
211 */
212 if (excptype & UNDERFLOWEXCEPTION) {
213 /* check for underflow trap enabled */
214 if (Is_underflowtrap_enabled()) {
215 update_trap_counts(Fpu_register, aflags, bflags,
216 trap_counts);
217 return SIGNALCODE(SIGFPE, FPE_FLTUND);
218 } else {
219 /*
220 * Isn't a real trap; we need to
221 * return the default value.
222 */
223 target = current_ir & fivebits;
224#ifndef lint
225 if (Ibit(Fpu_register[exception_index])) inexact = TRUE;
226 else inexact = FALSE;
227#endif
228 switch (Excp_format()) {
229 case SGL:
230 /*
231 * If ra (round-away) is set, will
232 * want to undo the rounding done
233 * by the hardware.
234 */
235 if (Rabit(Fpu_register[exception_index]))
236 Sgl_decrement(Fpu_sgl(target));
237
238 /* now denormalize */
239 sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());
240 break;
241 case DBL:
242 /*
243 * If ra (round-away) is set, will
244 * want to undo the rounding done
245 * by the hardware.
246 */
247 if (Rabit(Fpu_register[exception_index]))
248 Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));
249
250 /* now denormalize */
251 dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),
252 &inexact,Rounding_mode());
253 break;
254 }
255 if (inexact) Set_underflowflag();
256 /*
257 * Underflow can generate an inexact
258 * exception. If inexact trap is enabled,
259 * want to do an inexact trap, otherwise
260 * set inexact flag.
261 */
262 if (inexact && Is_inexacttrap_enabled()) {
263 /*
264 * Set exception field of exception register
265 * to inexact, parm field to zero.
266 * Underflow bit should be cleared.
267 */
268 Set_exceptiontype(Fpu_register[exception_index],
269 INEXACTEXCEPTION);
270 Set_parmfield(Fpu_register[exception_index],0);
271 update_trap_counts(Fpu_register, aflags, bflags,
272 trap_counts);
273 return SIGNALCODE(SIGFPE, FPE_FLTRES);
274 }
275 else {
276 /*
277 * Exception register needs to be cleared.
278 * Inexact flag needs to be set if inexact.
279 */
280 Clear_excp_register(exception_index);
281 if (inexact) Set_inexactflag();
282 }
283 }
284 continue;
285 }
286 switch(Excp_type(exception_index)) {
287 case OVERFLOWEXCEPTION:
288 case OVERFLOWEXCEPTION | INEXACTEXCEPTION:
289 /* check for overflow trap enabled */
290 update_trap_counts(Fpu_register, aflags, bflags,
291 trap_counts);
292 if (Is_overflowtrap_enabled()) {
293 update_trap_counts(Fpu_register, aflags, bflags,
294 trap_counts);
295 return SIGNALCODE(SIGFPE, FPE_FLTOVF);
296 } else {
297 /*
298 * Isn't a real trap; we need to
299 * return the default value.
300 */
301 target = current_ir & fivebits;
302 switch (Excp_format()) {
303 case SGL:
304 Sgl_setoverflow(Fpu_sgl(target));
305 break;
306 case DBL:
307 Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));
308 break;
309 }
310 Set_overflowflag();
311 /*
312 * Overflow always generates an inexact
313 * exception. If inexact trap is enabled,
314 * want to do an inexact trap, otherwise
315 * set inexact flag.
316 */
317 if (Is_inexacttrap_enabled()) {
318 /*
319 * Set exception field of exception
320 * register to inexact. Overflow
321 * bit should be cleared.
322 */
323 Set_exceptiontype(Fpu_register[exception_index],
324 INEXACTEXCEPTION);
325 update_trap_counts(Fpu_register, aflags, bflags,
326 trap_counts);
327 return SIGNALCODE(SIGFPE, FPE_FLTRES);
328 }
329 else {
330 /*
331 * Exception register needs to be cleared.
332 * Inexact flag needs to be set.
333 */
334 Clear_excp_register(exception_index);
335 Set_inexactflag();
336 }
337 }
338 break;
339 case INVALIDEXCEPTION:
340 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
341 return SIGNALCODE(SIGFPE, FPE_FLTINV);
342 case DIVISIONBYZEROEXCEPTION:
343 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
344 return SIGNALCODE(SIGFPE, FPE_FLTDIV);
345 case INEXACTEXCEPTION:
346 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
347 return SIGNALCODE(SIGFPE, FPE_FLTRES);
348 default:
349 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
350 printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__,
351 __LINE__, Excp_type(exception_index));
352 return SIGNALCODE(SIGILL, ILL_COPROC);
353 case NOEXCEPTION: /* no exception */
354 /*
355 * Clear exception register in case
356 * other fields are non-zero.
357 */
358 Clear_excp_register(exception_index);
359 break;
360 }
361 }
362 /*
363 * No real exceptions occurred.
364 */
365 Clear_tbit();
366 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
367 return(NOTRAP);
368}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/fp/denormal.c $ Revision: $
26 *
27 * Purpose:
28 * <<please update with a synopsis of the functionality provided by this file>>
29 *
30 * External Interfaces:
31 * <<the following list was autogenerated, please review>>
32 * dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
33 * sgl_denormalize(sgl_opnd,inexactflag,rmode)
34 *
35 * Internal Interfaces:
36 * <<please update>>
37 *
38 * Theory:
39 * <<please update with a overview of the operation of this file>>
40 *
41 * END_DESC
42*/
43
44
45
46#include "float.h"
47#include "sgl_float.h"
48#include "dbl_float.h"
49#include "hppa.h"
50#include <linux/kernel.h>
51/* #include <machine/sys/mdep_private.h> */
52
53#undef Fpustatus_register
54#define Fpustatus_register Fpu_register[0]
55
56void
57sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
58{
59 unsigned int opnd;
60 int sign, exponent;
61 boolean guardbit = FALSE, stickybit, inexact;
62
63 opnd = *sgl_opnd;
64 stickybit = *inexactflag;
65 exponent = Sgl_exponent(opnd) - SGL_WRAP;
66 sign = Sgl_sign(opnd);
67 Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
68 if (inexact) {
69 switch (rmode) {
70 case ROUNDPLUS:
71 if (sign == 0) {
72 Sgl_increment(opnd);
73 }
74 break;
75 case ROUNDMINUS:
76 if (sign != 0) {
77 Sgl_increment(opnd);
78 }
79 break;
80 case ROUNDNEAREST:
81 if (guardbit && (stickybit ||
82 Sgl_isone_lowmantissa(opnd))) {
83 Sgl_increment(opnd);
84 }
85 break;
86 }
87 }
88 Sgl_set_sign(opnd,sign);
89 *sgl_opnd = opnd;
90 *inexactflag = inexact;
91 return;
92}
93
94void
95dbl_denormalize(unsigned int *dbl_opndp1,
96 unsigned int * dbl_opndp2,
97 boolean *inexactflag,
98 int rmode)
99{
100 unsigned int opndp1, opndp2;
101 int sign, exponent;
102 boolean guardbit = FALSE, stickybit, inexact;
103
104 opndp1 = *dbl_opndp1;
105 opndp2 = *dbl_opndp2;
106 stickybit = *inexactflag;
107 exponent = Dbl_exponent(opndp1) - DBL_WRAP;
108 sign = Dbl_sign(opndp1);
109 Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
110 if (inexact) {
111 switch (rmode) {
112 case ROUNDPLUS:
113 if (sign == 0) {
114 Dbl_increment(opndp1,opndp2);
115 }
116 break;
117 case ROUNDMINUS:
118 if (sign != 0) {
119 Dbl_increment(opndp1,opndp2);
120 }
121 break;
122 case ROUNDNEAREST:
123 if (guardbit && (stickybit ||
124 Dbl_isone_lowmantissap2(opndp2))) {
125 Dbl_increment(opndp1,opndp2);
126 }
127 break;
128 }
129 }
130 Dbl_set_sign(opndp1,sign);
131 *dbl_opndp1 = opndp1;
132 *dbl_opndp2 = opndp2;
133 *inexactflag = inexact;
134 return;
135}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/dfadd.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Double_add: add two double precision values.
29 *
30 * External Interfaces:
31 * dbl_fadd(leftptr, rightptr, dstptr, status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "dbl_float.h"
44
45/*
46 * Double_add: add two double precision values.
47 */
48dbl_fadd(
49 dbl_floating_point *leftptr,
50 dbl_floating_point *rightptr,
51 dbl_floating_point *dstptr,
52 unsigned int *status)
53{
54 register unsigned int signless_upper_left, signless_upper_right, save;
55 register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
56 register unsigned int resultp1 = 0, resultp2 = 0;
57
58 register int result_exponent, right_exponent, diff_exponent;
59 register int sign_save, jumpsize;
60 register boolean inexact = FALSE;
61 register boolean underflowtrap;
62
63 /* Create local copies of the numbers */
64 Dbl_copyfromptr(leftptr,leftp1,leftp2);
65 Dbl_copyfromptr(rightptr,rightp1,rightp2);
66
67 /* A zero "save" helps discover equal operands (for later), *
68 * and is used in swapping operands (if needed). */
69 Dbl_xortointp1(leftp1,rightp1,/*to*/save);
70
71 /*
72 * check first operand for NaN's or infinity
73 */
74 if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
75 {
76 if (Dbl_iszero_mantissa(leftp1,leftp2))
77 {
78 if (Dbl_isnotnan(rightp1,rightp2))
79 {
80 if (Dbl_isinfinity(rightp1,rightp2) && save!=0)
81 {
82 /*
83 * invalid since operands are opposite signed infinity's
84 */
85 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
86 Set_invalidflag();
87 Dbl_makequietnan(resultp1,resultp2);
88 Dbl_copytoptr(resultp1,resultp2,dstptr);
89 return(NOEXCEPTION);
90 }
91 /*
92 * return infinity
93 */
94 Dbl_copytoptr(leftp1,leftp2,dstptr);
95 return(NOEXCEPTION);
96 }
97 }
98 else
99 {
100 /*
101 * is NaN; signaling or quiet?
102 */
103 if (Dbl_isone_signaling(leftp1))
104 {
105 /* trap if INVALIDTRAP enabled */
106 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
107 /* make NaN quiet */
108 Set_invalidflag();
109 Dbl_set_quiet(leftp1);
110 }
111 /*
112 * is second operand a signaling NaN?
113 */
114 else if (Dbl_is_signalingnan(rightp1))
115 {
116 /* trap if INVALIDTRAP enabled */
117 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
118 /* make NaN quiet */
119 Set_invalidflag();
120 Dbl_set_quiet(rightp1);
121 Dbl_copytoptr(rightp1,rightp2,dstptr);
122 return(NOEXCEPTION);
123 }
124 /*
125 * return quiet NaN
126 */
127 Dbl_copytoptr(leftp1,leftp2,dstptr);
128 return(NOEXCEPTION);
129 }
130 } /* End left NaN or Infinity processing */
131 /*
132 * check second operand for NaN's or infinity
133 */
134 if (Dbl_isinfinity_exponent(rightp1))
135 {
136 if (Dbl_iszero_mantissa(rightp1,rightp2))
137 {
138 /* return infinity */
139 Dbl_copytoptr(rightp1,rightp2,dstptr);
140 return(NOEXCEPTION);
141 }
142 /*
143 * is NaN; signaling or quiet?
144 */
145 if (Dbl_isone_signaling(rightp1))
146 {
147 /* trap if INVALIDTRAP enabled */
148 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
149 /* make NaN quiet */
150 Set_invalidflag();
151 Dbl_set_quiet(rightp1);
152 }
153 /*
154 * return quiet NaN
155 */
156 Dbl_copytoptr(rightp1,rightp2,dstptr);
157 return(NOEXCEPTION);
158 } /* End right NaN or Infinity processing */
159
160 /* Invariant: Must be dealing with finite numbers */
161
162 /* Compare operands by removing the sign */
163 Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
164 Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
165
166 /* sign difference selects add or sub operation. */
167 if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
168 {
169 /* Set the left operand to the larger one by XOR swap *
170 * First finish the first word using "save" */
171 Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
172 Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
173 Dbl_swap_lower(leftp2,rightp2);
174 result_exponent = Dbl_exponent(leftp1);
175 }
176 /* Invariant: left is not smaller than right. */
177
178 if((right_exponent = Dbl_exponent(rightp1)) == 0)
179 {
180 /* Denormalized operands. First look for zeroes */
181 if(Dbl_iszero_mantissa(rightp1,rightp2))
182 {
183 /* right is zero */
184 if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
185 {
186 /* Both operands are zeros */
187 if(Is_rounding_mode(ROUNDMINUS))
188 {
189 Dbl_or_signs(leftp1,/*with*/rightp1);
190 }
191 else
192 {
193 Dbl_and_signs(leftp1,/*with*/rightp1);
194 }
195 }
196 else
197 {
198 /* Left is not a zero and must be the result. Trapped
199 * underflows are signaled if left is denormalized. Result
200 * is always exact. */
201 if( (result_exponent == 0) && Is_underflowtrap_enabled() )
202 {
203 /* need to normalize results mantissa */
204 sign_save = Dbl_signextendedsign(leftp1);
205 Dbl_leftshiftby1(leftp1,leftp2);
206 Dbl_normalize(leftp1,leftp2,result_exponent);
207 Dbl_set_sign(leftp1,/*using*/sign_save);
208 Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
209 Dbl_copytoptr(leftp1,leftp2,dstptr);
210 /* inexact = FALSE */
211 return(UNDERFLOWEXCEPTION);
212 }
213 }
214 Dbl_copytoptr(leftp1,leftp2,dstptr);
215 return(NOEXCEPTION);
216 }
217
218 /* Neither are zeroes */
219 Dbl_clear_sign(rightp1); /* Exponent is already cleared */
220 if(result_exponent == 0 )
221 {
222 /* Both operands are denormalized. The result must be exact
223 * and is simply calculated. A sum could become normalized and a
224 * difference could cancel to a true zero. */
225 if( (/*signed*/int) save < 0 )
226 {
227 Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
228 /*into*/resultp1,resultp2);
229 if(Dbl_iszero_mantissa(resultp1,resultp2))
230 {
231 if(Is_rounding_mode(ROUNDMINUS))
232 {
233 Dbl_setone_sign(resultp1);
234 }
235 else
236 {
237 Dbl_setzero_sign(resultp1);
238 }
239 Dbl_copytoptr(resultp1,resultp2,dstptr);
240 return(NOEXCEPTION);
241 }
242 }
243 else
244 {
245 Dbl_addition(leftp1,leftp2,rightp1,rightp2,
246 /*into*/resultp1,resultp2);
247 if(Dbl_isone_hidden(resultp1))
248 {
249 Dbl_copytoptr(resultp1,resultp2,dstptr);
250 return(NOEXCEPTION);
251 }
252 }
253 if(Is_underflowtrap_enabled())
254 {
255 /* need to normalize result */
256 sign_save = Dbl_signextendedsign(resultp1);
257 Dbl_leftshiftby1(resultp1,resultp2);
258 Dbl_normalize(resultp1,resultp2,result_exponent);
259 Dbl_set_sign(resultp1,/*using*/sign_save);
260 Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
261 Dbl_copytoptr(resultp1,resultp2,dstptr);
262 /* inexact = FALSE */
263 return(UNDERFLOWEXCEPTION);
264 }
265 Dbl_copytoptr(resultp1,resultp2,dstptr);
266 return(NOEXCEPTION);
267 }
268 right_exponent = 1; /* Set exponent to reflect different bias
269 * with denomalized numbers. */
270 }
271 else
272 {
273 Dbl_clear_signexponent_set_hidden(rightp1);
274 }
275 Dbl_clear_exponent_set_hidden(leftp1);
276 diff_exponent = result_exponent - right_exponent;
277
278 /*
279 * Special case alignment of operands that would force alignment
280 * beyond the extent of the extension. A further optimization
281 * could special case this but only reduces the path length for this
282 * infrequent case.
283 */
284 if(diff_exponent > DBL_THRESHOLD)
285 {
286 diff_exponent = DBL_THRESHOLD;
287 }
288
289 /* Align right operand by shifting to right */
290 Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
291 /*and lower to*/extent);
292
293 /* Treat sum and difference of the operands separately. */
294 if( (/*signed*/int) save < 0 )
295 {
296 /*
297 * Difference of the two operands. Their can be no overflow. A
298 * borrow can occur out of the hidden bit and force a post
299 * normalization phase.
300 */
301 Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
302 /*with*/extent,/*into*/resultp1,resultp2);
303 if(Dbl_iszero_hidden(resultp1))
304 {
305 /* Handle normalization */
306 /* A straight foward algorithm would now shift the result
307 * and extension left until the hidden bit becomes one. Not
308 * all of the extension bits need participate in the shift.
309 * Only the two most significant bits (round and guard) are
310 * needed. If only a single shift is needed then the guard
311 * bit becomes a significant low order bit and the extension
312 * must participate in the rounding. If more than a single
313 * shift is needed, then all bits to the right of the guard
314 * bit are zeros, and the guard bit may or may not be zero. */
315 sign_save = Dbl_signextendedsign(resultp1);
316 Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
317
318 /* Need to check for a zero result. The sign and exponent
319 * fields have already been zeroed. The more efficient test
320 * of the full object can be used.
321 */
322 if(Dbl_iszero(resultp1,resultp2))
323 /* Must have been "x-x" or "x+(-x)". */
324 {
325 if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
326 Dbl_copytoptr(resultp1,resultp2,dstptr);
327 return(NOEXCEPTION);
328 }
329 result_exponent--;
330 /* Look to see if normalization is finished. */
331 if(Dbl_isone_hidden(resultp1))
332 {
333 if(result_exponent==0)
334 {
335 /* Denormalized, exponent should be zero. Left operand *
336 * was normalized, so extent (guard, round) was zero */
337 goto underflow;
338 }
339 else
340 {
341 /* No further normalization is needed. */
342 Dbl_set_sign(resultp1,/*using*/sign_save);
343 Ext_leftshiftby1(extent);
344 goto round;
345 }
346 }
347
348 /* Check for denormalized, exponent should be zero. Left *
349 * operand was normalized, so extent (guard, round) was zero */
350 if(!(underflowtrap = Is_underflowtrap_enabled()) &&
351 result_exponent==0) goto underflow;
352
353 /* Shift extension to complete one bit of normalization and
354 * update exponent. */
355 Ext_leftshiftby1(extent);
356
357 /* Discover first one bit to determine shift amount. Use a
358 * modified binary search. We have already shifted the result
359 * one position right and still not found a one so the remainder
360 * of the extension must be zero and simplifies rounding. */
361 /* Scan bytes */
362 while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
363 {
364 Dbl_leftshiftby8(resultp1,resultp2);
365 if((result_exponent -= 8) <= 0 && !underflowtrap)
366 goto underflow;
367 }
368 /* Now narrow it down to the nibble */
369 if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
370 {
371 /* The lower nibble contains the normalizing one */
372 Dbl_leftshiftby4(resultp1,resultp2);
373 if((result_exponent -= 4) <= 0 && !underflowtrap)
374 goto underflow;
375 }
376 /* Select case were first bit is set (already normalized)
377 * otherwise select the proper shift. */
378 if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
379 {
380 /* Already normalized */
381 if(result_exponent <= 0) goto underflow;
382 Dbl_set_sign(resultp1,/*using*/sign_save);
383 Dbl_set_exponent(resultp1,/*using*/result_exponent);
384 Dbl_copytoptr(resultp1,resultp2,dstptr);
385 return(NOEXCEPTION);
386 }
387 Dbl_sethigh4bits(resultp1,/*using*/sign_save);
388 switch(jumpsize)
389 {
390 case 1:
391 {
392 Dbl_leftshiftby3(resultp1,resultp2);
393 result_exponent -= 3;
394 break;
395 }
396 case 2:
397 case 3:
398 {
399 Dbl_leftshiftby2(resultp1,resultp2);
400 result_exponent -= 2;
401 break;
402 }
403 case 4:
404 case 5:
405 case 6:
406 case 7:
407 {
408 Dbl_leftshiftby1(resultp1,resultp2);
409 result_exponent -= 1;
410 break;
411 }
412 }
413 if(result_exponent > 0)
414 {
415 Dbl_set_exponent(resultp1,/*using*/result_exponent);
416 Dbl_copytoptr(resultp1,resultp2,dstptr);
417 return(NOEXCEPTION); /* Sign bit is already set */
418 }
419 /* Fixup potential underflows */
420 underflow:
421 if(Is_underflowtrap_enabled())
422 {
423 Dbl_set_sign(resultp1,sign_save);
424 Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
425 Dbl_copytoptr(resultp1,resultp2,dstptr);
426 /* inexact = FALSE */
427 return(UNDERFLOWEXCEPTION);
428 }
429 /*
430 * Since we cannot get an inexact denormalized result,
431 * we can now return.
432 */
433 Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
434 Dbl_clear_signexponent(resultp1);
435 Dbl_set_sign(resultp1,sign_save);
436 Dbl_copytoptr(resultp1,resultp2,dstptr);
437 return(NOEXCEPTION);
438 } /* end if(hidden...)... */
439 /* Fall through and round */
440 } /* end if(save < 0)... */
441 else
442 {
443 /* Add magnitudes */
444 Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
445 if(Dbl_isone_hiddenoverflow(resultp1))
446 {
447 /* Prenormalization required. */
448 Dbl_rightshiftby1_withextent(resultp2,extent,extent);
449 Dbl_arithrightshiftby1(resultp1,resultp2);
450 result_exponent++;
451 } /* end if hiddenoverflow... */
452 } /* end else ...add magnitudes... */
453
454 /* Round the result. If the extension is all zeros,then the result is
455 * exact. Otherwise round in the correct direction. No underflow is
456 * possible. If a postnormalization is necessary, then the mantissa is
457 * all zeros so no shift is needed. */
458 round:
459 if(Ext_isnotzero(extent))
460 {
461 inexact = TRUE;
462 switch(Rounding_mode())
463 {
464 case ROUNDNEAREST: /* The default. */
465 if(Ext_isone_sign(extent))
466 {
467 /* at least 1/2 ulp */
468 if(Ext_isnotzero_lower(extent) ||
469 Dbl_isone_lowmantissap2(resultp2))
470 {
471 /* either exactly half way and odd or more than 1/2ulp */
472 Dbl_increment(resultp1,resultp2);
473 }
474 }
475 break;
476
477 case ROUNDPLUS:
478 if(Dbl_iszero_sign(resultp1))
479 {
480 /* Round up positive results */
481 Dbl_increment(resultp1,resultp2);
482 }
483 break;
484
485 case ROUNDMINUS:
486 if(Dbl_isone_sign(resultp1))
487 {
488 /* Round down negative results */
489 Dbl_increment(resultp1,resultp2);
490 }
491
492 case ROUNDZERO:;
493 /* truncate is simple */
494 } /* end switch... */
495 if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
496 }
497 if(result_exponent == DBL_INFINITY_EXPONENT)
498 {
499 /* Overflow */
500 if(Is_overflowtrap_enabled())
501 {
502 Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
503 Dbl_copytoptr(resultp1,resultp2,dstptr);
504 if (inexact)
505 if (Is_inexacttrap_enabled())
506 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
507 else Set_inexactflag();
508 return(OVERFLOWEXCEPTION);
509 }
510 else
511 {
512 inexact = TRUE;
513 Set_overflowflag();
514 Dbl_setoverflow(resultp1,resultp2);
515 }
516 }
517 else Dbl_set_exponent(resultp1,result_exponent);
518 Dbl_copytoptr(resultp1,resultp2,dstptr);
519 if(inexact)
520 if(Is_inexacttrap_enabled())
521 return(INEXACTEXCEPTION);
522 else Set_inexactflag();
523 return(NOEXCEPTION);
524}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/dfcmp.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * dbl_cmp: compare two values
29 *
30 * External Interfaces:
31 * dbl_fcmp(leftptr, rightptr, cond, status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42
43#include "float.h"
44#include "dbl_float.h"
45
46/*
47 * dbl_cmp: compare two values
48 */
49int
50dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr,
51 unsigned int cond, unsigned int *status)
52
53 /* The predicate to be tested */
54
55 {
56 register unsigned int leftp1, leftp2, rightp1, rightp2;
57 register int xorresult;
58
59 /* Create local copies of the numbers */
60 Dbl_copyfromptr(leftptr,leftp1,leftp2);
61 Dbl_copyfromptr(rightptr,rightp1,rightp2);
62 /*
63 * Test for NaN
64 */
65 if( (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
66 || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) )
67 {
68 /* Check if a NaN is involved. Signal an invalid exception when
69 * comparing a signaling NaN or when comparing quiet NaNs and the
70 * low bit of the condition is set */
71 if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
72 && Dbl_isnotzero_mantissa(leftp1,leftp2)
73 && (Exception(cond) || Dbl_isone_signaling(leftp1)))
74 ||
75 ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
76 && Dbl_isnotzero_mantissa(rightp1,rightp2)
77 && (Exception(cond) || Dbl_isone_signaling(rightp1))) )
78 {
79 if( Is_invalidtrap_enabled() ) {
80 Set_status_cbit(Unordered(cond));
81 return(INVALIDEXCEPTION);
82 }
83 else Set_invalidflag();
84 Set_status_cbit(Unordered(cond));
85 return(NOEXCEPTION);
86 }
87 /* All the exceptional conditions are handled, now special case
88 NaN compares */
89 else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
90 && Dbl_isnotzero_mantissa(leftp1,leftp2))
91 ||
92 ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
93 && Dbl_isnotzero_mantissa(rightp1,rightp2)) )
94 {
95 /* NaNs always compare unordered. */
96 Set_status_cbit(Unordered(cond));
97 return(NOEXCEPTION);
98 }
99 /* infinities will drop down to the normal compare mechanisms */
100 }
101 /* First compare for unequal signs => less or greater or
102 * special equal case */
103 Dbl_xortointp1(leftp1,rightp1,xorresult);
104 if( xorresult < 0 )
105 {
106 /* left negative => less, left positive => greater.
107 * equal is possible if both operands are zeros. */
108 if( Dbl_iszero_exponentmantissa(leftp1,leftp2)
109 && Dbl_iszero_exponentmantissa(rightp1,rightp2) )
110 {
111 Set_status_cbit(Equal(cond));
112 }
113 else if( Dbl_isone_sign(leftp1) )
114 {
115 Set_status_cbit(Lessthan(cond));
116 }
117 else
118 {
119 Set_status_cbit(Greaterthan(cond));
120 }
121 }
122 /* Signs are the same. Treat negative numbers separately
123 * from the positives because of the reversed sense. */
124 else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2))
125 {
126 Set_status_cbit(Equal(cond));
127 }
128 else if( Dbl_iszero_sign(leftp1) )
129 {
130 /* Positive compare */
131 if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
132 {
133 Set_status_cbit(Lessthan(cond));
134 }
135 else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
136 {
137 Set_status_cbit(Greaterthan(cond));
138 }
139 else
140 {
141 /* Equal first parts. Now we must use unsigned compares to
142 * resolve the two possibilities. */
143 if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) )
144 {
145 Set_status_cbit(Lessthan(cond));
146 }
147 else
148 {
149 Set_status_cbit(Greaterthan(cond));
150 }
151 }
152 }
153 else
154 {
155 /* Negative compare. Signed or unsigned compares
156 * both work the same. That distinction is only
157 * important when the sign bits differ. */
158 if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
159 {
160 Set_status_cbit(Lessthan(cond));
161 }
162 else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
163 {
164 Set_status_cbit(Greaterthan(cond));
165 }
166 else
167 {
168 /* Equal first parts. Now we must use unsigned compares to
169 * resolve the two possibilities. */
170 if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) )
171 {
172 Set_status_cbit(Lessthan(cond));
173 }
174 else
175 {
176 Set_status_cbit(Greaterthan(cond));
177 }
178 }
179 }
180 return(NOEXCEPTION);
181 }
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/dfdiv.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Double Precision Floating-point Divide
29 *
30 * External Interfaces:
31 * dbl_fdiv(srcptr1,srcptr2,dstptr,status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "dbl_float.h"
44
45/*
46 * Double Precision Floating-point Divide
47 */
48
49int
50dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
51 dbl_floating_point * dstptr, unsigned int *status)
52{
53 register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
54 register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
55 register int dest_exponent, count;
56 register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
57 boolean is_tiny;
58
59 Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
60 Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
61 /*
62 * set sign bit of result
63 */
64 if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
65 Dbl_setnegativezerop1(resultp1);
66 else Dbl_setzerop1(resultp1);
67 /*
68 * check first operand for NaN's or infinity
69 */
70 if (Dbl_isinfinity_exponent(opnd1p1)) {
71 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
72 if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
73 if (Dbl_isinfinity(opnd2p1,opnd2p2)) {
74 /*
75 * invalid since both operands
76 * are infinity
77 */
78 if (Is_invalidtrap_enabled())
79 return(INVALIDEXCEPTION);
80 Set_invalidflag();
81 Dbl_makequietnan(resultp1,resultp2);
82 Dbl_copytoptr(resultp1,resultp2,dstptr);
83 return(NOEXCEPTION);
84 }
85 /*
86 * return infinity
87 */
88 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
89 Dbl_copytoptr(resultp1,resultp2,dstptr);
90 return(NOEXCEPTION);
91 }
92 }
93 else {
94 /*
95 * is NaN; signaling or quiet?
96 */
97 if (Dbl_isone_signaling(opnd1p1)) {
98 /* trap if INVALIDTRAP enabled */
99 if (Is_invalidtrap_enabled())
100 return(INVALIDEXCEPTION);
101 /* make NaN quiet */
102 Set_invalidflag();
103 Dbl_set_quiet(opnd1p1);
104 }
105 /*
106 * is second operand a signaling NaN?
107 */
108 else if (Dbl_is_signalingnan(opnd2p1)) {
109 /* trap if INVALIDTRAP enabled */
110 if (Is_invalidtrap_enabled())
111 return(INVALIDEXCEPTION);
112 /* make NaN quiet */
113 Set_invalidflag();
114 Dbl_set_quiet(opnd2p1);
115 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
116 return(NOEXCEPTION);
117 }
118 /*
119 * return quiet NaN
120 */
121 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
122 return(NOEXCEPTION);
123 }
124 }
125 /*
126 * check second operand for NaN's or infinity
127 */
128 if (Dbl_isinfinity_exponent(opnd2p1)) {
129 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
130 /*
131 * return zero
132 */
133 Dbl_setzero_exponentmantissa(resultp1,resultp2);
134 Dbl_copytoptr(resultp1,resultp2,dstptr);
135 return(NOEXCEPTION);
136 }
137 /*
138 * is NaN; signaling or quiet?
139 */
140 if (Dbl_isone_signaling(opnd2p1)) {
141 /* trap if INVALIDTRAP enabled */
142 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
143 /* make NaN quiet */
144 Set_invalidflag();
145 Dbl_set_quiet(opnd2p1);
146 }
147 /*
148 * return quiet NaN
149 */
150 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
151 return(NOEXCEPTION);
152 }
153 /*
154 * check for division by zero
155 */
156 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
157 if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
158 /* invalid since both operands are zero */
159 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
160 Set_invalidflag();
161 Dbl_makequietnan(resultp1,resultp2);
162 Dbl_copytoptr(resultp1,resultp2,dstptr);
163 return(NOEXCEPTION);
164 }
165 if (Is_divisionbyzerotrap_enabled())
166 return(DIVISIONBYZEROEXCEPTION);
167 Set_divisionbyzeroflag();
168 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
169 Dbl_copytoptr(resultp1,resultp2,dstptr);
170 return(NOEXCEPTION);
171 }
172 /*
173 * Generate exponent
174 */
175 dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS;
176
177 /*
178 * Generate mantissa
179 */
180 if (Dbl_isnotzero_exponent(opnd1p1)) {
181 /* set hidden bit */
182 Dbl_clear_signexponent_set_hidden(opnd1p1);
183 }
184 else {
185 /* check for zero */
186 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
187 Dbl_setzero_exponentmantissa(resultp1,resultp2);
188 Dbl_copytoptr(resultp1,resultp2,dstptr);
189 return(NOEXCEPTION);
190 }
191 /* is denormalized, want to normalize */
192 Dbl_clear_signexponent(opnd1p1);
193 Dbl_leftshiftby1(opnd1p1,opnd1p2);
194 Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
195 }
196 /* opnd2 needs to have hidden bit set with msb in hidden bit */
197 if (Dbl_isnotzero_exponent(opnd2p1)) {
198 Dbl_clear_signexponent_set_hidden(opnd2p1);
199 }
200 else {
201 /* is denormalized; want to normalize */
202 Dbl_clear_signexponent(opnd2p1);
203 Dbl_leftshiftby1(opnd2p1,opnd2p2);
204 while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) {
205 dest_exponent+=8;
206 Dbl_leftshiftby8(opnd2p1,opnd2p2);
207 }
208 if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) {
209 dest_exponent+=4;
210 Dbl_leftshiftby4(opnd2p1,opnd2p2);
211 }
212 while (Dbl_iszero_hidden(opnd2p1)) {
213 dest_exponent++;
214 Dbl_leftshiftby1(opnd2p1,opnd2p2);
215 }
216 }
217
218 /* Divide the source mantissas */
219
220 /*
221 * A non-restoring divide algorithm is used.
222 */
223 Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
224 Dbl_setzero(opnd3p1,opnd3p2);
225 for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) {
226 Dbl_leftshiftby1(opnd1p1,opnd1p2);
227 Dbl_leftshiftby1(opnd3p1,opnd3p2);
228 if (Dbl_iszero_sign(opnd1p1)) {
229 Dbl_setone_lowmantissap2(opnd3p2);
230 Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
231 }
232 else {
233 Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2);
234 }
235 }
236 if (count <= DBL_P) {
237 Dbl_leftshiftby1(opnd3p1,opnd3p2);
238 Dbl_setone_lowmantissap2(opnd3p2);
239 Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count));
240 if (Dbl_iszero_hidden(opnd3p1)) {
241 Dbl_leftshiftby1(opnd3p1,opnd3p2);
242 dest_exponent--;
243 }
244 }
245 else {
246 if (Dbl_iszero_hidden(opnd3p1)) {
247 /* need to get one more bit of result */
248 Dbl_leftshiftby1(opnd1p1,opnd1p2);
249 Dbl_leftshiftby1(opnd3p1,opnd3p2);
250 if (Dbl_iszero_sign(opnd1p1)) {
251 Dbl_setone_lowmantissap2(opnd3p2);
252 Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
253 }
254 else {
255 Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
256 }
257 dest_exponent--;
258 }
259 if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE;
260 stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2);
261 }
262 inexact = guardbit | stickybit;
263
264 /*
265 * round result
266 */
267 if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
268 Dbl_clear_signexponent(opnd3p1);
269 switch (Rounding_mode()) {
270 case ROUNDPLUS:
271 if (Dbl_iszero_sign(resultp1))
272 Dbl_increment(opnd3p1,opnd3p2);
273 break;
274 case ROUNDMINUS:
275 if (Dbl_isone_sign(resultp1))
276 Dbl_increment(opnd3p1,opnd3p2);
277 break;
278 case ROUNDNEAREST:
279 if (guardbit && (stickybit ||
280 Dbl_isone_lowmantissap2(opnd3p2))) {
281 Dbl_increment(opnd3p1,opnd3p2);
282 }
283 }
284 if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
285 }
286 Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
287
288 /*
289 * Test for overflow
290 */
291 if (dest_exponent >= DBL_INFINITY_EXPONENT) {
292 /* trap if OVERFLOWTRAP enabled */
293 if (Is_overflowtrap_enabled()) {
294 /*
295 * Adjust bias of result
296 */
297 Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
298 Dbl_copytoptr(resultp1,resultp2,dstptr);
299 if (inexact)
300 if (Is_inexacttrap_enabled())
301 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
302 else Set_inexactflag();
303 return(OVERFLOWEXCEPTION);
304 }
305 Set_overflowflag();
306 /* set result to infinity or largest number */
307 Dbl_setoverflow(resultp1,resultp2);
308 inexact = TRUE;
309 }
310 /*
311 * Test for underflow
312 */
313 else if (dest_exponent <= 0) {
314 /* trap if UNDERFLOWTRAP enabled */
315 if (Is_underflowtrap_enabled()) {
316 /*
317 * Adjust bias of result
318 */
319 Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
320 Dbl_copytoptr(resultp1,resultp2,dstptr);
321 if (inexact)
322 if (Is_inexacttrap_enabled())
323 return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
324 else Set_inexactflag();
325 return(UNDERFLOWEXCEPTION);
326 }
327
328 /* Determine if should set underflow flag */
329 is_tiny = TRUE;
330 if (dest_exponent == 0 && inexact) {
331 switch (Rounding_mode()) {
332 case ROUNDPLUS:
333 if (Dbl_iszero_sign(resultp1)) {
334 Dbl_increment(opnd3p1,opnd3p2);
335 if (Dbl_isone_hiddenoverflow(opnd3p1))
336 is_tiny = FALSE;
337 Dbl_decrement(opnd3p1,opnd3p2);
338 }
339 break;
340 case ROUNDMINUS:
341 if (Dbl_isone_sign(resultp1)) {
342 Dbl_increment(opnd3p1,opnd3p2);
343 if (Dbl_isone_hiddenoverflow(opnd3p1))
344 is_tiny = FALSE;
345 Dbl_decrement(opnd3p1,opnd3p2);
346 }
347 break;
348 case ROUNDNEAREST:
349 if (guardbit && (stickybit ||
350 Dbl_isone_lowmantissap2(opnd3p2))) {
351 Dbl_increment(opnd3p1,opnd3p2);
352 if (Dbl_isone_hiddenoverflow(opnd3p1))
353 is_tiny = FALSE;
354 Dbl_decrement(opnd3p1,opnd3p2);
355 }
356 break;
357 }
358 }
359
360 /*
361 * denormalize result or set to signed zero
362 */
363 stickybit = inexact;
364 Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
365 stickybit,inexact);
366
367 /* return rounded number */
368 if (inexact) {
369 switch (Rounding_mode()) {
370 case ROUNDPLUS:
371 if (Dbl_iszero_sign(resultp1)) {
372 Dbl_increment(opnd3p1,opnd3p2);
373 }
374 break;
375 case ROUNDMINUS:
376 if (Dbl_isone_sign(resultp1)) {
377 Dbl_increment(opnd3p1,opnd3p2);
378 }
379 break;
380 case ROUNDNEAREST:
381 if (guardbit && (stickybit ||
382 Dbl_isone_lowmantissap2(opnd3p2))) {
383 Dbl_increment(opnd3p1,opnd3p2);
384 }
385 break;
386 }
387 if (is_tiny) Set_underflowflag();
388 }
389 Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
390 }
391 else Dbl_set_exponent(resultp1,dest_exponent);
392 Dbl_copytoptr(resultp1,resultp2,dstptr);
393
394 /* check for inexact */
395 if (inexact) {
396 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
397 else Set_inexactflag();
398 }
399 return(NOEXCEPTION);
400}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/dfmpy.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Double Precision Floating-point Multiply
29 *
30 * External Interfaces:
31 * dbl_fmpy(srcptr1,srcptr2,dstptr,status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "dbl_float.h"
44
45/*
46 * Double Precision Floating-point Multiply
47 */
48
49int
50dbl_fmpy(
51 dbl_floating_point *srcptr1,
52 dbl_floating_point *srcptr2,
53 dbl_floating_point *dstptr,
54 unsigned int *status)
55{
56 register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
57 register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
58 register int dest_exponent, count;
59 register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
60 boolean is_tiny;
61
62 Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
63 Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
64
65 /*
66 * set sign bit of result
67 */
68 if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
69 Dbl_setnegativezerop1(resultp1);
70 else Dbl_setzerop1(resultp1);
71 /*
72 * check first operand for NaN's or infinity
73 */
74 if (Dbl_isinfinity_exponent(opnd1p1)) {
75 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
76 if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
77 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
78 /*
79 * invalid since operands are infinity
80 * and zero
81 */
82 if (Is_invalidtrap_enabled())
83 return(INVALIDEXCEPTION);
84 Set_invalidflag();
85 Dbl_makequietnan(resultp1,resultp2);
86 Dbl_copytoptr(resultp1,resultp2,dstptr);
87 return(NOEXCEPTION);
88 }
89 /*
90 * return infinity
91 */
92 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
93 Dbl_copytoptr(resultp1,resultp2,dstptr);
94 return(NOEXCEPTION);
95 }
96 }
97 else {
98 /*
99 * is NaN; signaling or quiet?
100 */
101 if (Dbl_isone_signaling(opnd1p1)) {
102 /* trap if INVALIDTRAP enabled */
103 if (Is_invalidtrap_enabled())
104 return(INVALIDEXCEPTION);
105 /* make NaN quiet */
106 Set_invalidflag();
107 Dbl_set_quiet(opnd1p1);
108 }
109 /*
110 * is second operand a signaling NaN?
111 */
112 else if (Dbl_is_signalingnan(opnd2p1)) {
113 /* trap if INVALIDTRAP enabled */
114 if (Is_invalidtrap_enabled())
115 return(INVALIDEXCEPTION);
116 /* make NaN quiet */
117 Set_invalidflag();
118 Dbl_set_quiet(opnd2p1);
119 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
120 return(NOEXCEPTION);
121 }
122 /*
123 * return quiet NaN
124 */
125 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
126 return(NOEXCEPTION);
127 }
128 }
129 /*
130 * check second operand for NaN's or infinity
131 */
132 if (Dbl_isinfinity_exponent(opnd2p1)) {
133 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
134 if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
135 /* invalid since operands are zero & infinity */
136 if (Is_invalidtrap_enabled())
137 return(INVALIDEXCEPTION);
138 Set_invalidflag();
139 Dbl_makequietnan(opnd2p1,opnd2p2);
140 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
141 return(NOEXCEPTION);
142 }
143 /*
144 * return infinity
145 */
146 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
147 Dbl_copytoptr(resultp1,resultp2,dstptr);
148 return(NOEXCEPTION);
149 }
150 /*
151 * is NaN; signaling or quiet?
152 */
153 if (Dbl_isone_signaling(opnd2p1)) {
154 /* trap if INVALIDTRAP enabled */
155 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
156 /* make NaN quiet */
157 Set_invalidflag();
158 Dbl_set_quiet(opnd2p1);
159 }
160 /*
161 * return quiet NaN
162 */
163 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
164 return(NOEXCEPTION);
165 }
166 /*
167 * Generate exponent
168 */
169 dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS;
170
171 /*
172 * Generate mantissa
173 */
174 if (Dbl_isnotzero_exponent(opnd1p1)) {
175 /* set hidden bit */
176 Dbl_clear_signexponent_set_hidden(opnd1p1);
177 }
178 else {
179 /* check for zero */
180 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
181 Dbl_setzero_exponentmantissa(resultp1,resultp2);
182 Dbl_copytoptr(resultp1,resultp2,dstptr);
183 return(NOEXCEPTION);
184 }
185 /* is denormalized, adjust exponent */
186 Dbl_clear_signexponent(opnd1p1);
187 Dbl_leftshiftby1(opnd1p1,opnd1p2);
188 Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
189 }
190 /* opnd2 needs to have hidden bit set with msb in hidden bit */
191 if (Dbl_isnotzero_exponent(opnd2p1)) {
192 Dbl_clear_signexponent_set_hidden(opnd2p1);
193 }
194 else {
195 /* check for zero */
196 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
197 Dbl_setzero_exponentmantissa(resultp1,resultp2);
198 Dbl_copytoptr(resultp1,resultp2,dstptr);
199 return(NOEXCEPTION);
200 }
201 /* is denormalized; want to normalize */
202 Dbl_clear_signexponent(opnd2p1);
203 Dbl_leftshiftby1(opnd2p1,opnd2p2);
204 Dbl_normalize(opnd2p1,opnd2p2,dest_exponent);
205 }
206
207 /* Multiply two source mantissas together */
208
209 /* make room for guard bits */
210 Dbl_leftshiftby7(opnd2p1,opnd2p2);
211 Dbl_setzero(opnd3p1,opnd3p2);
212 /*
213 * Four bits at a time are inspected in each loop, and a
214 * simple shift and add multiply algorithm is used.
215 */
216 for (count=1;count<=DBL_P;count+=4) {
217 stickybit |= Dlow4p2(opnd3p2);
218 Dbl_rightshiftby4(opnd3p1,opnd3p2);
219 if (Dbit28p2(opnd1p2)) {
220 /* Twoword_add should be an ADDC followed by an ADD. */
221 Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29,
222 opnd2p2<<3);
223 }
224 if (Dbit29p2(opnd1p2)) {
225 Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30,
226 opnd2p2<<2);
227 }
228 if (Dbit30p2(opnd1p2)) {
229 Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31,
230 opnd2p2<<1);
231 }
232 if (Dbit31p2(opnd1p2)) {
233 Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2);
234 }
235 Dbl_rightshiftby4(opnd1p1,opnd1p2);
236 }
237 if (Dbit3p1(opnd3p1)==0) {
238 Dbl_leftshiftby1(opnd3p1,opnd3p2);
239 }
240 else {
241 /* result mantissa >= 2. */
242 dest_exponent++;
243 }
244 /* check for denormalized result */
245 while (Dbit3p1(opnd3p1)==0) {
246 Dbl_leftshiftby1(opnd3p1,opnd3p2);
247 dest_exponent--;
248 }
249 /*
250 * check for guard, sticky and inexact bits
251 */
252 stickybit |= Dallp2(opnd3p2) << 25;
253 guardbit = (Dallp2(opnd3p2) << 24) >> 31;
254 inexact = guardbit | stickybit;
255
256 /* align result mantissa */
257 Dbl_rightshiftby8(opnd3p1,opnd3p2);
258
259 /*
260 * round result
261 */
262 if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
263 Dbl_clear_signexponent(opnd3p1);
264 switch (Rounding_mode()) {
265 case ROUNDPLUS:
266 if (Dbl_iszero_sign(resultp1))
267 Dbl_increment(opnd3p1,opnd3p2);
268 break;
269 case ROUNDMINUS:
270 if (Dbl_isone_sign(resultp1))
271 Dbl_increment(opnd3p1,opnd3p2);
272 break;
273 case ROUNDNEAREST:
274 if (guardbit) {
275 if (stickybit || Dbl_isone_lowmantissap2(opnd3p2))
276 Dbl_increment(opnd3p1,opnd3p2);
277 }
278 }
279 if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
280 }
281 Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
282
283 /*
284 * Test for overflow
285 */
286 if (dest_exponent >= DBL_INFINITY_EXPONENT) {
287 /* trap if OVERFLOWTRAP enabled */
288 if (Is_overflowtrap_enabled()) {
289 /*
290 * Adjust bias of result
291 */
292 Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
293 Dbl_copytoptr(resultp1,resultp2,dstptr);
294 if (inexact)
295 if (Is_inexacttrap_enabled())
296 return (OVERFLOWEXCEPTION | INEXACTEXCEPTION);
297 else Set_inexactflag();
298 return (OVERFLOWEXCEPTION);
299 }
300 inexact = TRUE;
301 Set_overflowflag();
302 /* set result to infinity or largest number */
303 Dbl_setoverflow(resultp1,resultp2);
304 }
305 /*
306 * Test for underflow
307 */
308 else if (dest_exponent <= 0) {
309 /* trap if UNDERFLOWTRAP enabled */
310 if (Is_underflowtrap_enabled()) {
311 /*
312 * Adjust bias of result
313 */
314 Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
315 Dbl_copytoptr(resultp1,resultp2,dstptr);
316 if (inexact)
317 if (Is_inexacttrap_enabled())
318 return (UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
319 else Set_inexactflag();
320 return (UNDERFLOWEXCEPTION);
321 }
322
323 /* Determine if should set underflow flag */
324 is_tiny = TRUE;
325 if (dest_exponent == 0 && inexact) {
326 switch (Rounding_mode()) {
327 case ROUNDPLUS:
328 if (Dbl_iszero_sign(resultp1)) {
329 Dbl_increment(opnd3p1,opnd3p2);
330 if (Dbl_isone_hiddenoverflow(opnd3p1))
331 is_tiny = FALSE;
332 Dbl_decrement(opnd3p1,opnd3p2);
333 }
334 break;
335 case ROUNDMINUS:
336 if (Dbl_isone_sign(resultp1)) {
337 Dbl_increment(opnd3p1,opnd3p2);
338 if (Dbl_isone_hiddenoverflow(opnd3p1))
339 is_tiny = FALSE;
340 Dbl_decrement(opnd3p1,opnd3p2);
341 }
342 break;
343 case ROUNDNEAREST:
344 if (guardbit && (stickybit ||
345 Dbl_isone_lowmantissap2(opnd3p2))) {
346 Dbl_increment(opnd3p1,opnd3p2);
347 if (Dbl_isone_hiddenoverflow(opnd3p1))
348 is_tiny = FALSE;
349 Dbl_decrement(opnd3p1,opnd3p2);
350 }
351 break;
352 }
353 }
354
355 /*
356 * denormalize result or set to signed zero
357 */
358 stickybit = inexact;
359 Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
360 stickybit,inexact);
361
362 /* return zero or smallest number */
363 if (inexact) {
364 switch (Rounding_mode()) {
365 case ROUNDPLUS:
366 if (Dbl_iszero_sign(resultp1)) {
367 Dbl_increment(opnd3p1,opnd3p2);
368 }
369 break;
370 case ROUNDMINUS:
371 if (Dbl_isone_sign(resultp1)) {
372 Dbl_increment(opnd3p1,opnd3p2);
373 }
374 break;
375 case ROUNDNEAREST:
376 if (guardbit && (stickybit ||
377 Dbl_isone_lowmantissap2(opnd3p2))) {
378 Dbl_increment(opnd3p1,opnd3p2);
379 }
380 break;
381 }
382 if (is_tiny) Set_underflowflag();
383 }
384 Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
385 }
386 else Dbl_set_exponent(resultp1,dest_exponent);
387 /* check for inexact */
388 Dbl_copytoptr(resultp1,resultp2,dstptr);
389 if (inexact) {
390 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
391 else Set_inexactflag();
392 }
393 return(NOEXCEPTION);
394}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/dfrem.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Double Precision Floating-point Remainder
29 *
30 * External Interfaces:
31 * dbl_frem(srcptr1,srcptr2,dstptr,status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42
43#include "float.h"
44#include "dbl_float.h"
45
46/*
47 * Double Precision Floating-point Remainder
48 */
49
50int
51dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
52 dbl_floating_point * dstptr, unsigned int *status)
53{
54 register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
55 register unsigned int resultp1, resultp2;
56 register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
57 register boolean roundup = FALSE;
58
59 Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
60 Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
61 /*
62 * check first operand for NaN's or infinity
63 */
64 if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
65 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
66 if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
67 /* invalid since first operand is infinity */
68 if (Is_invalidtrap_enabled())
69 return(INVALIDEXCEPTION);
70 Set_invalidflag();
71 Dbl_makequietnan(resultp1,resultp2);
72 Dbl_copytoptr(resultp1,resultp2,dstptr);
73 return(NOEXCEPTION);
74 }
75 }
76 else {
77 /*
78 * is NaN; signaling or quiet?
79 */
80 if (Dbl_isone_signaling(opnd1p1)) {
81 /* trap if INVALIDTRAP enabled */
82 if (Is_invalidtrap_enabled())
83 return(INVALIDEXCEPTION);
84 /* make NaN quiet */
85 Set_invalidflag();
86 Dbl_set_quiet(opnd1p1);
87 }
88 /*
89 * is second operand a signaling NaN?
90 */
91 else if (Dbl_is_signalingnan(opnd2p1)) {
92 /* trap if INVALIDTRAP enabled */
93 if (Is_invalidtrap_enabled())
94 return(INVALIDEXCEPTION);
95 /* make NaN quiet */
96 Set_invalidflag();
97 Dbl_set_quiet(opnd2p1);
98 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
99 return(NOEXCEPTION);
100 }
101 /*
102 * return quiet NaN
103 */
104 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
105 return(NOEXCEPTION);
106 }
107 }
108 /*
109 * check second operand for NaN's or infinity
110 */
111 if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
112 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
113 /*
114 * return first operand
115 */
116 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
117 return(NOEXCEPTION);
118 }
119 /*
120 * is NaN; signaling or quiet?
121 */
122 if (Dbl_isone_signaling(opnd2p1)) {
123 /* trap if INVALIDTRAP enabled */
124 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
125 /* make NaN quiet */
126 Set_invalidflag();
127 Dbl_set_quiet(opnd2p1);
128 }
129 /*
130 * return quiet NaN
131 */
132 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
133 return(NOEXCEPTION);
134 }
135 /*
136 * check second operand for zero
137 */
138 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
139 /* invalid since second operand is zero */
140 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
141 Set_invalidflag();
142 Dbl_makequietnan(resultp1,resultp2);
143 Dbl_copytoptr(resultp1,resultp2,dstptr);
144 return(NOEXCEPTION);
145 }
146
147 /*
148 * get sign of result
149 */
150 resultp1 = opnd1p1;
151
152 /*
153 * check for denormalized operands
154 */
155 if (opnd1_exponent == 0) {
156 /* check for zero */
157 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
158 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
159 return(NOEXCEPTION);
160 }
161 /* normalize, then continue */
162 opnd1_exponent = 1;
163 Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
164 }
165 else {
166 Dbl_clear_signexponent_set_hidden(opnd1p1);
167 }
168 if (opnd2_exponent == 0) {
169 /* normalize, then continue */
170 opnd2_exponent = 1;
171 Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
172 }
173 else {
174 Dbl_clear_signexponent_set_hidden(opnd2p1);
175 }
176
177 /* find result exponent and divide step loop count */
178 dest_exponent = opnd2_exponent - 1;
179 stepcount = opnd1_exponent - opnd2_exponent;
180
181 /*
182 * check for opnd1/opnd2 < 1
183 */
184 if (stepcount < 0) {
185 /*
186 * check for opnd1/opnd2 > 1/2
187 *
188 * In this case n will round to 1, so
189 * r = opnd1 - opnd2
190 */
191 if (stepcount == -1 &&
192 Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
193 /* set sign */
194 Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
195 /* align opnd2 with opnd1 */
196 Dbl_leftshiftby1(opnd2p1,opnd2p2);
197 Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
198 opnd2p1,opnd2p2);
199 /* now normalize */
200 while (Dbl_iszero_hidden(opnd2p1)) {
201 Dbl_leftshiftby1(opnd2p1,opnd2p2);
202 dest_exponent--;
203 }
204 Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
205 goto testforunderflow;
206 }
207 /*
208 * opnd1/opnd2 <= 1/2
209 *
210 * In this case n will round to zero, so
211 * r = opnd1
212 */
213 Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
214 dest_exponent = opnd1_exponent;
215 goto testforunderflow;
216 }
217
218 /*
219 * Generate result
220 *
221 * Do iterative subtract until remainder is less than operand 2.
222 */
223 while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
224 if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
225 Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
226 }
227 Dbl_leftshiftby1(opnd1p1,opnd1p2);
228 }
229 /*
230 * Do last subtract, then determine which way to round if remainder
231 * is exactly 1/2 of opnd2
232 */
233 if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
234 Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
235 roundup = TRUE;
236 }
237 if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
238 /* division is exact, remainder is zero */
239 Dbl_setzero_exponentmantissa(resultp1,resultp2);
240 Dbl_copytoptr(resultp1,resultp2,dstptr);
241 return(NOEXCEPTION);
242 }
243
244 /*
245 * Check for cases where opnd1/opnd2 < n
246 *
247 * In this case the result's sign will be opposite that of
248 * opnd1. The mantissa also needs some correction.
249 */
250 Dbl_leftshiftby1(opnd1p1,opnd1p2);
251 if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
252 Dbl_invert_sign(resultp1);
253 Dbl_leftshiftby1(opnd2p1,opnd2p2);
254 Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
255 }
256 /* check for remainder being exactly 1/2 of opnd2 */
257 else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
258 Dbl_invert_sign(resultp1);
259 }
260
261 /* normalize result's mantissa */
262 while (Dbl_iszero_hidden(opnd1p1)) {
263 dest_exponent--;
264 Dbl_leftshiftby1(opnd1p1,opnd1p2);
265 }
266 Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
267
268 /*
269 * Test for underflow
270 */
271 testforunderflow:
272 if (dest_exponent <= 0) {
273 /* trap if UNDERFLOWTRAP enabled */
274 if (Is_underflowtrap_enabled()) {
275 /*
276 * Adjust bias of result
277 */
278 Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
279 /* frem is always exact */
280 Dbl_copytoptr(resultp1,resultp2,dstptr);
281 return(UNDERFLOWEXCEPTION);
282 }
283 /*
284 * denormalize result or set to signed zero
285 */
286 if (dest_exponent >= (1 - DBL_P)) {
287 Dbl_rightshift_exponentmantissa(resultp1,resultp2,
288 1-dest_exponent);
289 }
290 else {
291 Dbl_setzero_exponentmantissa(resultp1,resultp2);
292 }
293 }
294 else Dbl_set_exponent(resultp1,dest_exponent);
295 Dbl_copytoptr(resultp1,resultp2,dstptr);
296 return(NOEXCEPTION);
297}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/dfsqrt.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Double Floating-point Square Root
29 *
30 * External Interfaces:
31 * dbl_fsqrt(srcptr,nullptr,dstptr,status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "dbl_float.h"
44
45/*
46 * Double Floating-point Square Root
47 */
48
49/*ARGSUSED*/
50unsigned int
51dbl_fsqrt(
52 dbl_floating_point *srcptr,
53 unsigned int *nullptr,
54 dbl_floating_point *dstptr,
55 unsigned int *status)
56{
57 register unsigned int srcp1, srcp2, resultp1, resultp2;
58 register unsigned int newbitp1, newbitp2, sump1, sump2;
59 register int src_exponent;
60 register boolean guardbit = FALSE, even_exponent;
61
62 Dbl_copyfromptr(srcptr,srcp1,srcp2);
63 /*
64 * check source operand for NaN or infinity
65 */
66 if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
67 /*
68 * is signaling NaN?
69 */
70 if (Dbl_isone_signaling(srcp1)) {
71 /* trap if INVALIDTRAP enabled */
72 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
73 /* make NaN quiet */
74 Set_invalidflag();
75 Dbl_set_quiet(srcp1);
76 }
77 /*
78 * Return quiet NaN or positive infinity.
79 * Fall thru to negative test if negative infinity.
80 */
81 if (Dbl_iszero_sign(srcp1) ||
82 Dbl_isnotzero_mantissa(srcp1,srcp2)) {
83 Dbl_copytoptr(srcp1,srcp2,dstptr);
84 return(NOEXCEPTION);
85 }
86 }
87
88 /*
89 * check for zero source operand
90 */
91 if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) {
92 Dbl_copytoptr(srcp1,srcp2,dstptr);
93 return(NOEXCEPTION);
94 }
95
96 /*
97 * check for negative source operand
98 */
99 if (Dbl_isone_sign(srcp1)) {
100 /* trap if INVALIDTRAP enabled */
101 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
102 /* make NaN quiet */
103 Set_invalidflag();
104 Dbl_makequietnan(srcp1,srcp2);
105 Dbl_copytoptr(srcp1,srcp2,dstptr);
106 return(NOEXCEPTION);
107 }
108
109 /*
110 * Generate result
111 */
112 if (src_exponent > 0) {
113 even_exponent = Dbl_hidden(srcp1);
114 Dbl_clear_signexponent_set_hidden(srcp1);
115 }
116 else {
117 /* normalize operand */
118 Dbl_clear_signexponent(srcp1);
119 src_exponent++;
120 Dbl_normalize(srcp1,srcp2,src_exponent);
121 even_exponent = src_exponent & 1;
122 }
123 if (even_exponent) {
124 /* exponent is even */
125 /* Add comment here. Explain why odd exponent needs correction */
126 Dbl_leftshiftby1(srcp1,srcp2);
127 }
128 /*
129 * Add comment here. Explain following algorithm.
130 *
131 * Trust me, it works.
132 *
133 */
134 Dbl_setzero(resultp1,resultp2);
135 Dbl_allp1(newbitp1) = 1 << (DBL_P - 32);
136 Dbl_setzero_mantissap2(newbitp2);
137 while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) {
138 Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2);
139 if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) {
140 Dbl_leftshiftby1(newbitp1,newbitp2);
141 /* update result */
142 Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,
143 resultp1,resultp2);
144 Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2);
145 Dbl_rightshiftby2(newbitp1,newbitp2);
146 }
147 else {
148 Dbl_rightshiftby1(newbitp1,newbitp2);
149 }
150 Dbl_leftshiftby1(srcp1,srcp2);
151 }
152 /* correct exponent for pre-shift */
153 if (even_exponent) {
154 Dbl_rightshiftby1(resultp1,resultp2);
155 }
156
157 /* check for inexact */
158 if (Dbl_isnotzero(srcp1,srcp2)) {
159 if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) {
160 Dbl_increment(resultp1,resultp2);
161 }
162 guardbit = Dbl_lowmantissap2(resultp2);
163 Dbl_rightshiftby1(resultp1,resultp2);
164
165 /* now round result */
166 switch (Rounding_mode()) {
167 case ROUNDPLUS:
168 Dbl_increment(resultp1,resultp2);
169 break;
170 case ROUNDNEAREST:
171 /* stickybit is always true, so guardbit
172 * is enough to determine rounding */
173 if (guardbit) {
174 Dbl_increment(resultp1,resultp2);
175 }
176 break;
177 }
178 /* increment result exponent by 1 if mantissa overflowed */
179 if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2;
180
181 if (Is_inexacttrap_enabled()) {
182 Dbl_set_exponent(resultp1,
183 ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
184 Dbl_copytoptr(resultp1,resultp2,dstptr);
185 return(INEXACTEXCEPTION);
186 }
187 else Set_inexactflag();
188 }
189 else {
190 Dbl_rightshiftby1(resultp1,resultp2);
191 }
192 Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
193 Dbl_copytoptr(resultp1,resultp2,dstptr);
194 return(NOEXCEPTION);
195}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/dfsub.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Double_subtract: subtract two double precision values.
29 *
30 * External Interfaces:
31 * dbl_fsub(leftptr, rightptr, dstptr, status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "dbl_float.h"
44
45/*
46 * Double_subtract: subtract two double precision values.
47 */
48int
49dbl_fsub(
50 dbl_floating_point *leftptr,
51 dbl_floating_point *rightptr,
52 dbl_floating_point *dstptr,
53 unsigned int *status)
54 {
55 register unsigned int signless_upper_left, signless_upper_right, save;
56 register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
57 register unsigned int resultp1 = 0, resultp2 = 0;
58
59 register int result_exponent, right_exponent, diff_exponent;
60 register int sign_save, jumpsize;
61 register boolean inexact = FALSE, underflowtrap;
62
63 /* Create local copies of the numbers */
64 Dbl_copyfromptr(leftptr,leftp1,leftp2);
65 Dbl_copyfromptr(rightptr,rightp1,rightp2);
66
67 /* A zero "save" helps discover equal operands (for later), *
68 * and is used in swapping operands (if needed). */
69 Dbl_xortointp1(leftp1,rightp1,/*to*/save);
70
71 /*
72 * check first operand for NaN's or infinity
73 */
74 if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
75 {
76 if (Dbl_iszero_mantissa(leftp1,leftp2))
77 {
78 if (Dbl_isnotnan(rightp1,rightp2))
79 {
80 if (Dbl_isinfinity(rightp1,rightp2) && save==0)
81 {
82 /*
83 * invalid since operands are same signed infinity's
84 */
85 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
86 Set_invalidflag();
87 Dbl_makequietnan(resultp1,resultp2);
88 Dbl_copytoptr(resultp1,resultp2,dstptr);
89 return(NOEXCEPTION);
90 }
91 /*
92 * return infinity
93 */
94 Dbl_copytoptr(leftp1,leftp2,dstptr);
95 return(NOEXCEPTION);
96 }
97 }
98 else
99 {
100 /*
101 * is NaN; signaling or quiet?
102 */
103 if (Dbl_isone_signaling(leftp1))
104 {
105 /* trap if INVALIDTRAP enabled */
106 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
107 /* make NaN quiet */
108 Set_invalidflag();
109 Dbl_set_quiet(leftp1);
110 }
111 /*
112 * is second operand a signaling NaN?
113 */
114 else if (Dbl_is_signalingnan(rightp1))
115 {
116 /* trap if INVALIDTRAP enabled */
117 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
118 /* make NaN quiet */
119 Set_invalidflag();
120 Dbl_set_quiet(rightp1);
121 Dbl_copytoptr(rightp1,rightp2,dstptr);
122 return(NOEXCEPTION);
123 }
124 /*
125 * return quiet NaN
126 */
127 Dbl_copytoptr(leftp1,leftp2,dstptr);
128 return(NOEXCEPTION);
129 }
130 } /* End left NaN or Infinity processing */
131 /*
132 * check second operand for NaN's or infinity
133 */
134 if (Dbl_isinfinity_exponent(rightp1))
135 {
136 if (Dbl_iszero_mantissa(rightp1,rightp2))
137 {
138 /* return infinity */
139 Dbl_invert_sign(rightp1);
140 Dbl_copytoptr(rightp1,rightp2,dstptr);
141 return(NOEXCEPTION);
142 }
143 /*
144 * is NaN; signaling or quiet?
145 */
146 if (Dbl_isone_signaling(rightp1))
147 {
148 /* trap if INVALIDTRAP enabled */
149 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
150 /* make NaN quiet */
151 Set_invalidflag();
152 Dbl_set_quiet(rightp1);
153 }
154 /*
155 * return quiet NaN
156 */
157 Dbl_copytoptr(rightp1,rightp2,dstptr);
158 return(NOEXCEPTION);
159 } /* End right NaN or Infinity processing */
160
161 /* Invariant: Must be dealing with finite numbers */
162
163 /* Compare operands by removing the sign */
164 Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
165 Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
166
167 /* sign difference selects add or sub operation. */
168 if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
169 {
170 /* Set the left operand to the larger one by XOR swap *
171 * First finish the first word using "save" */
172 Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
173 Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
174 Dbl_swap_lower(leftp2,rightp2);
175 result_exponent = Dbl_exponent(leftp1);
176 Dbl_invert_sign(leftp1);
177 }
178 /* Invariant: left is not smaller than right. */
179
180 if((right_exponent = Dbl_exponent(rightp1)) == 0)
181 {
182 /* Denormalized operands. First look for zeroes */
183 if(Dbl_iszero_mantissa(rightp1,rightp2))
184 {
185 /* right is zero */
186 if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
187 {
188 /* Both operands are zeros */
189 Dbl_invert_sign(rightp1);
190 if(Is_rounding_mode(ROUNDMINUS))
191 {
192 Dbl_or_signs(leftp1,/*with*/rightp1);
193 }
194 else
195 {
196 Dbl_and_signs(leftp1,/*with*/rightp1);
197 }
198 }
199 else
200 {
201 /* Left is not a zero and must be the result. Trapped
202 * underflows are signaled if left is denormalized. Result
203 * is always exact. */
204 if( (result_exponent == 0) && Is_underflowtrap_enabled() )
205 {
206 /* need to normalize results mantissa */
207 sign_save = Dbl_signextendedsign(leftp1);
208 Dbl_leftshiftby1(leftp1,leftp2);
209 Dbl_normalize(leftp1,leftp2,result_exponent);
210 Dbl_set_sign(leftp1,/*using*/sign_save);
211 Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
212 Dbl_copytoptr(leftp1,leftp2,dstptr);
213 /* inexact = FALSE */
214 return(UNDERFLOWEXCEPTION);
215 }
216 }
217 Dbl_copytoptr(leftp1,leftp2,dstptr);
218 return(NOEXCEPTION);
219 }
220
221 /* Neither are zeroes */
222 Dbl_clear_sign(rightp1); /* Exponent is already cleared */
223 if(result_exponent == 0 )
224 {
225 /* Both operands are denormalized. The result must be exact
226 * and is simply calculated. A sum could become normalized and a
227 * difference could cancel to a true zero. */
228 if( (/*signed*/int) save >= 0 )
229 {
230 Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
231 /*into*/resultp1,resultp2);
232 if(Dbl_iszero_mantissa(resultp1,resultp2))
233 {
234 if(Is_rounding_mode(ROUNDMINUS))
235 {
236 Dbl_setone_sign(resultp1);
237 }
238 else
239 {
240 Dbl_setzero_sign(resultp1);
241 }
242 Dbl_copytoptr(resultp1,resultp2,dstptr);
243 return(NOEXCEPTION);
244 }
245 }
246 else
247 {
248 Dbl_addition(leftp1,leftp2,rightp1,rightp2,
249 /*into*/resultp1,resultp2);
250 if(Dbl_isone_hidden(resultp1))
251 {
252 Dbl_copytoptr(resultp1,resultp2,dstptr);
253 return(NOEXCEPTION);
254 }
255 }
256 if(Is_underflowtrap_enabled())
257 {
258 /* need to normalize result */
259 sign_save = Dbl_signextendedsign(resultp1);
260 Dbl_leftshiftby1(resultp1,resultp2);
261 Dbl_normalize(resultp1,resultp2,result_exponent);
262 Dbl_set_sign(resultp1,/*using*/sign_save);
263 Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
264 Dbl_copytoptr(resultp1,resultp2,dstptr);
265 /* inexact = FALSE */
266 return(UNDERFLOWEXCEPTION);
267 }
268 Dbl_copytoptr(resultp1,resultp2,dstptr);
269 return(NOEXCEPTION);
270 }
271 right_exponent = 1; /* Set exponent to reflect different bias
272 * with denomalized numbers. */
273 }
274 else
275 {
276 Dbl_clear_signexponent_set_hidden(rightp1);
277 }
278 Dbl_clear_exponent_set_hidden(leftp1);
279 diff_exponent = result_exponent - right_exponent;
280
281 /*
282 * Special case alignment of operands that would force alignment
283 * beyond the extent of the extension. A further optimization
284 * could special case this but only reduces the path length for this
285 * infrequent case.
286 */
287 if(diff_exponent > DBL_THRESHOLD)
288 {
289 diff_exponent = DBL_THRESHOLD;
290 }
291
292 /* Align right operand by shifting to right */
293 Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
294 /*and lower to*/extent);
295
296 /* Treat sum and difference of the operands separately. */
297 if( (/*signed*/int) save >= 0 )
298 {
299 /*
300 * Difference of the two operands. Their can be no overflow. A
301 * borrow can occur out of the hidden bit and force a post
302 * normalization phase.
303 */
304 Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
305 /*with*/extent,/*into*/resultp1,resultp2);
306 if(Dbl_iszero_hidden(resultp1))
307 {
308 /* Handle normalization */
309 /* A straight foward algorithm would now shift the result
310 * and extension left until the hidden bit becomes one. Not
311 * all of the extension bits need participate in the shift.
312 * Only the two most significant bits (round and guard) are
313 * needed. If only a single shift is needed then the guard
314 * bit becomes a significant low order bit and the extension
315 * must participate in the rounding. If more than a single
316 * shift is needed, then all bits to the right of the guard
317 * bit are zeros, and the guard bit may or may not be zero. */
318 sign_save = Dbl_signextendedsign(resultp1);
319 Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
320
321 /* Need to check for a zero result. The sign and exponent
322 * fields have already been zeroed. The more efficient test
323 * of the full object can be used.
324 */
325 if(Dbl_iszero(resultp1,resultp2))
326 /* Must have been "x-x" or "x+(-x)". */
327 {
328 if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
329 Dbl_copytoptr(resultp1,resultp2,dstptr);
330 return(NOEXCEPTION);
331 }
332 result_exponent--;
333 /* Look to see if normalization is finished. */
334 if(Dbl_isone_hidden(resultp1))
335 {
336 if(result_exponent==0)
337 {
338 /* Denormalized, exponent should be zero. Left operand *
339 * was normalized, so extent (guard, round) was zero */
340 goto underflow;
341 }
342 else
343 {
344 /* No further normalization is needed. */
345 Dbl_set_sign(resultp1,/*using*/sign_save);
346 Ext_leftshiftby1(extent);
347 goto round;
348 }
349 }
350
351 /* Check for denormalized, exponent should be zero. Left *
352 * operand was normalized, so extent (guard, round) was zero */
353 if(!(underflowtrap = Is_underflowtrap_enabled()) &&
354 result_exponent==0) goto underflow;
355
356 /* Shift extension to complete one bit of normalization and
357 * update exponent. */
358 Ext_leftshiftby1(extent);
359
360 /* Discover first one bit to determine shift amount. Use a
361 * modified binary search. We have already shifted the result
362 * one position right and still not found a one so the remainder
363 * of the extension must be zero and simplifies rounding. */
364 /* Scan bytes */
365 while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
366 {
367 Dbl_leftshiftby8(resultp1,resultp2);
368 if((result_exponent -= 8) <= 0 && !underflowtrap)
369 goto underflow;
370 }
371 /* Now narrow it down to the nibble */
372 if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
373 {
374 /* The lower nibble contains the normalizing one */
375 Dbl_leftshiftby4(resultp1,resultp2);
376 if((result_exponent -= 4) <= 0 && !underflowtrap)
377 goto underflow;
378 }
379 /* Select case were first bit is set (already normalized)
380 * otherwise select the proper shift. */
381 if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
382 {
383 /* Already normalized */
384 if(result_exponent <= 0) goto underflow;
385 Dbl_set_sign(resultp1,/*using*/sign_save);
386 Dbl_set_exponent(resultp1,/*using*/result_exponent);
387 Dbl_copytoptr(resultp1,resultp2,dstptr);
388 return(NOEXCEPTION);
389 }
390 Dbl_sethigh4bits(resultp1,/*using*/sign_save);
391 switch(jumpsize)
392 {
393 case 1:
394 {
395 Dbl_leftshiftby3(resultp1,resultp2);
396 result_exponent -= 3;
397 break;
398 }
399 case 2:
400 case 3:
401 {
402 Dbl_leftshiftby2(resultp1,resultp2);
403 result_exponent -= 2;
404 break;
405 }
406 case 4:
407 case 5:
408 case 6:
409 case 7:
410 {
411 Dbl_leftshiftby1(resultp1,resultp2);
412 result_exponent -= 1;
413 break;
414 }
415 }
416 if(result_exponent > 0)
417 {
418 Dbl_set_exponent(resultp1,/*using*/result_exponent);
419 Dbl_copytoptr(resultp1,resultp2,dstptr);
420 return(NOEXCEPTION); /* Sign bit is already set */
421 }
422 /* Fixup potential underflows */
423 underflow:
424 if(Is_underflowtrap_enabled())
425 {
426 Dbl_set_sign(resultp1,sign_save);
427 Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
428 Dbl_copytoptr(resultp1,resultp2,dstptr);
429 /* inexact = FALSE */
430 return(UNDERFLOWEXCEPTION);
431 }
432 /*
433 * Since we cannot get an inexact denormalized result,
434 * we can now return.
435 */
436 Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
437 Dbl_clear_signexponent(resultp1);
438 Dbl_set_sign(resultp1,sign_save);
439 Dbl_copytoptr(resultp1,resultp2,dstptr);
440 return(NOEXCEPTION);
441 } /* end if(hidden...)... */
442 /* Fall through and round */
443 } /* end if(save >= 0)... */
444 else
445 {
446 /* Subtract magnitudes */
447 Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
448 if(Dbl_isone_hiddenoverflow(resultp1))
449 {
450 /* Prenormalization required. */
451 Dbl_rightshiftby1_withextent(resultp2,extent,extent);
452 Dbl_arithrightshiftby1(resultp1,resultp2);
453 result_exponent++;
454 } /* end if hiddenoverflow... */
455 } /* end else ...subtract magnitudes... */
456
457 /* Round the result. If the extension is all zeros,then the result is
458 * exact. Otherwise round in the correct direction. No underflow is
459 * possible. If a postnormalization is necessary, then the mantissa is
460 * all zeros so no shift is needed. */
461 round:
462 if(Ext_isnotzero(extent))
463 {
464 inexact = TRUE;
465 switch(Rounding_mode())
466 {
467 case ROUNDNEAREST: /* The default. */
468 if(Ext_isone_sign(extent))
469 {
470 /* at least 1/2 ulp */
471 if(Ext_isnotzero_lower(extent) ||
472 Dbl_isone_lowmantissap2(resultp2))
473 {
474 /* either exactly half way and odd or more than 1/2ulp */
475 Dbl_increment(resultp1,resultp2);
476 }
477 }
478 break;
479
480 case ROUNDPLUS:
481 if(Dbl_iszero_sign(resultp1))
482 {
483 /* Round up positive results */
484 Dbl_increment(resultp1,resultp2);
485 }
486 break;
487
488 case ROUNDMINUS:
489 if(Dbl_isone_sign(resultp1))
490 {
491 /* Round down negative results */
492 Dbl_increment(resultp1,resultp2);
493 }
494
495 case ROUNDZERO:;
496 /* truncate is simple */
497 } /* end switch... */
498 if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
499 }
500 if(result_exponent == DBL_INFINITY_EXPONENT)
501 {
502 /* Overflow */
503 if(Is_overflowtrap_enabled())
504 {
505 Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
506 Dbl_copytoptr(resultp1,resultp2,dstptr);
507 if (inexact)
508 if (Is_inexacttrap_enabled())
509 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
510 else Set_inexactflag();
511 return(OVERFLOWEXCEPTION);
512 }
513 else
514 {
515 inexact = TRUE;
516 Set_overflowflag();
517 Dbl_setoverflow(resultp1,resultp2);
518 }
519 }
520 else Dbl_set_exponent(resultp1,result_exponent);
521 Dbl_copytoptr(resultp1,resultp2,dstptr);
522 if(inexact)
523 if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
524 else Set_inexactflag();
525 return(NOEXCEPTION);
526 }
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * linux/arch/math-emu/driver.c.c
23 *
24 * decodes and dispatches unimplemented FPU instructions
25 *
26 * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org>
27 * Copyright (C) 2001 Hewlett-Packard <bame@debian.org>
28 */
29
30#include <linux/sched.h>
31#include "float.h"
32#include "math-emu.h"
33
34
35#define fptpos 31
36#define fpr1pos 10
37#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
38
39#define FPUDEBUG 0
40
41/* Format of the floating-point exception registers. */
42struct exc_reg {
43 unsigned int exception : 6;
44 unsigned int ei : 26;
45};
46
47/* Macros for grabbing bits of the instruction format from the 'ei'
48 field above. */
49/* Major opcode 0c and 0e */
50#define FP0CE_UID(i) (((i) >> 6) & 3)
51#define FP0CE_CLASS(i) (((i) >> 9) & 3)
52#define FP0CE_SUBOP(i) (((i) >> 13) & 7)
53#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
54#define FP0C_FORMAT(i) (((i) >> 11) & 3)
55#define FP0E_FORMAT(i) (((i) >> 11) & 1)
56
57/* Major opcode 0c, uid 2 (performance monitoring) */
58#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
59
60/* Major opcode 2e (fused operations). */
61#define FP2E_SUBOP(i) (((i) >> 5) & 1)
62#define FP2E_FORMAT(i) (((i) >> 11) & 1)
63
64/* Major opcode 26 (FMPYSUB) */
65/* Major opcode 06 (FMPYADD) */
66#define FPx6_FORMAT(i) ((i) & 0x1f)
67
68/* Flags and enable bits of the status word. */
69#define FPSW_FLAGS(w) ((w) >> 27)
70#define FPSW_ENABLE(w) ((w) & 0x1f)
71#define FPSW_V (1<<4)
72#define FPSW_Z (1<<3)
73#define FPSW_O (1<<2)
74#define FPSW_U (1<<1)
75#define FPSW_I (1<<0)
76
77/* Handle a floating point exception. Return zero if the faulting
78 instruction can be completed successfully. */
79int
80handle_fpe(struct pt_regs *regs)
81{
82 extern void printbinary(unsigned long x, int nbits);
83 struct siginfo si;
84 unsigned int orig_sw, sw;
85 int signalcode;
86 /* need an intermediate copy of float regs because FPU emulation
87 * code expects an artificial last entry which contains zero
88 *
89 * also, the passed in fr registers contain one word that defines
90 * the fpu type. the fpu type information is constructed
91 * inside the emulation code
92 */
93 __u64 frcopy[36];
94
95 memcpy(frcopy, regs->fr, sizeof regs->fr);
96 frcopy[32] = 0;
97
98 memcpy(&orig_sw, frcopy, sizeof(orig_sw));
99
100 if (FPUDEBUG) {
101 printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n ");
102 printbinary(orig_sw, 32);
103 printk(KERN_DEBUG "\n");
104 }
105
106 signalcode = decode_fpu(frcopy, 0x666);
107
108 /* Status word = FR0L. */
109 memcpy(&sw, frcopy, sizeof(sw));
110 if (FPUDEBUG) {
111 printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n",
112 signalcode >> 24, signalcode & 0xffffff);
113 printbinary(sw, 32);
114 printk(KERN_DEBUG "\n");
115 }
116
117 memcpy(regs->fr, frcopy, sizeof regs->fr);
118 if (signalcode != 0) {
119 si.si_signo = signalcode >> 24;
120 si.si_errno = 0;
121 si.si_code = signalcode & 0xffffff;
122 si.si_addr = (void __user *) regs->iaoq[0];
123 force_sig_info(si.si_signo, &si, current);
124 return -1;
125 }
126
127 return signalcode ? -1 : 0;
128}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fcnvff.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single Floating-point to Double Floating-point
29 * Double Floating-point to Single Floating-point
30 *
31 * External Interfaces:
32 * dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status)
33 * sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status)
34 *
35 * Internal Interfaces:
36 *
37 * Theory:
38 * <<please update with a overview of the operation of this file>>
39 *
40 * END_DESC
41*/
42
43
44#include "float.h"
45#include "sgl_float.h"
46#include "dbl_float.h"
47#include "cnv_float.h"
48
49/*
50 * Single Floating-point to Double Floating-point
51 */
52/*ARGSUSED*/
53int
54sgl_to_dbl_fcnvff(
55 sgl_floating_point *srcptr,
56 unsigned int *nullptr,
57 dbl_floating_point *dstptr,
58 unsigned int *status)
59{
60 register unsigned int src, resultp1, resultp2;
61 register int src_exponent;
62
63 src = *srcptr;
64 src_exponent = Sgl_exponent(src);
65 Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */
66 /*
67 * Test for NaN or infinity
68 */
69 if (src_exponent == SGL_INFINITY_EXPONENT) {
70 /*
71 * determine if NaN or infinity
72 */
73 if (Sgl_iszero_mantissa(src)) {
74 /*
75 * is infinity; want to return double infinity
76 */
77 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
78 Dbl_copytoptr(resultp1,resultp2,dstptr);
79 return(NOEXCEPTION);
80 }
81 else {
82 /*
83 * is NaN; signaling or quiet?
84 */
85 if (Sgl_isone_signaling(src)) {
86 /* trap if INVALIDTRAP enabled */
87 if (Is_invalidtrap_enabled())
88 return(INVALIDEXCEPTION);
89 /* make NaN quiet */
90 else {
91 Set_invalidflag();
92 Sgl_set_quiet(src);
93 }
94 }
95 /*
96 * NaN is quiet, return as double NaN
97 */
98 Dbl_setinfinity_exponent(resultp1);
99 Sgl_to_dbl_mantissa(src,resultp1,resultp2);
100 Dbl_copytoptr(resultp1,resultp2,dstptr);
101 return(NOEXCEPTION);
102 }
103 }
104 /*
105 * Test for zero or denormalized
106 */
107 if (src_exponent == 0) {
108 /*
109 * determine if zero or denormalized
110 */
111 if (Sgl_isnotzero_mantissa(src)) {
112 /*
113 * is denormalized; want to normalize
114 */
115 Sgl_clear_signexponent(src);
116 Sgl_leftshiftby1(src);
117 Sgl_normalize(src,src_exponent);
118 Sgl_to_dbl_exponent(src_exponent,resultp1);
119 Sgl_to_dbl_mantissa(src,resultp1,resultp2);
120 }
121 else {
122 Dbl_setzero_exponentmantissa(resultp1,resultp2);
123 }
124 Dbl_copytoptr(resultp1,resultp2,dstptr);
125 return(NOEXCEPTION);
126 }
127 /*
128 * No special cases, just complete the conversion
129 */
130 Sgl_to_dbl_exponent(src_exponent, resultp1);
131 Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
132 Dbl_copytoptr(resultp1,resultp2,dstptr);
133 return(NOEXCEPTION);
134}
135
136/*
137 * Double Floating-point to Single Floating-point
138 */
139/*ARGSUSED*/
140int
141dbl_to_sgl_fcnvff(
142 dbl_floating_point *srcptr,
143 unsigned int *nullptr,
144 sgl_floating_point *dstptr,
145 unsigned int *status)
146{
147 register unsigned int srcp1, srcp2, result;
148 register int src_exponent, dest_exponent, dest_mantissa;
149 register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
150 register boolean lsb_odd = FALSE;
151 boolean is_tiny;
152
153 Dbl_copyfromptr(srcptr,srcp1,srcp2);
154 src_exponent = Dbl_exponent(srcp1);
155 Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */
156 /*
157 * Test for NaN or infinity
158 */
159 if (src_exponent == DBL_INFINITY_EXPONENT) {
160 /*
161 * determine if NaN or infinity
162 */
163 if (Dbl_iszero_mantissa(srcp1,srcp2)) {
164 /*
165 * is infinity; want to return single infinity
166 */
167 Sgl_setinfinity_exponentmantissa(result);
168 *dstptr = result;
169 return(NOEXCEPTION);
170 }
171 /*
172 * is NaN; signaling or quiet?
173 */
174 if (Dbl_isone_signaling(srcp1)) {
175 /* trap if INVALIDTRAP enabled */
176 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
177 else {
178 Set_invalidflag();
179 /* make NaN quiet */
180 Dbl_set_quiet(srcp1);
181 }
182 }
183 /*
184 * NaN is quiet, return as single NaN
185 */
186 Sgl_setinfinity_exponent(result);
187 Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
188 if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
189 *dstptr = result;
190 return(NOEXCEPTION);
191 }
192 /*
193 * Generate result
194 */
195 Dbl_to_sgl_exponent(src_exponent,dest_exponent);
196 if (dest_exponent > 0) {
197 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
198 stickybit,lsb_odd);
199 }
200 else {
201 if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
202 Sgl_setzero_exponentmantissa(result);
203 *dstptr = result;
204 return(NOEXCEPTION);
205 }
206 if (Is_underflowtrap_enabled()) {
207 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
208 guardbit,stickybit,lsb_odd);
209 }
210 else {
211 /* compute result, determine inexact info,
212 * and set Underflowflag if appropriate
213 */
214 Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
215 dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
216 is_tiny);
217 }
218 }
219 /*
220 * Now round result if not exact
221 */
222 if (inexact) {
223 switch (Rounding_mode()) {
224 case ROUNDPLUS:
225 if (Sgl_iszero_sign(result)) dest_mantissa++;
226 break;
227 case ROUNDMINUS:
228 if (Sgl_isone_sign(result)) dest_mantissa++;
229 break;
230 case ROUNDNEAREST:
231 if (guardbit) {
232 if (stickybit || lsb_odd) dest_mantissa++;
233 }
234 }
235 }
236 Sgl_set_exponentmantissa(result,dest_mantissa);
237
238 /*
239 * check for mantissa overflow after rounding
240 */
241 if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
242 Sgl_isone_hidden(result)) dest_exponent++;
243
244 /*
245 * Test for overflow
246 */
247 if (dest_exponent >= SGL_INFINITY_EXPONENT) {
248 /* trap if OVERFLOWTRAP enabled */
249 if (Is_overflowtrap_enabled()) {
250 /*
251 * Check for gross overflow
252 */
253 if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
254 return(UNIMPLEMENTEDEXCEPTION);
255
256 /*
257 * Adjust bias of result
258 */
259 Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
260 *dstptr = result;
261 if (inexact)
262 if (Is_inexacttrap_enabled())
263 return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
264 else Set_inexactflag();
265 return(OVERFLOWEXCEPTION);
266 }
267 Set_overflowflag();
268 inexact = TRUE;
269 /* set result to infinity or largest number */
270 Sgl_setoverflow(result);
271 }
272 /*
273 * Test for underflow
274 */
275 else if (dest_exponent <= 0) {
276 /* trap if UNDERFLOWTRAP enabled */
277 if (Is_underflowtrap_enabled()) {
278 /*
279 * Check for gross underflow
280 */
281 if (dest_exponent <= -(SGL_WRAP))
282 return(UNIMPLEMENTEDEXCEPTION);
283 /*
284 * Adjust bias of result
285 */
286 Sgl_setwrapped_exponent(result,dest_exponent,unfl);
287 *dstptr = result;
288 if (inexact)
289 if (Is_inexacttrap_enabled())
290 return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
291 else Set_inexactflag();
292 return(UNDERFLOWEXCEPTION);
293 }
294 /*
295 * result is denormalized or signed zero
296 */
297 if (inexact && is_tiny) Set_underflowflag();
298
299 }
300 else Sgl_set_exponent(result,dest_exponent);
301 *dstptr = result;
302 /*
303 * Trap if inexact trap is enabled
304 */
305 if (inexact)
306 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
307 else Set_inexactflag();
308 return(NOEXCEPTION);
309}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Floating-point to Unsigned Fixed-point Converts
29 *
30 * External Interfaces:
31 * dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
32 * dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
33 * sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
34 * sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
35 *
36 * Internal Interfaces:
37 *
38 * Theory:
39 * <<please update with a overview of the operation of this file>>
40 *
41 * END_DESC
42*/
43
44
45#include "float.h"
46#include "sgl_float.h"
47#include "dbl_float.h"
48#include "cnv_float.h"
49
50/************************************************************************
51 * Floating-point to Unsigned Fixed-point Converts *
52 ************************************************************************/
53
54/*
55 * Single Floating-point to Single Unsigned Fixed
56 */
57/*ARGSUSED*/
58int
59sgl_to_sgl_fcnvfu(
60 sgl_floating_point *srcptr,
61 unsigned int *nullptr,
62 unsigned int *dstptr,
63 unsigned int *status)
64{
65 register unsigned int src, result;
66 register int src_exponent;
67 register boolean inexact = FALSE;
68
69 src = *srcptr;
70 src_exponent = Sgl_exponent(src) - SGL_BIAS;
71
72 /*
73 * Test for overflow
74 */
75 if (src_exponent > SGL_FX_MAX_EXP + 1) {
76 if (Sgl_isone_sign(src)) {
77 result = 0;
78 } else {
79 result = 0xffffffff;
80 }
81 if (Is_invalidtrap_enabled()) {
82 return(INVALIDEXCEPTION);
83 }
84 Set_invalidflag();
85 *dstptr = result;
86 return(NOEXCEPTION);
87 }
88 /*
89 * Generate result
90 */
91 if (src_exponent >= 0) {
92 /*
93 * Check sign.
94 * If negative, trap unimplemented.
95 */
96 if (Sgl_isone_sign(src)) {
97 result = 0;
98 if (Is_invalidtrap_enabled()) {
99 return(INVALIDEXCEPTION);
100 }
101 Set_invalidflag();
102 *dstptr = result;
103 return(NOEXCEPTION);
104 }
105 Sgl_clear_signexponent_set_hidden(src);
106 Suint_from_sgl_mantissa(src,src_exponent,result);
107
108 /* check for inexact */
109 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
110 inexact = TRUE;
111 /* round result */
112 switch (Rounding_mode()) {
113 case ROUNDPLUS:
114 result++;
115 break;
116 case ROUNDMINUS: /* never negative */
117 break;
118 case ROUNDNEAREST:
119 if (Sgl_isone_roundbit(src,src_exponent) &&
120 (Sgl_isone_stickybit(src,src_exponent) ||
121 (result & 1))) {
122 result++;
123 }
124 break;
125 }
126 }
127 } else {
128 result = 0;
129
130 /* check for inexact */
131 if (Sgl_isnotzero_exponentmantissa(src)) {
132 inexact = TRUE;
133 /* round result */
134 switch (Rounding_mode()) {
135 case ROUNDPLUS:
136 if (Sgl_iszero_sign(src)) {
137 result++;
138 }
139 break;
140 case ROUNDMINUS:
141 if (Sgl_isone_sign(src)) {
142 result = 0;
143 if (Is_invalidtrap_enabled()) {
144 return(INVALIDEXCEPTION);
145 }
146 Set_invalidflag();
147 inexact = FALSE;
148 }
149 break;
150 case ROUNDNEAREST:
151 if (src_exponent == -1 &&
152 Sgl_isnotzero_mantissa(src)) {
153 if (Sgl_isone_sign(src)) {
154 result = 0;
155 if (Is_invalidtrap_enabled()) {
156 return(INVALIDEXCEPTION);
157 }
158 Set_invalidflag();
159 inexact = FALSE;
160 }
161 else result++;
162 }
163 break;
164 }
165 }
166 }
167 *dstptr = result;
168 if (inexact) {
169 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
170 else Set_inexactflag();
171 }
172 return(NOEXCEPTION);
173}
174
175/*
176 * Single Floating-point to Double Unsigned Fixed
177 */
178/*ARGSUSED*/
179int
180sgl_to_dbl_fcnvfu(
181 sgl_floating_point *srcptr,
182 unsigned int *nullptr,
183 dbl_unsigned *dstptr,
184 unsigned int *status)
185{
186 register int src_exponent;
187 register unsigned int src, resultp1, resultp2;
188 register boolean inexact = FALSE;
189
190 src = *srcptr;
191 src_exponent = Sgl_exponent(src) - SGL_BIAS;
192
193 /*
194 * Test for overflow
195 */
196 if (src_exponent > DBL_FX_MAX_EXP + 1) {
197 if (Sgl_isone_sign(src)) {
198 resultp1 = resultp2 = 0;
199 } else {
200 resultp1 = resultp2 = 0xffffffff;
201 }
202 if (Is_invalidtrap_enabled()) {
203 return(INVALIDEXCEPTION);
204 }
205 Set_invalidflag();
206 Duint_copytoptr(resultp1,resultp2,dstptr);
207 return(NOEXCEPTION);
208 }
209 /*
210 * Generate result
211 */
212 if (src_exponent >= 0) {
213 /*
214 * Check sign.
215 * If negative, trap unimplemented.
216 */
217 if (Sgl_isone_sign(src)) {
218 resultp1 = resultp2 = 0;
219 if (Is_invalidtrap_enabled()) {
220 return(INVALIDEXCEPTION);
221 }
222 Set_invalidflag();
223 Duint_copytoptr(resultp1,resultp2,dstptr);
224 return(NOEXCEPTION);
225 }
226 Sgl_clear_signexponent_set_hidden(src);
227 Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
228
229 /* check for inexact */
230 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
231 inexact = TRUE;
232 /* round result */
233 switch (Rounding_mode()) {
234 case ROUNDPLUS:
235 Duint_increment(resultp1,resultp2);
236 break;
237 case ROUNDMINUS: /* never negative */
238 break;
239 case ROUNDNEAREST:
240 if (Sgl_isone_roundbit(src,src_exponent) &&
241 (Sgl_isone_stickybit(src,src_exponent) ||
242 Duint_isone_lowp2(resultp2))) {
243 Duint_increment(resultp1,resultp2);
244 }
245 break;
246 }
247 }
248 } else {
249 Duint_setzero(resultp1,resultp2);
250
251 /* check for inexact */
252 if (Sgl_isnotzero_exponentmantissa(src)) {
253 inexact = TRUE;
254 /* round result */
255 switch (Rounding_mode()) {
256 case ROUNDPLUS:
257 if (Sgl_iszero_sign(src)) {
258 Duint_increment(resultp1,resultp2);
259 }
260 break;
261 case ROUNDMINUS:
262 if (Sgl_isone_sign(src)) {
263 resultp1 = resultp2 = 0;
264 if (Is_invalidtrap_enabled()) {
265 return(INVALIDEXCEPTION);
266 }
267 Set_invalidflag();
268 inexact = FALSE;
269 }
270 break;
271 case ROUNDNEAREST:
272 if (src_exponent == -1 &&
273 Sgl_isnotzero_mantissa(src)) {
274 if (Sgl_isone_sign(src)) {
275 resultp1 = 0;
276 resultp2 = 0;
277 if (Is_invalidtrap_enabled()) {
278 return(INVALIDEXCEPTION);
279 }
280 Set_invalidflag();
281 inexact = FALSE;
282 }
283 else Duint_increment(resultp1,resultp2);
284 }
285 }
286 }
287 }
288 Duint_copytoptr(resultp1,resultp2,dstptr);
289 if (inexact) {
290 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
291 else Set_inexactflag();
292 }
293 return(NOEXCEPTION);
294}
295
296/*
297 * Double Floating-point to Single Unsigned Fixed
298 */
299/*ARGSUSED*/
300int
301dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
302 unsigned int *dstptr, unsigned int *status)
303{
304 register unsigned int srcp1, srcp2, result;
305 register int src_exponent;
306 register boolean inexact = FALSE;
307
308 Dbl_copyfromptr(srcptr,srcp1,srcp2);
309 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
310
311 /*
312 * Test for overflow
313 */
314 if (src_exponent > SGL_FX_MAX_EXP + 1) {
315 if (Dbl_isone_sign(srcp1)) {
316 result = 0;
317 } else {
318 result = 0xffffffff;
319 }
320 if (Is_invalidtrap_enabled()) {
321 return(INVALIDEXCEPTION);
322 }
323 Set_invalidflag();
324 *dstptr = result;
325 return(NOEXCEPTION);
326 }
327 /*
328 * Generate result
329 */
330 if (src_exponent >= 0) {
331 /*
332 * Check sign.
333 * If negative, trap unimplemented.
334 */
335 if (Dbl_isone_sign(srcp1)) {
336 result = 0;
337 if (Is_invalidtrap_enabled()) {
338 return(INVALIDEXCEPTION);
339 }
340 Set_invalidflag();
341 *dstptr = result;
342 return(NOEXCEPTION);
343 }
344 Dbl_clear_signexponent_set_hidden(srcp1);
345 Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
346
347 /* check for inexact */
348 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
349 inexact = TRUE;
350 /* round result */
351 switch (Rounding_mode()) {
352 case ROUNDPLUS:
353 result++;
354 break;
355 case ROUNDMINUS: /* never negative */
356 break;
357 case ROUNDNEAREST:
358 if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
359 (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
360 result&1))
361 result++;
362 break;
363 }
364 /* check for overflow */
365 if (result == 0) {
366 result = 0xffffffff;
367 if (Is_invalidtrap_enabled()) {
368 return(INVALIDEXCEPTION);
369 }
370 Set_invalidflag();
371 *dstptr = result;
372 return(NOEXCEPTION);
373 }
374 }
375 } else {
376 result = 0;
377
378 /* check for inexact */
379 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
380 inexact = TRUE;
381 /* round result */
382 switch (Rounding_mode()) {
383 case ROUNDPLUS:
384 if (Dbl_iszero_sign(srcp1)) result++;
385 break;
386 case ROUNDMINUS:
387 if (Dbl_isone_sign(srcp1)) {
388 result = 0;
389 if (Is_invalidtrap_enabled()) {
390 return(INVALIDEXCEPTION);
391 }
392 Set_invalidflag();
393 inexact = FALSE;
394 }
395 break;
396 case ROUNDNEAREST:
397 if (src_exponent == -1 &&
398 Dbl_isnotzero_mantissa(srcp1,srcp2))
399 if (Dbl_isone_sign(srcp1)) {
400 result = 0;
401 if (Is_invalidtrap_enabled()) {
402 return(INVALIDEXCEPTION);
403 }
404 Set_invalidflag();
405 inexact = FALSE;
406 }
407 else result++;
408 }
409 }
410 }
411 *dstptr = result;
412 if (inexact) {
413 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
414 else Set_inexactflag();
415 }
416 return(NOEXCEPTION);
417}
418
419/*
420 * Double Floating-point to Double Unsigned Fixed
421 */
422/*ARGSUSED*/
423int
424dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
425 dbl_unsigned * dstptr, unsigned int *status)
426{
427 register int src_exponent;
428 register unsigned int srcp1, srcp2, resultp1, resultp2;
429 register boolean inexact = FALSE;
430
431 Dbl_copyfromptr(srcptr,srcp1,srcp2);
432 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
433
434 /*
435 * Test for overflow
436 */
437 if (src_exponent > DBL_FX_MAX_EXP + 1) {
438 if (Dbl_isone_sign(srcp1)) {
439 resultp1 = resultp2 = 0;
440 } else {
441 resultp1 = resultp2 = 0xffffffff;
442 }
443 if (Is_invalidtrap_enabled()) {
444 return(INVALIDEXCEPTION);
445 }
446 Set_invalidflag();
447 Duint_copytoptr(resultp1,resultp2,dstptr);
448 return(NOEXCEPTION);
449 }
450
451 /*
452 * Generate result
453 */
454 if (src_exponent >= 0) {
455 /*
456 * Check sign.
457 * If negative, trap unimplemented.
458 */
459 if (Dbl_isone_sign(srcp1)) {
460 resultp1 = resultp2 = 0;
461 if (Is_invalidtrap_enabled()) {
462 return(INVALIDEXCEPTION);
463 }
464 Set_invalidflag();
465 Duint_copytoptr(resultp1,resultp2,dstptr);
466 return(NOEXCEPTION);
467 }
468 Dbl_clear_signexponent_set_hidden(srcp1);
469 Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
470 resultp2);
471
472 /* check for inexact */
473 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
474 inexact = TRUE;
475 /* round result */
476 switch (Rounding_mode()) {
477 case ROUNDPLUS:
478 Duint_increment(resultp1,resultp2);
479 break;
480 case ROUNDMINUS: /* never negative */
481 break;
482 case ROUNDNEAREST:
483 if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
484 if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
485 Duint_isone_lowp2(resultp2))
486 Duint_increment(resultp1,resultp2);
487 }
488 }
489 } else {
490 Duint_setzero(resultp1,resultp2);
491
492 /* check for inexact */
493 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
494 inexact = TRUE;
495 /* round result */
496 switch (Rounding_mode()) {
497 case ROUNDPLUS:
498 if (Dbl_iszero_sign(srcp1)) {
499 Duint_increment(resultp1,resultp2);
500 }
501 break;
502 case ROUNDMINUS:
503 if (Dbl_isone_sign(srcp1)) {
504 resultp1 = resultp2 = 0;
505 if (Is_invalidtrap_enabled()) {
506 return(INVALIDEXCEPTION);
507 }
508 Set_invalidflag();
509 inexact = FALSE;
510 }
511 break;
512 case ROUNDNEAREST:
513 if (src_exponent == -1 &&
514 Dbl_isnotzero_mantissa(srcp1,srcp2))
515 if (Dbl_iszero_sign(srcp1)) {
516 Duint_increment(resultp1,resultp2);
517 } else {
518 resultp1 = 0;
519 resultp2 = 0;
520 if (Is_invalidtrap_enabled()) {
521 return(INVALIDEXCEPTION);
522 }
523 Set_invalidflag();
524 inexact = FALSE;
525 }
526 }
527 }
528 }
529 Duint_copytoptr(resultp1,resultp2,dstptr);
530 if (inexact) {
531 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
532 else Set_inexactflag();
533 }
534 return(NOEXCEPTION);
535}
536
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fcnvfut.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Floating-point to Unsigned Fixed-point Converts with Truncation
29 *
30 * External Interfaces:
31 * dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
32 * dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
33 * sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
34 * sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
35 *
36 * Internal Interfaces:
37 *
38 * Theory:
39 * <<please update with a overview of the operation of this file>>
40 *
41 * END_DESC
42*/
43
44
45#include "float.h"
46#include "sgl_float.h"
47#include "dbl_float.h"
48#include "cnv_float.h"
49
50/************************************************************************
51 * Floating-point to Unsigned Fixed-point Converts with Truncation *
52 ************************************************************************/
53
54/*
55 * Convert single floating-point to single fixed-point format
56 * with truncated result
57 */
58/*ARGSUSED*/
59int
60sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
61 unsigned int *dstptr, unsigned int *status)
62{
63 register unsigned int src, result;
64 register int src_exponent;
65
66 src = *srcptr;
67 src_exponent = Sgl_exponent(src) - SGL_BIAS;
68
69 /*
70 * Test for overflow
71 */
72 if (src_exponent > SGL_FX_MAX_EXP + 1) {
73 if (Sgl_isone_sign(src)) {
74 result = 0;
75 } else {
76 result = 0xffffffff;
77 }
78 if (Is_invalidtrap_enabled()) {
79 return(INVALIDEXCEPTION);
80 }
81 Set_invalidflag();
82 *dstptr = result;
83 return(NOEXCEPTION);
84 }
85 /*
86 * Generate result
87 */
88 if (src_exponent >= 0) {
89 /*
90 * Check sign.
91 * If negative, trap unimplemented.
92 */
93 if (Sgl_isone_sign(src)) {
94 result = 0;
95 if (Is_invalidtrap_enabled()) {
96 return(INVALIDEXCEPTION);
97 }
98 Set_invalidflag();
99 *dstptr = result;
100 return(NOEXCEPTION);
101 }
102 Sgl_clear_signexponent_set_hidden(src);
103 Suint_from_sgl_mantissa(src,src_exponent,result);
104 *dstptr = result;
105
106 /* check for inexact */
107 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
108 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
109 else Set_inexactflag();
110 }
111 }
112 else {
113 *dstptr = 0;
114
115 /* check for inexact */
116 if (Sgl_isnotzero_exponentmantissa(src)) {
117 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
118 else Set_inexactflag();
119 }
120 }
121 return(NOEXCEPTION);
122}
123
124/*
125 * Single Floating-point to Double Unsigned Fixed
126 */
127/*ARGSUSED*/
128int
129sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
130 dbl_unsigned * dstptr, unsigned int *status)
131{
132 register int src_exponent;
133 register unsigned int src, resultp1, resultp2;
134
135 src = *srcptr;
136 src_exponent = Sgl_exponent(src) - SGL_BIAS;
137
138 /*
139 * Test for overflow
140 */
141 if (src_exponent > DBL_FX_MAX_EXP + 1) {
142 if (Sgl_isone_sign(src)) {
143 resultp1 = resultp2 = 0;
144 } else {
145 resultp1 = resultp2 = 0xffffffff;
146 }
147 if (Is_invalidtrap_enabled()) {
148 return(INVALIDEXCEPTION);
149 }
150 Set_invalidflag();
151 Duint_copytoptr(resultp1,resultp2,dstptr);
152 return(NOEXCEPTION);
153 }
154 /*
155 * Generate result
156 */
157 if (src_exponent >= 0) {
158 /*
159 * Check sign.
160 * If negative, trap unimplemented.
161 */
162 if (Sgl_isone_sign(src)) {
163 resultp1 = resultp2 = 0;
164 if (Is_invalidtrap_enabled()) {
165 return(INVALIDEXCEPTION);
166 }
167 Set_invalidflag();
168 Duint_copytoptr(resultp1,resultp2,dstptr);
169 return(NOEXCEPTION);
170 }
171 Sgl_clear_signexponent_set_hidden(src);
172 Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
173 Duint_copytoptr(resultp1,resultp2,dstptr);
174
175 /* check for inexact */
176 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
177 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
178 else Set_inexactflag();
179 }
180 }
181 else {
182 Duint_setzero(resultp1,resultp2);
183 Duint_copytoptr(resultp1,resultp2,dstptr);
184
185 /* check for inexact */
186 if (Sgl_isnotzero_exponentmantissa(src)) {
187 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
188 else Set_inexactflag();
189 }
190 }
191 return(NOEXCEPTION);
192}
193
194/*
195 * Double Floating-point to Single Unsigned Fixed
196 */
197/*ARGSUSED*/
198int
199dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
200 unsigned int *dstptr, unsigned int *status)
201{
202 register unsigned int srcp1, srcp2, result;
203 register int src_exponent;
204
205 Dbl_copyfromptr(srcptr,srcp1,srcp2);
206 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
207
208 /*
209 * Test for overflow
210 */
211 if (src_exponent > SGL_FX_MAX_EXP + 1) {
212 if (Dbl_isone_sign(srcp1)) {
213 result = 0;
214 } else {
215 result = 0xffffffff;
216 }
217 if (Is_invalidtrap_enabled()) {
218 return(INVALIDEXCEPTION);
219 }
220 Set_invalidflag();
221 *dstptr = result;
222 return(NOEXCEPTION);
223 }
224 /*
225 * Generate result
226 */
227 if (src_exponent >= 0) {
228 /*
229 * Check sign.
230 * If negative, trap unimplemented.
231 */
232 if (Dbl_isone_sign(srcp1)) {
233 result = 0;
234 if (Is_invalidtrap_enabled()) {
235 return(INVALIDEXCEPTION);
236 }
237 Set_invalidflag();
238 *dstptr = result;
239 return(NOEXCEPTION);
240 }
241 Dbl_clear_signexponent_set_hidden(srcp1);
242 Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
243 *dstptr = result;
244
245 /* check for inexact */
246 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
247 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
248 else Set_inexactflag();
249 }
250 }
251 else {
252 *dstptr = 0;
253
254 /* check for inexact */
255 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
256 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
257 else Set_inexactflag();
258 }
259 }
260 return(NOEXCEPTION);
261}
262
263/*
264 * Double Floating-point to Double Unsigned Fixed
265 */
266/*ARGSUSED*/
267int
268dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
269 dbl_unsigned * dstptr, unsigned int *status)
270{
271 register int src_exponent;
272 register unsigned int srcp1, srcp2, resultp1, resultp2;
273
274 Dbl_copyfromptr(srcptr,srcp1,srcp2);
275 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
276
277 /*
278 * Test for overflow
279 */
280 if (src_exponent > DBL_FX_MAX_EXP + 1) {
281 if (Dbl_isone_sign(srcp1)) {
282 resultp1 = resultp2 = 0;
283 } else {
284 resultp1 = resultp2 = 0xffffffff;
285 }
286 if (Is_invalidtrap_enabled()) {
287 return(INVALIDEXCEPTION);
288 }
289 Set_invalidflag();
290 Duint_copytoptr(resultp1,resultp2,dstptr);
291 return(NOEXCEPTION);
292 }
293 /*
294 * Generate result
295 */
296 if (src_exponent >= 0) {
297 /*
298 * Check sign.
299 * If negative, trap unimplemented.
300 */
301 if (Dbl_isone_sign(srcp1)) {
302 resultp1 = resultp2 = 0;
303 if (Is_invalidtrap_enabled()) {
304 return(INVALIDEXCEPTION);
305 }
306 Set_invalidflag();
307 Duint_copytoptr(resultp1,resultp2,dstptr);
308 return(NOEXCEPTION);
309 }
310 Dbl_clear_signexponent_set_hidden(srcp1);
311 Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,
312 resultp1,resultp2);
313 Duint_copytoptr(resultp1,resultp2,dstptr);
314
315 /* check for inexact */
316 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
317 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
318 else Set_inexactflag();
319 }
320 }
321 else {
322 Duint_setzero(resultp1,resultp2);
323 Duint_copytoptr(resultp1,resultp2,dstptr);
324
325 /* check for inexact */
326 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
327 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
328 else Set_inexactflag();
329 }
330 }
331 return(NOEXCEPTION);
332}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single Floating-point to Single Fixed-point
29 * Single Floating-point to Double Fixed-point
30 * Double Floating-point to Single Fixed-point
31 * Double Floating-point to Double Fixed-point
32 *
33 * External Interfaces:
34 * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
35 * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
36 * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
37 * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
38 *
39 * Internal Interfaces:
40 *
41 * Theory:
42 * <<please update with a overview of the operation of this file>>
43 *
44 * END_DESC
45*/
46
47
48#include "float.h"
49#include "sgl_float.h"
50#include "dbl_float.h"
51#include "cnv_float.h"
52
53/*
54 * Single Floating-point to Single Fixed-point
55 */
56/*ARGSUSED*/
57int
58sgl_to_sgl_fcnvfx(
59 sgl_floating_point *srcptr,
60 sgl_floating_point *nullptr,
61 int *dstptr,
62 sgl_floating_point *status)
63{
64 register unsigned int src, temp;
65 register int src_exponent, result;
66 register boolean inexact = FALSE;
67
68 src = *srcptr;
69 src_exponent = Sgl_exponent(src) - SGL_BIAS;
70
71 /*
72 * Test for overflow
73 */
74 if (src_exponent > SGL_FX_MAX_EXP) {
75 /* check for MININT */
76 if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
77 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
78 if (Sgl_iszero_sign(src)) result = 0x7fffffff;
79 else result = 0x80000000;
80
81 if (Is_invalidtrap_enabled()) {
82 return(INVALIDEXCEPTION);
83 }
84 Set_invalidflag();
85 *dstptr = result;
86 return(NOEXCEPTION);
87 }
88 }
89 /*
90 * Generate result
91 */
92 if (src_exponent >= 0) {
93 temp = src;
94 Sgl_clear_signexponent_set_hidden(temp);
95 Int_from_sgl_mantissa(temp,src_exponent);
96 if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
97 else result = Sgl_all(temp);
98
99 /* check for inexact */
100 if (Sgl_isinexact_to_fix(src,src_exponent)) {
101 inexact = TRUE;
102 /* round result */
103 switch (Rounding_mode()) {
104 case ROUNDPLUS:
105 if (Sgl_iszero_sign(src)) result++;
106 break;
107 case ROUNDMINUS:
108 if (Sgl_isone_sign(src)) result--;
109 break;
110 case ROUNDNEAREST:
111 if (Sgl_isone_roundbit(src,src_exponent)) {
112 if (Sgl_isone_stickybit(src,src_exponent)
113 || (Sgl_isone_lowmantissa(temp)))
114 if (Sgl_iszero_sign(src)) result++;
115 else result--;
116 }
117 }
118 }
119 }
120 else {
121 result = 0;
122
123 /* check for inexact */
124 if (Sgl_isnotzero_exponentmantissa(src)) {
125 inexact = TRUE;
126 /* round result */
127 switch (Rounding_mode()) {
128 case ROUNDPLUS:
129 if (Sgl_iszero_sign(src)) result++;
130 break;
131 case ROUNDMINUS:
132 if (Sgl_isone_sign(src)) result--;
133 break;
134 case ROUNDNEAREST:
135 if (src_exponent == -1)
136 if (Sgl_isnotzero_mantissa(src))
137 if (Sgl_iszero_sign(src)) result++;
138 else result--;
139 }
140 }
141 }
142 *dstptr = result;
143 if (inexact) {
144 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
145 else Set_inexactflag();
146 }
147 return(NOEXCEPTION);
148}
149
150/*
151 * Single Floating-point to Double Fixed-point
152 */
153/*ARGSUSED*/
154int
155sgl_to_dbl_fcnvfx(
156 sgl_floating_point *srcptr,
157 unsigned int *nullptr,
158 dbl_integer *dstptr,
159 unsigned int *status)
160{
161 register int src_exponent, resultp1;
162 register unsigned int src, temp, resultp2;
163 register boolean inexact = FALSE;
164
165 src = *srcptr;
166 src_exponent = Sgl_exponent(src) - SGL_BIAS;
167
168 /*
169 * Test for overflow
170 */
171 if (src_exponent > DBL_FX_MAX_EXP) {
172 /* check for MININT */
173 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
174 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
175 if (Sgl_iszero_sign(src)) {
176 resultp1 = 0x7fffffff;
177 resultp2 = 0xffffffff;
178 }
179 else {
180 resultp1 = 0x80000000;
181 resultp2 = 0;
182 }
183 if (Is_invalidtrap_enabled()) {
184 return(INVALIDEXCEPTION);
185 }
186 Set_invalidflag();
187 Dint_copytoptr(resultp1,resultp2,dstptr);
188 return(NOEXCEPTION);
189 }
190 Dint_set_minint(resultp1,resultp2);
191 Dint_copytoptr(resultp1,resultp2,dstptr);
192 return(NOEXCEPTION);
193 }
194 /*
195 * Generate result
196 */
197 if (src_exponent >= 0) {
198 temp = src;
199 Sgl_clear_signexponent_set_hidden(temp);
200 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
201 if (Sgl_isone_sign(src)) {
202 Dint_setone_sign(resultp1,resultp2);
203 }
204
205 /* check for inexact */
206 if (Sgl_isinexact_to_fix(src,src_exponent)) {
207 inexact = TRUE;
208 /* round result */
209 switch (Rounding_mode()) {
210 case ROUNDPLUS:
211 if (Sgl_iszero_sign(src)) {
212 Dint_increment(resultp1,resultp2);
213 }
214 break;
215 case ROUNDMINUS:
216 if (Sgl_isone_sign(src)) {
217 Dint_decrement(resultp1,resultp2);
218 }
219 break;
220 case ROUNDNEAREST:
221 if (Sgl_isone_roundbit(src,src_exponent))
222 if (Sgl_isone_stickybit(src,src_exponent) ||
223 (Dint_isone_lowp2(resultp2)))
224 if (Sgl_iszero_sign(src)) {
225 Dint_increment(resultp1,resultp2);
226 }
227 else {
228 Dint_decrement(resultp1,resultp2);
229 }
230 }
231 }
232 }
233 else {
234 Dint_setzero(resultp1,resultp2);
235
236 /* check for inexact */
237 if (Sgl_isnotzero_exponentmantissa(src)) {
238 inexact = TRUE;
239 /* round result */
240 switch (Rounding_mode()) {
241 case ROUNDPLUS:
242 if (Sgl_iszero_sign(src)) {
243 Dint_increment(resultp1,resultp2);
244 }
245 break;
246 case ROUNDMINUS:
247 if (Sgl_isone_sign(src)) {
248 Dint_decrement(resultp1,resultp2);
249 }
250 break;
251 case ROUNDNEAREST:
252 if (src_exponent == -1)
253 if (Sgl_isnotzero_mantissa(src))
254 if (Sgl_iszero_sign(src)) {
255 Dint_increment(resultp1,resultp2);
256 }
257 else {
258 Dint_decrement(resultp1,resultp2);
259 }
260 }
261 }
262 }
263 Dint_copytoptr(resultp1,resultp2,dstptr);
264 if (inexact) {
265 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
266 else Set_inexactflag();
267 }
268 return(NOEXCEPTION);
269}
270
271/*
272 * Double Floating-point to Single Fixed-point
273 */
274/*ARGSUSED*/
275int
276dbl_to_sgl_fcnvfx(
277 dbl_floating_point *srcptr,
278 unsigned int *nullptr,
279 int *dstptr,
280 unsigned int *status)
281{
282 register unsigned int srcp1,srcp2, tempp1,tempp2;
283 register int src_exponent, result;
284 register boolean inexact = FALSE;
285
286 Dbl_copyfromptr(srcptr,srcp1,srcp2);
287 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
288
289 /*
290 * Test for overflow
291 */
292 if (src_exponent > SGL_FX_MAX_EXP) {
293 /* check for MININT */
294 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
295 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
296 else result = 0x80000000;
297
298 if (Is_invalidtrap_enabled()) {
299 return(INVALIDEXCEPTION);
300 }
301 Set_invalidflag();
302 *dstptr = result;
303 return(NOEXCEPTION);
304 }
305 }
306 /*
307 * Generate result
308 */
309 if (src_exponent >= 0) {
310 tempp1 = srcp1;
311 tempp2 = srcp2;
312 Dbl_clear_signexponent_set_hidden(tempp1);
313 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
314 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
315 result = -Dbl_allp1(tempp1);
316 else result = Dbl_allp1(tempp1);
317
318 /* check for inexact */
319 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
320 inexact = TRUE;
321 /* round result */
322 switch (Rounding_mode()) {
323 case ROUNDPLUS:
324 if (Dbl_iszero_sign(srcp1)) result++;
325 break;
326 case ROUNDMINUS:
327 if (Dbl_isone_sign(srcp1)) result--;
328 break;
329 case ROUNDNEAREST:
330 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
331 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
332 (Dbl_isone_lowmantissap1(tempp1)))
333 if (Dbl_iszero_sign(srcp1)) result++;
334 else result--;
335 }
336 /* check for overflow */
337 if ((Dbl_iszero_sign(srcp1) && result < 0) ||
338 (Dbl_isone_sign(srcp1) && result > 0)) {
339
340 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
341 else result = 0x80000000;
342
343 if (Is_invalidtrap_enabled()) {
344 return(INVALIDEXCEPTION);
345 }
346 Set_invalidflag();
347 *dstptr = result;
348 return(NOEXCEPTION);
349 }
350 }
351 }
352 else {
353 result = 0;
354
355 /* check for inexact */
356 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
357 inexact = TRUE;
358 /* round result */
359 switch (Rounding_mode()) {
360 case ROUNDPLUS:
361 if (Dbl_iszero_sign(srcp1)) result++;
362 break;
363 case ROUNDMINUS:
364 if (Dbl_isone_sign(srcp1)) result--;
365 break;
366 case ROUNDNEAREST:
367 if (src_exponent == -1)
368 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
369 if (Dbl_iszero_sign(srcp1)) result++;
370 else result--;
371 }
372 }
373 }
374 *dstptr = result;
375 if (inexact) {
376 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
377 else Set_inexactflag();
378 }
379 return(NOEXCEPTION);
380}
381
382/*
383 * Double Floating-point to Double Fixed-point
384 */
385/*ARGSUSED*/
386int
387dbl_to_dbl_fcnvfx(
388 dbl_floating_point *srcptr,
389 unsigned int *nullptr,
390 dbl_integer *dstptr,
391 unsigned int *status)
392{
393 register int src_exponent, resultp1;
394 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
395 register boolean inexact = FALSE;
396
397 Dbl_copyfromptr(srcptr,srcp1,srcp2);
398 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
399
400 /*
401 * Test for overflow
402 */
403 if (src_exponent > DBL_FX_MAX_EXP) {
404 /* check for MININT */
405 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
406 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
407 if (Dbl_iszero_sign(srcp1)) {
408 resultp1 = 0x7fffffff;
409 resultp2 = 0xffffffff;
410 }
411 else {
412 resultp1 = 0x80000000;
413 resultp2 = 0;
414 }
415 if (Is_invalidtrap_enabled()) {
416 return(INVALIDEXCEPTION);
417 }
418 Set_invalidflag();
419 Dint_copytoptr(resultp1,resultp2,dstptr);
420 return(NOEXCEPTION);
421 }
422 }
423
424 /*
425 * Generate result
426 */
427 if (src_exponent >= 0) {
428 tempp1 = srcp1;
429 tempp2 = srcp2;
430 Dbl_clear_signexponent_set_hidden(tempp1);
431 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
432 resultp2);
433 if (Dbl_isone_sign(srcp1)) {
434 Dint_setone_sign(resultp1,resultp2);
435 }
436
437 /* check for inexact */
438 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
439 inexact = TRUE;
440 /* round result */
441 switch (Rounding_mode()) {
442 case ROUNDPLUS:
443 if (Dbl_iszero_sign(srcp1)) {
444 Dint_increment(resultp1,resultp2);
445 }
446 break;
447 case ROUNDMINUS:
448 if (Dbl_isone_sign(srcp1)) {
449 Dint_decrement(resultp1,resultp2);
450 }
451 break;
452 case ROUNDNEAREST:
453 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
454 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
455 (Dint_isone_lowp2(resultp2)))
456 if (Dbl_iszero_sign(srcp1)) {
457 Dint_increment(resultp1,resultp2);
458 }
459 else {
460 Dint_decrement(resultp1,resultp2);
461 }
462 }
463 }
464 }
465 else {
466 Dint_setzero(resultp1,resultp2);
467
468 /* check for inexact */
469 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
470 inexact = TRUE;
471 /* round result */
472 switch (Rounding_mode()) {
473 case ROUNDPLUS:
474 if (Dbl_iszero_sign(srcp1)) {
475 Dint_increment(resultp1,resultp2);
476 }
477 break;
478 case ROUNDMINUS:
479 if (Dbl_isone_sign(srcp1)) {
480 Dint_decrement(resultp1,resultp2);
481 }
482 break;
483 case ROUNDNEAREST:
484 if (src_exponent == -1)
485 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
486 if (Dbl_iszero_sign(srcp1)) {
487 Dint_increment(resultp1,resultp2);
488 }
489 else {
490 Dint_decrement(resultp1,resultp2);
491 }
492 }
493 }
494 }
495 Dint_copytoptr(resultp1,resultp2,dstptr);
496 if (inexact) {
497 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
498 else Set_inexactflag();
499 }
500 return(NOEXCEPTION);
501}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fcnvfxt.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single Floating-point to Single Fixed-point /w truncated result
29 * Single Floating-point to Double Fixed-point /w truncated result
30 * Double Floating-point to Single Fixed-point /w truncated result
31 * Double Floating-point to Double Fixed-point /w truncated result
32 *
33 * External Interfaces:
34 * dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
35 * dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
36 * sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
37 * sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
38 *
39 * Internal Interfaces:
40 *
41 * Theory:
42 * <<please update with a overview of the operation of this file>>
43 *
44 * END_DESC
45*/
46
47
48#include "float.h"
49#include "sgl_float.h"
50#include "dbl_float.h"
51#include "cnv_float.h"
52
53/*
54 * Convert single floating-point to single fixed-point format
55 * with truncated result
56 */
57/*ARGSUSED*/
58int
59sgl_to_sgl_fcnvfxt(
60 sgl_floating_point *srcptr,
61 unsigned int *nullptr,
62 int *dstptr,
63 unsigned int *status)
64{
65 register unsigned int src, temp;
66 register int src_exponent, result;
67
68 src = *srcptr;
69 src_exponent = Sgl_exponent(src) - SGL_BIAS;
70
71 /*
72 * Test for overflow
73 */
74 if (src_exponent > SGL_FX_MAX_EXP) {
75 /* check for MININT */
76 if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
77 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
78 if (Sgl_iszero_sign(src)) result = 0x7fffffff;
79 else result = 0x80000000;
80
81 if (Is_invalidtrap_enabled()) {
82 return(INVALIDEXCEPTION);
83 }
84 Set_invalidflag();
85 *dstptr = result;
86 return(NOEXCEPTION);
87 }
88 }
89 /*
90 * Generate result
91 */
92 if (src_exponent >= 0) {
93 temp = src;
94 Sgl_clear_signexponent_set_hidden(temp);
95 Int_from_sgl_mantissa(temp,src_exponent);
96 if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
97 else result = Sgl_all(temp);
98 *dstptr = result;
99
100 /* check for inexact */
101 if (Sgl_isinexact_to_fix(src,src_exponent)) {
102 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
103 else Set_inexactflag();
104 }
105 }
106 else {
107 *dstptr = 0;
108
109 /* check for inexact */
110 if (Sgl_isnotzero_exponentmantissa(src)) {
111 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
112 else Set_inexactflag();
113 }
114 }
115 return(NOEXCEPTION);
116}
117
118/*
119 * Single Floating-point to Double Fixed-point
120 */
121/*ARGSUSED*/
122int
123sgl_to_dbl_fcnvfxt(
124 sgl_floating_point *srcptr,
125 unsigned int *nullptr,
126 dbl_integer *dstptr,
127 unsigned int *status)
128{
129 register int src_exponent, resultp1;
130 register unsigned int src, temp, resultp2;
131
132 src = *srcptr;
133 src_exponent = Sgl_exponent(src) - SGL_BIAS;
134
135 /*
136 * Test for overflow
137 */
138 if (src_exponent > DBL_FX_MAX_EXP) {
139 /* check for MININT */
140 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
141 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
142 if (Sgl_iszero_sign(src)) {
143 resultp1 = 0x7fffffff;
144 resultp2 = 0xffffffff;
145 }
146 else {
147 resultp1 = 0x80000000;
148 resultp2 = 0;
149 }
150 if (Is_invalidtrap_enabled()) {
151 return(INVALIDEXCEPTION);
152 }
153 Set_invalidflag();
154 Dint_copytoptr(resultp1,resultp2,dstptr);
155 return(NOEXCEPTION);
156 }
157 Dint_set_minint(resultp1,resultp2);
158 Dint_copytoptr(resultp1,resultp2,dstptr);
159 return(NOEXCEPTION);
160 }
161 /*
162 * Generate result
163 */
164 if (src_exponent >= 0) {
165 temp = src;
166 Sgl_clear_signexponent_set_hidden(temp);
167 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
168 if (Sgl_isone_sign(src)) {
169 Dint_setone_sign(resultp1,resultp2);
170 }
171 Dint_copytoptr(resultp1,resultp2,dstptr);
172
173 /* check for inexact */
174 if (Sgl_isinexact_to_fix(src,src_exponent)) {
175 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
176 else Set_inexactflag();
177 }
178 }
179 else {
180 Dint_setzero(resultp1,resultp2);
181 Dint_copytoptr(resultp1,resultp2,dstptr);
182
183 /* check for inexact */
184 if (Sgl_isnotzero_exponentmantissa(src)) {
185 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
186 else Set_inexactflag();
187 }
188 }
189 return(NOEXCEPTION);
190}
191
192/*
193 * Double Floating-point to Single Fixed-point
194 */
195/*ARGSUSED*/
196int
197dbl_to_sgl_fcnvfxt(
198 dbl_floating_point *srcptr,
199 unsigned int *nullptr,
200 int *dstptr,
201 unsigned int *status)
202{
203 register unsigned int srcp1, srcp2, tempp1, tempp2;
204 register int src_exponent, result;
205
206 Dbl_copyfromptr(srcptr,srcp1,srcp2);
207 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
208
209 /*
210 * Test for overflow
211 */
212 if (src_exponent > SGL_FX_MAX_EXP) {
213 /* check for MININT */
214 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
215 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
216 else result = 0x80000000;
217
218 if (Is_invalidtrap_enabled()) {
219 return(INVALIDEXCEPTION);
220 }
221 Set_invalidflag();
222 *dstptr = result;
223 return(NOEXCEPTION);
224 }
225 }
226 /*
227 * Generate result
228 */
229 if (src_exponent >= 0) {
230 tempp1 = srcp1;
231 tempp2 = srcp2;
232 Dbl_clear_signexponent_set_hidden(tempp1);
233 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
234 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
235 result = -Dbl_allp1(tempp1);
236 else result = Dbl_allp1(tempp1);
237 *dstptr = result;
238
239 /* check for inexact */
240 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
241 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
242 else Set_inexactflag();
243 }
244 }
245 else {
246 *dstptr = 0;
247
248 /* check for inexact */
249 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
250 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
251 else Set_inexactflag();
252 }
253 }
254 return(NOEXCEPTION);
255}
256
257/*
258 * Double Floating-point to Double Fixed-point
259 */
260/*ARGSUSED*/
261int
262dbl_to_dbl_fcnvfxt(
263 dbl_floating_point *srcptr,
264 unsigned int *nullptr,
265 dbl_integer *dstptr,
266 unsigned int *status)
267{
268 register int src_exponent, resultp1;
269 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
270
271 Dbl_copyfromptr(srcptr,srcp1,srcp2);
272 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
273
274 /*
275 * Test for overflow
276 */
277 if (src_exponent > DBL_FX_MAX_EXP) {
278 /* check for MININT */
279 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
280 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
281 if (Dbl_iszero_sign(srcp1)) {
282 resultp1 = 0x7fffffff;
283 resultp2 = 0xffffffff;
284 }
285 else {
286 resultp1 = 0x80000000;
287 resultp2 = 0;
288 }
289 if (Is_invalidtrap_enabled()) {
290 return(INVALIDEXCEPTION);
291 }
292 Set_invalidflag();
293 Dint_copytoptr(resultp1,resultp2,dstptr);
294 return(NOEXCEPTION);
295 }
296 }
297 /*
298 * Generate result
299 */
300 if (src_exponent >= 0) {
301 tempp1 = srcp1;
302 tempp2 = srcp2;
303 Dbl_clear_signexponent_set_hidden(tempp1);
304 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
305 resultp1,resultp2);
306 if (Dbl_isone_sign(srcp1)) {
307 Dint_setone_sign(resultp1,resultp2);
308 }
309 Dint_copytoptr(resultp1,resultp2,dstptr);
310
311 /* check for inexact */
312 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
313 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
314 else Set_inexactflag();
315 }
316 }
317 else {
318 Dint_setzero(resultp1,resultp2);
319 Dint_copytoptr(resultp1,resultp2,dstptr);
320
321 /* check for inexact */
322 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
323 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
324 else Set_inexactflag();
325 }
326 }
327 return(NOEXCEPTION);
328}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fcnvuf.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Fixed point to Floating-point Converts
29 *
30 * External Interfaces:
31 * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
32 * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
33 * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
34 * sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
35 *
36 * Internal Interfaces:
37 *
38 * Theory:
39 * <<please update with a overview of the operation of this file>>
40 *
41 * END_DESC
42*/
43
44
45#include "float.h"
46#include "sgl_float.h"
47#include "dbl_float.h"
48#include "cnv_float.h"
49
50/************************************************************************
51 * Fixed point to Floating-point Converts *
52 ************************************************************************/
53
54/*
55 * Convert Single Unsigned Fixed to Single Floating-point format
56 */
57
58int
59sgl_to_sgl_fcnvuf(
60 unsigned int *srcptr,
61 unsigned int *nullptr,
62 sgl_floating_point *dstptr,
63 unsigned int *status)
64{
65 register unsigned int src, result = 0;
66 register int dst_exponent;
67
68 src = *srcptr;
69
70 /* Check for zero */
71 if (src == 0) {
72 Sgl_setzero(result);
73 *dstptr = result;
74 return(NOEXCEPTION);
75 }
76 /*
77 * Generate exponent and normalized mantissa
78 */
79 dst_exponent = 16; /* initialize for normalization */
80 /*
81 * Check word for most significant bit set. Returns
82 * a value in dst_exponent indicating the bit position,
83 * between -1 and 30.
84 */
85 Find_ms_one_bit(src,dst_exponent);
86 /* left justify source, with msb at bit position 0 */
87 src <<= dst_exponent+1;
88 Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH);
89 Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
90
91 /* check for inexact */
92 if (Suint_isinexact_to_sgl(src)) {
93 switch (Rounding_mode()) {
94 case ROUNDPLUS:
95 Sgl_increment(result);
96 break;
97 case ROUNDMINUS: /* never negative */
98 break;
99 case ROUNDNEAREST:
100 Sgl_roundnearest_from_suint(src,result);
101 break;
102 }
103 if (Is_inexacttrap_enabled()) {
104 *dstptr = result;
105 return(INEXACTEXCEPTION);
106 }
107 else Set_inexactflag();
108 }
109 *dstptr = result;
110 return(NOEXCEPTION);
111}
112
113/*
114 * Single Unsigned Fixed to Double Floating-point
115 */
116
117int
118sgl_to_dbl_fcnvuf(
119 unsigned int *srcptr,
120 unsigned int *nullptr,
121 dbl_floating_point *dstptr,
122 unsigned int *status)
123{
124 register int dst_exponent;
125 register unsigned int src, resultp1 = 0, resultp2 = 0;
126
127 src = *srcptr;
128
129 /* Check for zero */
130 if (src == 0) {
131 Dbl_setzero(resultp1,resultp2);
132 Dbl_copytoptr(resultp1,resultp2,dstptr);
133 return(NOEXCEPTION);
134 }
135 /*
136 * Generate exponent and normalized mantissa
137 */
138 dst_exponent = 16; /* initialize for normalization */
139 /*
140 * Check word for most significant bit set. Returns
141 * a value in dst_exponent indicating the bit position,
142 * between -1 and 30.
143 */
144 Find_ms_one_bit(src,dst_exponent);
145 /* left justify source, with msb at bit position 0 */
146 src <<= dst_exponent+1;
147 Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH);
148 Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH));
149 Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
150 Dbl_copytoptr(resultp1,resultp2,dstptr);
151 return(NOEXCEPTION);
152}
153
154/*
155 * Double Unsigned Fixed to Single Floating-point
156 */
157
158int
159dbl_to_sgl_fcnvuf(
160 dbl_unsigned *srcptr,
161 unsigned int *nullptr,
162 sgl_floating_point *dstptr,
163 unsigned int *status)
164{
165 int dst_exponent;
166 unsigned int srcp1, srcp2, result = 0;
167
168 Duint_copyfromptr(srcptr,srcp1,srcp2);
169
170 /* Check for zero */
171 if (srcp1 == 0 && srcp2 == 0) {
172 Sgl_setzero(result);
173 *dstptr = result;
174 return(NOEXCEPTION);
175 }
176 /*
177 * Generate exponent and normalized mantissa
178 */
179 dst_exponent = 16; /* initialize for normalization */
180 if (srcp1 == 0) {
181 /*
182 * Check word for most significant bit set. Returns
183 * a value in dst_exponent indicating the bit position,
184 * between -1 and 30.
185 */
186 Find_ms_one_bit(srcp2,dst_exponent);
187 /* left justify source, with msb at bit position 0 */
188 srcp1 = srcp2 << dst_exponent+1;
189 srcp2 = 0;
190 /*
191 * since msb set is in second word, need to
192 * adjust bit position count
193 */
194 dst_exponent += 32;
195 }
196 else {
197 /*
198 * Check word for most significant bit set. Returns
199 * a value in dst_exponent indicating the bit position,
200 * between -1 and 30.
201 *
202 */
203 Find_ms_one_bit(srcp1,dst_exponent);
204 /* left justify source, with msb at bit position 0 */
205 if (dst_exponent >= 0) {
206 Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
207 srcp1);
208 srcp2 <<= dst_exponent+1;
209 }
210 }
211 Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH);
212 Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
213
214 /* check for inexact */
215 if (Duint_isinexact_to_sgl(srcp1,srcp2)) {
216 switch (Rounding_mode()) {
217 case ROUNDPLUS:
218 Sgl_increment(result);
219 break;
220 case ROUNDMINUS: /* never negative */
221 break;
222 case ROUNDNEAREST:
223 Sgl_roundnearest_from_duint(srcp1,srcp2,result);
224 break;
225 }
226 if (Is_inexacttrap_enabled()) {
227 *dstptr = result;
228 return(INEXACTEXCEPTION);
229 }
230 else Set_inexactflag();
231 }
232 *dstptr = result;
233 return(NOEXCEPTION);
234}
235
236/*
237 * Double Unsigned Fixed to Double Floating-point
238 */
239
240int
241dbl_to_dbl_fcnvuf(
242 dbl_unsigned *srcptr,
243 unsigned int *nullptr,
244 dbl_floating_point *dstptr,
245 unsigned int *status)
246{
247 register int dst_exponent;
248 register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0;
249
250 Duint_copyfromptr(srcptr,srcp1,srcp2);
251
252 /* Check for zero */
253 if (srcp1 == 0 && srcp2 ==0) {
254 Dbl_setzero(resultp1,resultp2);
255 Dbl_copytoptr(resultp1,resultp2,dstptr);
256 return(NOEXCEPTION);
257 }
258 /*
259 * Generate exponent and normalized mantissa
260 */
261 dst_exponent = 16; /* initialize for normalization */
262 if (srcp1 == 0) {
263 /*
264 * Check word for most significant bit set. Returns
265 * a value in dst_exponent indicating the bit position,
266 * between -1 and 30.
267 */
268 Find_ms_one_bit(srcp2,dst_exponent);
269 /* left justify source, with msb at bit position 0 */
270 srcp1 = srcp2 << dst_exponent+1;
271 srcp2 = 0;
272 /*
273 * since msb set is in second word, need to
274 * adjust bit position count
275 */
276 dst_exponent += 32;
277 }
278 else {
279 /*
280 * Check word for most significant bit set. Returns
281 * a value in dst_exponent indicating the bit position,
282 * between -1 and 30.
283 */
284 Find_ms_one_bit(srcp1,dst_exponent);
285 /* left justify source, with msb at bit position 0 */
286 if (dst_exponent >= 0) {
287 Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
288 srcp1);
289 srcp2 <<= dst_exponent+1;
290 }
291 }
292 Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH);
293 Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2);
294 Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
295
296 /* check for inexact */
297 if (Duint_isinexact_to_dbl(srcp2)) {
298 switch (Rounding_mode()) {
299 case ROUNDPLUS:
300 Dbl_increment(resultp1,resultp2);
301 break;
302 case ROUNDMINUS: /* never negative */
303 break;
304 case ROUNDNEAREST:
305 Dbl_roundnearest_from_duint(srcp2,resultp1,
306 resultp2);
307 break;
308 }
309 if (Is_inexacttrap_enabled()) {
310 Dbl_copytoptr(resultp1,resultp2,dstptr);
311 return(INEXACTEXCEPTION);
312 }
313 else Set_inexactflag();
314 }
315 Dbl_copytoptr(resultp1,resultp2,dstptr);
316 return(NOEXCEPTION);
317}
318
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single Fixed-point to Single Floating-point
29 * Single Fixed-point to Double Floating-point
30 * Double Fixed-point to Single Floating-point
31 * Double Fixed-point to Double Floating-point
32 *
33 * External Interfaces:
34 * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
35 * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
36 * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
37 * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
38 *
39 * Internal Interfaces:
40 *
41 * Theory:
42 * <<please update with a overview of the operation of this file>>
43 *
44 * END_DESC
45*/
46
47
48#include "float.h"
49#include "sgl_float.h"
50#include "dbl_float.h"
51#include "cnv_float.h"
52
53/*
54 * Convert single fixed-point to single floating-point format
55 */
56
57int
58sgl_to_sgl_fcnvxf(
59 int *srcptr,
60 unsigned int *nullptr,
61 sgl_floating_point *dstptr,
62 unsigned int *status)
63{
64 register int src, dst_exponent;
65 register unsigned int result = 0;
66
67 src = *srcptr;
68 /*
69 * set sign bit of result and get magnitude of source
70 */
71 if (src < 0) {
72 Sgl_setone_sign(result);
73 Int_negate(src);
74 }
75 else {
76 Sgl_setzero_sign(result);
77 /* Check for zero */
78 if (src == 0) {
79 Sgl_setzero(result);
80 *dstptr = result;
81 return(NOEXCEPTION);
82 }
83 }
84 /*
85 * Generate exponent and normalized mantissa
86 */
87 dst_exponent = 16; /* initialize for normalization */
88 /*
89 * Check word for most significant bit set. Returns
90 * a value in dst_exponent indicating the bit position,
91 * between -1 and 30.
92 */
93 Find_ms_one_bit(src,dst_exponent);
94 /* left justify source, with msb at bit position 1 */
95 if (dst_exponent >= 0) src <<= dst_exponent;
96 else src = 1 << 30;
97 Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
98 Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
99
100 /* check for inexact */
101 if (Int_isinexact_to_sgl(src)) {
102 switch (Rounding_mode()) {
103 case ROUNDPLUS:
104 if (Sgl_iszero_sign(result))
105 Sgl_increment(result);
106 break;
107 case ROUNDMINUS:
108 if (Sgl_isone_sign(result))
109 Sgl_increment(result);
110 break;
111 case ROUNDNEAREST:
112 Sgl_roundnearest_from_int(src,result);
113 }
114 if (Is_inexacttrap_enabled()) {
115 *dstptr = result;
116 return(INEXACTEXCEPTION);
117 }
118 else Set_inexactflag();
119 }
120 *dstptr = result;
121 return(NOEXCEPTION);
122}
123
124/*
125 * Single Fixed-point to Double Floating-point
126 */
127
128int
129sgl_to_dbl_fcnvxf(
130 int *srcptr,
131 unsigned int *nullptr,
132 dbl_floating_point *dstptr,
133 unsigned int *status)
134{
135 register int src, dst_exponent;
136 register unsigned int resultp1 = 0, resultp2 = 0;
137
138 src = *srcptr;
139 /*
140 * set sign bit of result and get magnitude of source
141 */
142 if (src < 0) {
143 Dbl_setone_sign(resultp1);
144 Int_negate(src);
145 }
146 else {
147 Dbl_setzero_sign(resultp1);
148 /* Check for zero */
149 if (src == 0) {
150 Dbl_setzero(resultp1,resultp2);
151 Dbl_copytoptr(resultp1,resultp2,dstptr);
152 return(NOEXCEPTION);
153 }
154 }
155 /*
156 * Generate exponent and normalized mantissa
157 */
158 dst_exponent = 16; /* initialize for normalization */
159 /*
160 * Check word for most significant bit set. Returns
161 * a value in dst_exponent indicating the bit position,
162 * between -1 and 30.
163 */
164 Find_ms_one_bit(src,dst_exponent);
165 /* left justify source, with msb at bit position 1 */
166 if (dst_exponent >= 0) src <<= dst_exponent;
167 else src = 1 << 30;
168 Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
169 Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
170 Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
171 Dbl_copytoptr(resultp1,resultp2,dstptr);
172 return(NOEXCEPTION);
173}
174
175/*
176 * Double Fixed-point to Single Floating-point
177 */
178
179int
180dbl_to_sgl_fcnvxf(
181 dbl_integer *srcptr,
182 unsigned int *nullptr,
183 sgl_floating_point *dstptr,
184 unsigned int *status)
185{
186 int dst_exponent, srcp1;
187 unsigned int result = 0, srcp2;
188
189 Dint_copyfromptr(srcptr,srcp1,srcp2);
190 /*
191 * set sign bit of result and get magnitude of source
192 */
193 if (srcp1 < 0) {
194 Sgl_setone_sign(result);
195 Dint_negate(srcp1,srcp2);
196 }
197 else {
198 Sgl_setzero_sign(result);
199 /* Check for zero */
200 if (srcp1 == 0 && srcp2 == 0) {
201 Sgl_setzero(result);
202 *dstptr = result;
203 return(NOEXCEPTION);
204 }
205 }
206 /*
207 * Generate exponent and normalized mantissa
208 */
209 dst_exponent = 16; /* initialize for normalization */
210 if (srcp1 == 0) {
211 /*
212 * Check word for most significant bit set. Returns
213 * a value in dst_exponent indicating the bit position,
214 * between -1 and 30.
215 */
216 Find_ms_one_bit(srcp2,dst_exponent);
217 /* left justify source, with msb at bit position 1 */
218 if (dst_exponent >= 0) {
219 srcp1 = srcp2 << dst_exponent;
220 srcp2 = 0;
221 }
222 else {
223 srcp1 = srcp2 >> 1;
224 srcp2 <<= 31;
225 }
226 /*
227 * since msb set is in second word, need to
228 * adjust bit position count
229 */
230 dst_exponent += 32;
231 }
232 else {
233 /*
234 * Check word for most significant bit set. Returns
235 * a value in dst_exponent indicating the bit position,
236 * between -1 and 30.
237 *
238 */
239 Find_ms_one_bit(srcp1,dst_exponent);
240 /* left justify source, with msb at bit position 1 */
241 if (dst_exponent > 0) {
242 Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
243 srcp1);
244 srcp2 <<= dst_exponent;
245 }
246 /*
247 * If dst_exponent = 0, we don't need to shift anything.
248 * If dst_exponent = -1, src = - 2**63 so we won't need to
249 * shift srcp2.
250 */
251 else srcp1 >>= -(dst_exponent);
252 }
253 Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
254 Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
255
256 /* check for inexact */
257 if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
258 switch (Rounding_mode()) {
259 case ROUNDPLUS:
260 if (Sgl_iszero_sign(result))
261 Sgl_increment(result);
262 break;
263 case ROUNDMINUS:
264 if (Sgl_isone_sign(result))
265 Sgl_increment(result);
266 break;
267 case ROUNDNEAREST:
268 Sgl_roundnearest_from_dint(srcp1,srcp2,result);
269 }
270 if (Is_inexacttrap_enabled()) {
271 *dstptr = result;
272 return(INEXACTEXCEPTION);
273 }
274 else Set_inexactflag();
275 }
276 *dstptr = result;
277 return(NOEXCEPTION);
278}
279
280/*
281 * Double Fixed-point to Double Floating-point
282 */
283
284int
285dbl_to_dbl_fcnvxf(
286 dbl_integer *srcptr,
287 unsigned int *nullptr,
288 dbl_floating_point *dstptr,
289 unsigned int *status)
290{
291 register int srcp1, dst_exponent;
292 register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
293
294 Dint_copyfromptr(srcptr,srcp1,srcp2);
295 /*
296 * set sign bit of result and get magnitude of source
297 */
298 if (srcp1 < 0) {
299 Dbl_setone_sign(resultp1);
300 Dint_negate(srcp1,srcp2);
301 }
302 else {
303 Dbl_setzero_sign(resultp1);
304 /* Check for zero */
305 if (srcp1 == 0 && srcp2 ==0) {
306 Dbl_setzero(resultp1,resultp2);
307 Dbl_copytoptr(resultp1,resultp2,dstptr);
308 return(NOEXCEPTION);
309 }
310 }
311 /*
312 * Generate exponent and normalized mantissa
313 */
314 dst_exponent = 16; /* initialize for normalization */
315 if (srcp1 == 0) {
316 /*
317 * Check word for most significant bit set. Returns
318 * a value in dst_exponent indicating the bit position,
319 * between -1 and 30.
320 */
321 Find_ms_one_bit(srcp2,dst_exponent);
322 /* left justify source, with msb at bit position 1 */
323 if (dst_exponent >= 0) {
324 srcp1 = srcp2 << dst_exponent;
325 srcp2 = 0;
326 }
327 else {
328 srcp1 = srcp2 >> 1;
329 srcp2 <<= 31;
330 }
331 /*
332 * since msb set is in second word, need to
333 * adjust bit position count
334 */
335 dst_exponent += 32;
336 }
337 else {
338 /*
339 * Check word for most significant bit set. Returns
340 * a value in dst_exponent indicating the bit position,
341 * between -1 and 30.
342 */
343 Find_ms_one_bit(srcp1,dst_exponent);
344 /* left justify source, with msb at bit position 1 */
345 if (dst_exponent > 0) {
346 Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
347 srcp1);
348 srcp2 <<= dst_exponent;
349 }
350 /*
351 * If dst_exponent = 0, we don't need to shift anything.
352 * If dst_exponent = -1, src = - 2**63 so we won't need to
353 * shift srcp2.
354 */
355 else srcp1 >>= -(dst_exponent);
356 }
357 Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
358 Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
359 Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
360
361 /* check for inexact */
362 if (Dint_isinexact_to_dbl(srcp2)) {
363 switch (Rounding_mode()) {
364 case ROUNDPLUS:
365 if (Dbl_iszero_sign(resultp1)) {
366 Dbl_increment(resultp1,resultp2);
367 }
368 break;
369 case ROUNDMINUS:
370 if (Dbl_isone_sign(resultp1)) {
371 Dbl_increment(resultp1,resultp2);
372 }
373 break;
374 case ROUNDNEAREST:
375 Dbl_roundnearest_from_dint(srcp2,resultp1,
376 resultp2);
377 }
378 if (Is_inexacttrap_enabled()) {
379 Dbl_copytoptr(resultp1,resultp2,dstptr);
380 return(INEXACTEXCEPTION);
381 }
382 else Set_inexactflag();
383 }
384 Dbl_copytoptr(resultp1,resultp2,dstptr);
385 return(NOEXCEPTION);
386}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/float.h $Revision: 1.1 $
26 *
27 * Purpose:
28 * <<please update with a synopis of the functionality provided by this file>>
29 *
30 * BE header: no
31 *
32 * Shipped: yes
33 * /usr/conf/pa/spmath/float.h
34 *
35 * END_DESC
36*/
37
38#ifdef __NO_PA_HDRS
39 PA header file -- do not include this header file for non-PA builds.
40#endif
41
42#include "fpbits.h"
43#include "hppa.h"
44/*
45 * Want to pick up the FPU capability flags, not the PDC structures.
46 * 'LOCORE' isn't really true in this case, but we don't want the C structures
47 * so it suits our purposes
48 */
49#define LOCORE
50#include "fpu.h"
51
52/*
53 * Declare the basic structures for the 3 different
54 * floating-point precisions.
55 *
56 * Single number
57 * +-------+-------+-------+-------+-------+-------+-------+-------+
58 * |s| exp | mantissa |
59 * +-------+-------+-------+-------+-------+-------+-------+-------+
60 */
61#define Sall(object) (object)
62#define Ssign(object) Bitfield_extract( 0, 1,object)
63#define Ssignedsign(object) Bitfield_signed_extract( 0, 1,object)
64#define Sexponent(object) Bitfield_extract( 1, 8,object)
65#define Smantissa(object) Bitfield_mask( 9, 23,object)
66#define Ssignaling(object) Bitfield_extract( 9, 1,object)
67#define Ssignalingnan(object) Bitfield_extract( 1, 9,object)
68#define Shigh2mantissa(object) Bitfield_extract( 9, 2,object)
69#define Sexponentmantissa(object) Bitfield_mask( 1, 31,object)
70#define Ssignexponent(object) Bitfield_extract( 0, 9,object)
71#define Shidden(object) Bitfield_extract( 8, 1,object)
72#define Shiddenoverflow(object) Bitfield_extract( 7, 1,object)
73#define Shiddenhigh7mantissa(object) Bitfield_extract( 8, 8,object)
74#define Shiddenhigh3mantissa(object) Bitfield_extract( 8, 4,object)
75#define Slow(object) Bitfield_mask( 31, 1,object)
76#define Slow4(object) Bitfield_mask( 28, 4,object)
77#define Slow31(object) Bitfield_mask( 1, 31,object)
78#define Shigh31(object) Bitfield_extract( 0, 31,object)
79#define Ssignedhigh31(object) Bitfield_signed_extract( 0, 31,object)
80#define Shigh4(object) Bitfield_extract( 0, 4,object)
81#define Sbit24(object) Bitfield_extract( 24, 1,object)
82#define Sbit28(object) Bitfield_extract( 28, 1,object)
83#define Sbit29(object) Bitfield_extract( 29, 1,object)
84#define Sbit30(object) Bitfield_extract( 30, 1,object)
85#define Sbit31(object) Bitfield_mask( 31, 1,object)
86
87#define Deposit_ssign(object,value) Bitfield_deposit(value,0,1,object)
88#define Deposit_sexponent(object,value) Bitfield_deposit(value,1,8,object)
89#define Deposit_smantissa(object,value) Bitfield_deposit(value,9,23,object)
90#define Deposit_shigh2mantissa(object,value) Bitfield_deposit(value,9,2,object)
91#define Deposit_sexponentmantissa(object,value) \
92 Bitfield_deposit(value,1,31,object)
93#define Deposit_ssignexponent(object,value) Bitfield_deposit(value,0,9,object)
94#define Deposit_slow(object,value) Bitfield_deposit(value,31,1,object)
95#define Deposit_shigh4(object,value) Bitfield_deposit(value,0,4,object)
96
97#define Is_ssign(object) Bitfield_mask( 0, 1,object)
98#define Is_ssignaling(object) Bitfield_mask( 9, 1,object)
99#define Is_shidden(object) Bitfield_mask( 8, 1,object)
100#define Is_shiddenoverflow(object) Bitfield_mask( 7, 1,object)
101#define Is_slow(object) Bitfield_mask( 31, 1,object)
102#define Is_sbit24(object) Bitfield_mask( 24, 1,object)
103#define Is_sbit28(object) Bitfield_mask( 28, 1,object)
104#define Is_sbit29(object) Bitfield_mask( 29, 1,object)
105#define Is_sbit30(object) Bitfield_mask( 30, 1,object)
106#define Is_sbit31(object) Bitfield_mask( 31, 1,object)
107
108/*
109 * Double number.
110 * +-------+-------+-------+-------+-------+-------+-------+-------+
111 * |s| exponent | mantissa part 1 |
112 * +-------+-------+-------+-------+-------+-------+-------+-------+
113 *
114 * +-------+-------+-------+-------+-------+-------+-------+-------+
115 * | mantissa part 2 |
116 * +-------+-------+-------+-------+-------+-------+-------+-------+
117 */
118#define Dallp1(object) (object)
119#define Dsign(object) Bitfield_extract( 0, 1,object)
120#define Dsignedsign(object) Bitfield_signed_extract( 0, 1,object)
121#define Dexponent(object) Bitfield_extract( 1, 11,object)
122#define Dmantissap1(object) Bitfield_mask( 12, 20,object)
123#define Dsignaling(object) Bitfield_extract( 12, 1,object)
124#define Dsignalingnan(object) Bitfield_extract( 1, 12,object)
125#define Dhigh2mantissa(object) Bitfield_extract( 12, 2,object)
126#define Dexponentmantissap1(object) Bitfield_mask( 1, 31,object)
127#define Dsignexponent(object) Bitfield_extract( 0, 12,object)
128#define Dhidden(object) Bitfield_extract( 11, 1,object)
129#define Dhiddenoverflow(object) Bitfield_extract( 10, 1,object)
130#define Dhiddenhigh7mantissa(object) Bitfield_extract( 11, 8,object)
131#define Dhiddenhigh3mantissa(object) Bitfield_extract( 11, 4,object)
132#define Dlowp1(object) Bitfield_mask( 31, 1,object)
133#define Dlow31p1(object) Bitfield_mask( 1, 31,object)
134#define Dhighp1(object) Bitfield_extract( 0, 1,object)
135#define Dhigh4p1(object) Bitfield_extract( 0, 4,object)
136#define Dhigh31p1(object) Bitfield_extract( 0, 31,object)
137#define Dsignedhigh31p1(object) Bitfield_signed_extract( 0, 31,object)
138#define Dbit3p1(object) Bitfield_extract( 3, 1,object)
139
140#define Deposit_dsign(object,value) Bitfield_deposit(value,0,1,object)
141#define Deposit_dexponent(object,value) Bitfield_deposit(value,1,11,object)
142#define Deposit_dmantissap1(object,value) Bitfield_deposit(value,12,20,object)
143#define Deposit_dhigh2mantissa(object,value) Bitfield_deposit(value,12,2,object)
144#define Deposit_dexponentmantissap1(object,value) \
145 Bitfield_deposit(value,1,31,object)
146#define Deposit_dsignexponent(object,value) Bitfield_deposit(value,0,12,object)
147#define Deposit_dlowp1(object,value) Bitfield_deposit(value,31,1,object)
148#define Deposit_dhigh4p1(object,value) Bitfield_deposit(value,0,4,object)
149
150#define Is_dsign(object) Bitfield_mask( 0, 1,object)
151#define Is_dsignaling(object) Bitfield_mask( 12, 1,object)
152#define Is_dhidden(object) Bitfield_mask( 11, 1,object)
153#define Is_dhiddenoverflow(object) Bitfield_mask( 10, 1,object)
154#define Is_dlowp1(object) Bitfield_mask( 31, 1,object)
155#define Is_dhighp1(object) Bitfield_mask( 0, 1,object)
156#define Is_dbit3p1(object) Bitfield_mask( 3, 1,object)
157
158#define Dallp2(object) (object)
159#define Dmantissap2(object) (object)
160#define Dlowp2(object) Bitfield_mask( 31, 1,object)
161#define Dlow4p2(object) Bitfield_mask( 28, 4,object)
162#define Dlow31p2(object) Bitfield_mask( 1, 31,object)
163#define Dhighp2(object) Bitfield_extract( 0, 1,object)
164#define Dhigh31p2(object) Bitfield_extract( 0, 31,object)
165#define Dbit2p2(object) Bitfield_extract( 2, 1,object)
166#define Dbit3p2(object) Bitfield_extract( 3, 1,object)
167#define Dbit21p2(object) Bitfield_extract( 21, 1,object)
168#define Dbit28p2(object) Bitfield_extract( 28, 1,object)
169#define Dbit29p2(object) Bitfield_extract( 29, 1,object)
170#define Dbit30p2(object) Bitfield_extract( 30, 1,object)
171#define Dbit31p2(object) Bitfield_mask( 31, 1,object)
172
173#define Deposit_dlowp2(object,value) Bitfield_deposit(value,31,1,object)
174
175#define Is_dlowp2(object) Bitfield_mask( 31, 1,object)
176#define Is_dhighp2(object) Bitfield_mask( 0, 1,object)
177#define Is_dbit2p2(object) Bitfield_mask( 2, 1,object)
178#define Is_dbit3p2(object) Bitfield_mask( 3, 1,object)
179#define Is_dbit21p2(object) Bitfield_mask( 21, 1,object)
180#define Is_dbit28p2(object) Bitfield_mask( 28, 1,object)
181#define Is_dbit29p2(object) Bitfield_mask( 29, 1,object)
182#define Is_dbit30p2(object) Bitfield_mask( 30, 1,object)
183#define Is_dbit31p2(object) Bitfield_mask( 31, 1,object)
184
185/*
186 * Quad number.
187 * +-------+-------+-------+-------+-------+-------+-------+-------+
188 * |s| exponent | mantissa part 1 |
189 * +-------+-------+-------+-------+-------+-------+-------+-------+
190 *
191 * +-------+-------+-------+-------+-------+-------+-------+-------+
192 * | mantissa part 2 |
193 * +-------+-------+-------+-------+-------+-------+-------+-------+
194 *
195 * +-------+-------+-------+-------+-------+-------+-------+-------+
196 * | mantissa part 3 |
197 * +-------+-------+-------+-------+-------+-------+-------+-------+
198 *
199 * +-------+-------+-------+-------+-------+-------+-------+-------+
200 * | mantissa part 4 |
201 * +-------+-------+-------+-------+-------+-------+-------+-------+
202 */
203typedef struct
204 {
205 union
206 {
207 struct { unsigned qallp1; } u_qallp1;
208/* Not needed for now...
209 Bitfield_extract( 0, 1,u_qsign,qsign)
210 Bitfield_signed_extract( 0, 1,u_qsignedsign,qsignedsign)
211 Bitfield_extract( 1, 15,u_qexponent,qexponent)
212 Bitfield_extract(16, 16,u_qmantissap1,qmantissap1)
213 Bitfield_extract(16, 1,u_qsignaling,qsignaling)
214 Bitfield_extract(1, 16,u_qsignalingnan,qsignalingnan)
215 Bitfield_extract(16, 2,u_qhigh2mantissa,qhigh2mantissa)
216 Bitfield_extract( 1, 31,u_qexponentmantissap1,qexponentmantissap1)
217 Bitfield_extract( 0, 16,u_qsignexponent,qsignexponent)
218 Bitfield_extract(15, 1,u_qhidden,qhidden)
219 Bitfield_extract(14, 1,u_qhiddenoverflow,qhiddenoverflow)
220 Bitfield_extract(15, 8,u_qhiddenhigh7mantissa,qhiddenhigh7mantissa)
221 Bitfield_extract(15, 4,u_qhiddenhigh3mantissa,qhiddenhigh3mantissa)
222 Bitfield_extract(31, 1,u_qlowp1,qlowp1)
223 Bitfield_extract( 1, 31,u_qlow31p1,qlow31p1)
224 Bitfield_extract( 0, 1,u_qhighp1,qhighp1)
225 Bitfield_extract( 0, 4,u_qhigh4p1,qhigh4p1)
226 Bitfield_extract( 0, 31,u_qhigh31p1,qhigh31p1)
227 */
228 } quad_u1;
229 union
230 {
231 struct { unsigned qallp2; } u_qallp2;
232 /* Not needed for now...
233 Bitfield_extract(31, 1,u_qlowp2,qlowp2)
234 Bitfield_extract( 1, 31,u_qlow31p2,qlow31p2)
235 Bitfield_extract( 0, 1,u_qhighp2,qhighp2)
236 Bitfield_extract( 0, 31,u_qhigh31p2,qhigh31p2)
237 */
238 } quad_u2;
239 union
240 {
241 struct { unsigned qallp3; } u_qallp3;
242 /* Not needed for now...
243 Bitfield_extract(31, 1,u_qlowp3,qlowp3)
244 Bitfield_extract( 1, 31,u_qlow31p3,qlow31p3)
245 Bitfield_extract( 0, 1,u_qhighp3,qhighp3)
246 Bitfield_extract( 0, 31,u_qhigh31p3,qhigh31p3)
247 */
248 } quad_u3;
249 union
250 {
251 struct { unsigned qallp4; } u_qallp4;
252 /* Not need for now...
253 Bitfield_extract(31, 1,u_qlowp4,qlowp4)
254 Bitfield_extract( 1, 31,u_qlow31p4,qlow31p4)
255 Bitfield_extract( 0, 1,u_qhighp4,qhighp4)
256 Bitfield_extract( 0, 31,u_qhigh31p4,qhigh31p4)
257 */
258 } quad_u4;
259 } quad_floating_point;
260
261/* Extension - An additional structure to hold the guard, round and
262 * sticky bits during computations.
263 */
264#define Extall(object) (object)
265#define Extsign(object) Bitfield_extract( 0, 1,object)
266#define Exthigh31(object) Bitfield_extract( 0, 31,object)
267#define Extlow31(object) Bitfield_extract( 1, 31,object)
268#define Extlow(object) Bitfield_extract( 31, 1,object)
269
270/*
271 * Single extended - The upper word is just like single precision,
272 * but one additional word of mantissa is needed.
273 */
274#define Sextallp1(object) (object)
275#define Sextallp2(object) (object)
276#define Sextlowp1(object) Bitfield_extract( 31, 1,object)
277#define Sexthighp2(object) Bitfield_extract( 0, 1,object)
278#define Sextlow31p2(object) Bitfield_extract( 1, 31,object)
279#define Sexthiddenoverflow(object) Bitfield_extract( 4, 1,object)
280#define Is_sexthiddenoverflow(object) Bitfield_mask( 4, 1,object)
281
282/*
283 * Double extended - The upper two words are just like double precision,
284 * but two additional words of mantissa are needed.
285 */
286#define Dextallp1(object) (object)
287#define Dextallp2(object) (object)
288#define Dextallp3(object) (object)
289#define Dextallp4(object) (object)
290#define Dextlowp2(object) Bitfield_extract( 31, 1,object)
291#define Dexthighp3(object) Bitfield_extract( 0, 1,object)
292#define Dextlow31p3(object) Bitfield_extract( 1, 31,object)
293#define Dexthiddenoverflow(object) Bitfield_extract( 10, 1,object)
294#define Is_dexthiddenoverflow(object) Bitfield_mask( 10, 1,object)
295#define Deposit_dextlowp4(object,value) Bitfield_deposit(value,31,1,object)
296
297/*
298 * Declare the basic structures for the 3 different
299 * fixed-point precisions.
300 *
301 * Single number
302 * +-------+-------+-------+-------+-------+-------+-------+-------+
303 * |s| integer |
304 * +-------+-------+-------+-------+-------+-------+-------+-------+
305 */
306typedef int sgl_integer;
307
308/*
309 * Double number.
310 * +-------+-------+-------+-------+-------+-------+-------+-------+
311 * |s| high integer |
312 * +-------+-------+-------+-------+-------+-------+-------+-------+
313 *
314 * +-------+-------+-------+-------+-------+-------+-------+-------+
315 * | low integer |
316 * +-------+-------+-------+-------+-------+-------+-------+-------+
317 */
318struct dint {
319 int wd0;
320 unsigned int wd1;
321};
322
323struct dblwd {
324 unsigned int wd0;
325 unsigned int wd1;
326};
327
328/*
329 * Quad number.
330 * +-------+-------+-------+-------+-------+-------+-------+-------+
331 * |s| integer part1 |
332 * +-------+-------+-------+-------+-------+-------+-------+-------+
333 *
334 * +-------+-------+-------+-------+-------+-------+-------+-------+
335 * | integer part 2 |
336 * +-------+-------+-------+-------+-------+-------+-------+-------+
337 *
338 * +-------+-------+-------+-------+-------+-------+-------+-------+
339 * | integer part 3 |
340 * +-------+-------+-------+-------+-------+-------+-------+-------+
341 *
342 * +-------+-------+-------+-------+-------+-------+-------+-------+
343 * | integer part 4 |
344 * +-------+-------+-------+-------+-------+-------+-------+-------+
345 */
346
347struct quadwd {
348 int wd0;
349 unsigned int wd1;
350 unsigned int wd2;
351 unsigned int wd3;
352};
353
354typedef struct quadwd quad_integer;
355
356
357/* useful typedefs */
358typedef unsigned int sgl_floating_point;
359typedef struct dblwd dbl_floating_point;
360typedef struct dint dbl_integer;
361typedef struct dblwd dbl_unsigned;
362
363/*
364 * Define the different precisions' parameters.
365 */
366#define SGL_BITLENGTH 32
367#define SGL_EMAX 127
368#define SGL_EMIN (-126)
369#define SGL_BIAS 127
370#define SGL_WRAP 192
371#define SGL_INFINITY_EXPONENT (SGL_EMAX+SGL_BIAS+1)
372#define SGL_THRESHOLD 32
373#define SGL_EXP_LENGTH 8
374#define SGL_P 24
375
376#define DBL_BITLENGTH 64
377#define DBL_EMAX 1023
378#define DBL_EMIN (-1022)
379#define DBL_BIAS 1023
380#define DBL_WRAP 1536
381#define DBL_INFINITY_EXPONENT (DBL_EMAX+DBL_BIAS+1)
382#define DBL_THRESHOLD 64
383#define DBL_EXP_LENGTH 11
384#define DBL_P 53
385
386#define QUAD_BITLENGTH 128
387#define QUAD_EMAX 16383
388#define QUAD_EMIN (-16382)
389#define QUAD_BIAS 16383
390#define QUAD_WRAP 24576
391#define QUAD_INFINITY_EXPONENT (QUAD_EMAX+QUAD_BIAS+1)
392#define QUAD_P 113
393
394/* Boolean Values etc. */
395#define FALSE 0
396#define TRUE (!FALSE)
397#define NOT !
398#define XOR ^
399
400/* other constants */
401#undef NULL
402#define NULL 0
403#define NIL 0
404#define SGL 0
405#define DBL 1
406#define BADFMT 2
407#define QUAD 3
408
409
410/* Types */
411typedef int boolean;
412typedef int FORMAT;
413typedef int VOID;
414
415
416/* Declare status register equivalent to FPUs architecture.
417 *
418 * 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
419 * +-------+-------+-------+-------+-------+-------+-------+-------+
420 * |V|Z|O|U|I|C| rsv | model | version |RM |rsv|T|r|V|Z|O|U|I|
421 * +-------+-------+-------+-------+-------+-------+-------+-------+
422 */
423#define Cbit(object) Bitfield_extract( 5, 1,object)
424#define Tbit(object) Bitfield_extract( 25, 1,object)
425#define Roundingmode(object) Bitfield_extract( 21, 2,object)
426#define Invalidtrap(object) Bitfield_extract( 27, 1,object)
427#define Divisionbyzerotrap(object) Bitfield_extract( 28, 1,object)
428#define Overflowtrap(object) Bitfield_extract( 29, 1,object)
429#define Underflowtrap(object) Bitfield_extract( 30, 1,object)
430#define Inexacttrap(object) Bitfield_extract( 31, 1,object)
431#define Invalidflag(object) Bitfield_extract( 0, 1,object)
432#define Divisionbyzeroflag(object) Bitfield_extract( 1, 1,object)
433#define Overflowflag(object) Bitfield_extract( 2, 1,object)
434#define Underflowflag(object) Bitfield_extract( 3, 1,object)
435#define Inexactflag(object) Bitfield_extract( 4, 1,object)
436#define Allflags(object) Bitfield_extract( 0, 5,object)
437
438/* Definitions relevant to the status register */
439
440/* Rounding Modes */
441#define ROUNDNEAREST 0
442#define ROUNDZERO 1
443#define ROUNDPLUS 2
444#define ROUNDMINUS 3
445
446/* Exceptions */
447#define NOEXCEPTION 0x0
448#define INVALIDEXCEPTION 0x20
449#define DIVISIONBYZEROEXCEPTION 0x10
450#define OVERFLOWEXCEPTION 0x08
451#define UNDERFLOWEXCEPTION 0x04
452#define INEXACTEXCEPTION 0x02
453#define UNIMPLEMENTEDEXCEPTION 0x01
454
455/* New exceptions for the 2E Opcode */
456#define OPC_2E_INVALIDEXCEPTION 0x30
457#define OPC_2E_OVERFLOWEXCEPTION 0x18
458#define OPC_2E_UNDERFLOWEXCEPTION 0x0c
459#define OPC_2E_INEXACTEXCEPTION 0x12
460
461/* Declare exception registers equivalent to FPUs architecture
462 *
463 * 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
464 * +-------+-------+-------+-------+-------+-------+-------+-------+
465 * |excepttype | r1 | r2/ext | operation |parm |n| t/cond |
466 * +-------+-------+-------+-------+-------+-------+-------+-------+
467 */
468#define Allexception(object) (object)
469#define Exceptiontype(object) Bitfield_extract( 0, 6,object)
470#define Instructionfield(object) Bitfield_mask( 6,26,object)
471#define Parmfield(object) Bitfield_extract( 23, 3,object)
472#define Rabit(object) Bitfield_extract( 24, 1,object)
473#define Ibit(object) Bitfield_extract( 25, 1,object)
474
475#define Set_exceptiontype(object,value) Bitfield_deposit(value, 0, 6,object)
476#define Set_parmfield(object,value) Bitfield_deposit(value, 23, 3,object)
477#define Set_exceptiontype_and_instr_field(exception,instruction,object) \
478 object = exception << 26 | instruction
479
480/* Declare the condition field
481 *
482 * 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
483 * +-------+-------+-------+-------+-------+-------+-------+-------+
484 * | |G|L|E|U|X|
485 * +-------+-------+-------+-------+-------+-------+-------+-------+
486 */
487#define Allexception(object) (object)
488#define Greaterthanbit(object) Bitfield_extract( 27, 1,object)
489#define Lessthanbit(object) Bitfield_extract( 28, 1,object)
490#define Equalbit(object) Bitfield_extract( 29, 1,object)
491#define Unorderedbit(object) Bitfield_extract( 30, 1,object)
492#define Exceptionbit(object) Bitfield_extract( 31, 1,object)
493
494/* An alias name for the status register */
495#define Fpustatus_register (*status)
496
497/**************************************************
498 * Status register referencing and manipulation. *
499 **************************************************/
500
501/* Rounding mode */
502#define Rounding_mode() Roundingmode(Fpustatus_register)
503#define Is_rounding_mode(rmode) \
504 (Roundingmode(Fpustatus_register) == rmode)
505#define Set_rounding_mode(value) \
506 Bitfield_deposit(value,21,2,Fpustatus_register)
507
508/* Boolean testing of the trap enable bits */
509#define Is_invalidtrap_enabled() Invalidtrap(Fpustatus_register)
510#define Is_divisionbyzerotrap_enabled() Divisionbyzerotrap(Fpustatus_register)
511#define Is_overflowtrap_enabled() Overflowtrap(Fpustatus_register)
512#define Is_underflowtrap_enabled() Underflowtrap(Fpustatus_register)
513#define Is_inexacttrap_enabled() Inexacttrap(Fpustatus_register)
514
515/* Set the indicated flags in the status register */
516#define Set_invalidflag() Bitfield_deposit(1,0,1,Fpustatus_register)
517#define Set_divisionbyzeroflag() Bitfield_deposit(1,1,1,Fpustatus_register)
518#define Set_overflowflag() Bitfield_deposit(1,2,1,Fpustatus_register)
519#define Set_underflowflag() Bitfield_deposit(1,3,1,Fpustatus_register)
520#define Set_inexactflag() Bitfield_deposit(1,4,1,Fpustatus_register)
521
522#define Clear_all_flags() Bitfield_deposit(0,0,5,Fpustatus_register)
523
524/* Manipulate the trap and condition code bits (tbit and cbit) */
525#define Set_tbit() Bitfield_deposit(1,25,1,Fpustatus_register)
526#define Clear_tbit() Bitfield_deposit(0,25,1,Fpustatus_register)
527#define Is_tbit_set() Tbit(Fpustatus_register)
528#define Is_cbit_set() Cbit(Fpustatus_register)
529
530#define Set_status_cbit(value) \
531 Bitfield_deposit(value,5,1,Fpustatus_register)
532
533/*******************************
534 * Condition field referencing *
535 *******************************/
536#define Unordered(cond) Unorderedbit(cond)
537#define Equal(cond) Equalbit(cond)
538#define Lessthan(cond) Lessthanbit(cond)
539#define Greaterthan(cond) Greaterthanbit(cond)
540#define Exception(cond) Exceptionbit(cond)
541
542
543/* Defines for the extension */
544#define Ext_isone_sign(extent) (Extsign(extent))
545#define Ext_isnotzero(extent) \
546 (Extall(extent))
547#define Ext_isnotzero_lower(extent) \
548 (Extlow31(extent))
549#define Ext_leftshiftby1(extent) \
550 Extall(extent) <<= 1
551#define Ext_negate(extent) \
552 (int )Extall(extent) = 0 - (int )Extall(extent)
553#define Ext_setone_low(extent) Bitfield_deposit(1,31,1,extent)
554#define Ext_setzero(extent) Extall(extent) = 0
555
556typedef int operation;
557
558/* error messages */
559
560#define NONE 0
561#define UNDEFFPINST 1
562
563/* Function definitions: opcode, opclass */
564#define FTEST (1<<2) | 0
565#define FCPY (2<<2) | 0
566#define FABS (3<<2) | 0
567#define FSQRT (4<<2) | 0
568#define FRND (5<<2) | 0
569
570#define FCNVFF (0<<2) | 1
571#define FCNVXF (1<<2) | 1
572#define FCNVFX (2<<2) | 1
573#define FCNVFXT (3<<2) | 1
574
575#define FCMP (0<<2) | 2
576
577#define FADD (0<<2) | 3
578#define FSUB (1<<2) | 3
579#define FMPY (2<<2) | 3
580#define FDIV (3<<2) | 3
581#define FREM (4<<2) | 3
582
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fmpyfadd.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Double Floating-point Multiply Fused Add
29 * Double Floating-point Multiply Negate Fused Add
30 * Single Floating-point Multiply Fused Add
31 * Single Floating-point Multiply Negate Fused Add
32 *
33 * External Interfaces:
34 * dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
35 * dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
36 * sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
37 * sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
38 *
39 * Internal Interfaces:
40 *
41 * Theory:
42 * <<please update with a overview of the operation of this file>>
43 *
44 * END_DESC
45*/
46
47
48#include "float.h"
49#include "sgl_float.h"
50#include "dbl_float.h"
51
52
53/*
54 * Double Floating-point Multiply Fused Add
55 */
56
57int
58dbl_fmpyfadd(
59 dbl_floating_point *src1ptr,
60 dbl_floating_point *src2ptr,
61 dbl_floating_point *src3ptr,
62 unsigned int *status,
63 dbl_floating_point *dstptr)
64{
65 unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
66 register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
67 unsigned int rightp1, rightp2, rightp3, rightp4;
68 unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
69 register int mpy_exponent, add_exponent, count;
70 boolean inexact = FALSE, is_tiny = FALSE;
71
72 unsigned int signlessleft1, signlessright1, save;
73 register int result_exponent, diff_exponent;
74 int sign_save, jumpsize;
75
76 Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
77 Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
78 Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
79
80 /*
81 * set sign bit of result of multiply
82 */
83 if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
84 Dbl_setnegativezerop1(resultp1);
85 else Dbl_setzerop1(resultp1);
86
87 /*
88 * Generate multiply exponent
89 */
90 mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
91
92 /*
93 * check first operand for NaN's or infinity
94 */
95 if (Dbl_isinfinity_exponent(opnd1p1)) {
96 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
97 if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
98 Dbl_isnotnan(opnd3p1,opnd3p2)) {
99 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
100 /*
101 * invalid since operands are infinity
102 * and zero
103 */
104 if (Is_invalidtrap_enabled())
105 return(OPC_2E_INVALIDEXCEPTION);
106 Set_invalidflag();
107 Dbl_makequietnan(resultp1,resultp2);
108 Dbl_copytoptr(resultp1,resultp2,dstptr);
109 return(NOEXCEPTION);
110 }
111 /*
112 * Check third operand for infinity with a
113 * sign opposite of the multiply result
114 */
115 if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
116 (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
117 /*
118 * invalid since attempting a magnitude
119 * subtraction of infinities
120 */
121 if (Is_invalidtrap_enabled())
122 return(OPC_2E_INVALIDEXCEPTION);
123 Set_invalidflag();
124 Dbl_makequietnan(resultp1,resultp2);
125 Dbl_copytoptr(resultp1,resultp2,dstptr);
126 return(NOEXCEPTION);
127 }
128
129 /*
130 * return infinity
131 */
132 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
133 Dbl_copytoptr(resultp1,resultp2,dstptr);
134 return(NOEXCEPTION);
135 }
136 }
137 else {
138 /*
139 * is NaN; signaling or quiet?
140 */
141 if (Dbl_isone_signaling(opnd1p1)) {
142 /* trap if INVALIDTRAP enabled */
143 if (Is_invalidtrap_enabled())
144 return(OPC_2E_INVALIDEXCEPTION);
145 /* make NaN quiet */
146 Set_invalidflag();
147 Dbl_set_quiet(opnd1p1);
148 }
149 /*
150 * is second operand a signaling NaN?
151 */
152 else if (Dbl_is_signalingnan(opnd2p1)) {
153 /* trap if INVALIDTRAP enabled */
154 if (Is_invalidtrap_enabled())
155 return(OPC_2E_INVALIDEXCEPTION);
156 /* make NaN quiet */
157 Set_invalidflag();
158 Dbl_set_quiet(opnd2p1);
159 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
160 return(NOEXCEPTION);
161 }
162 /*
163 * is third operand a signaling NaN?
164 */
165 else if (Dbl_is_signalingnan(opnd3p1)) {
166 /* trap if INVALIDTRAP enabled */
167 if (Is_invalidtrap_enabled())
168 return(OPC_2E_INVALIDEXCEPTION);
169 /* make NaN quiet */
170 Set_invalidflag();
171 Dbl_set_quiet(opnd3p1);
172 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
173 return(NOEXCEPTION);
174 }
175 /*
176 * return quiet NaN
177 */
178 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
179 return(NOEXCEPTION);
180 }
181 }
182
183 /*
184 * check second operand for NaN's or infinity
185 */
186 if (Dbl_isinfinity_exponent(opnd2p1)) {
187 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
188 if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
189 if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
190 /*
191 * invalid since multiply operands are
192 * zero & infinity
193 */
194 if (Is_invalidtrap_enabled())
195 return(OPC_2E_INVALIDEXCEPTION);
196 Set_invalidflag();
197 Dbl_makequietnan(opnd2p1,opnd2p2);
198 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
199 return(NOEXCEPTION);
200 }
201
202 /*
203 * Check third operand for infinity with a
204 * sign opposite of the multiply result
205 */
206 if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
207 (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
208 /*
209 * invalid since attempting a magnitude
210 * subtraction of infinities
211 */
212 if (Is_invalidtrap_enabled())
213 return(OPC_2E_INVALIDEXCEPTION);
214 Set_invalidflag();
215 Dbl_makequietnan(resultp1,resultp2);
216 Dbl_copytoptr(resultp1,resultp2,dstptr);
217 return(NOEXCEPTION);
218 }
219
220 /*
221 * return infinity
222 */
223 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
224 Dbl_copytoptr(resultp1,resultp2,dstptr);
225 return(NOEXCEPTION);
226 }
227 }
228 else {
229 /*
230 * is NaN; signaling or quiet?
231 */
232 if (Dbl_isone_signaling(opnd2p1)) {
233 /* trap if INVALIDTRAP enabled */
234 if (Is_invalidtrap_enabled())
235 return(OPC_2E_INVALIDEXCEPTION);
236 /* make NaN quiet */
237 Set_invalidflag();
238 Dbl_set_quiet(opnd2p1);
239 }
240 /*
241 * is third operand a signaling NaN?
242 */
243 else if (Dbl_is_signalingnan(opnd3p1)) {
244 /* trap if INVALIDTRAP enabled */
245 if (Is_invalidtrap_enabled())
246 return(OPC_2E_INVALIDEXCEPTION);
247 /* make NaN quiet */
248 Set_invalidflag();
249 Dbl_set_quiet(opnd3p1);
250 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
251 return(NOEXCEPTION);
252 }
253 /*
254 * return quiet NaN
255 */
256 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
257 return(NOEXCEPTION);
258 }
259 }
260
261 /*
262 * check third operand for NaN's or infinity
263 */
264 if (Dbl_isinfinity_exponent(opnd3p1)) {
265 if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
266 /* return infinity */
267 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
268 return(NOEXCEPTION);
269 } else {
270 /*
271 * is NaN; signaling or quiet?
272 */
273 if (Dbl_isone_signaling(opnd3p1)) {
274 /* trap if INVALIDTRAP enabled */
275 if (Is_invalidtrap_enabled())
276 return(OPC_2E_INVALIDEXCEPTION);
277 /* make NaN quiet */
278 Set_invalidflag();
279 Dbl_set_quiet(opnd3p1);
280 }
281 /*
282 * return quiet NaN
283 */
284 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
285 return(NOEXCEPTION);
286 }
287 }
288
289 /*
290 * Generate multiply mantissa
291 */
292 if (Dbl_isnotzero_exponent(opnd1p1)) {
293 /* set hidden bit */
294 Dbl_clear_signexponent_set_hidden(opnd1p1);
295 }
296 else {
297 /* check for zero */
298 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
299 /*
300 * Perform the add opnd3 with zero here.
301 */
302 if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
303 if (Is_rounding_mode(ROUNDMINUS)) {
304 Dbl_or_signs(opnd3p1,resultp1);
305 } else {
306 Dbl_and_signs(opnd3p1,resultp1);
307 }
308 }
309 /*
310 * Now let's check for trapped underflow case.
311 */
312 else if (Dbl_iszero_exponent(opnd3p1) &&
313 Is_underflowtrap_enabled()) {
314 /* need to normalize results mantissa */
315 sign_save = Dbl_signextendedsign(opnd3p1);
316 result_exponent = 0;
317 Dbl_leftshiftby1(opnd3p1,opnd3p2);
318 Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
319 Dbl_set_sign(opnd3p1,/*using*/sign_save);
320 Dbl_setwrapped_exponent(opnd3p1,result_exponent,
321 unfl);
322 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
323 /* inexact = FALSE */
324 return(OPC_2E_UNDERFLOWEXCEPTION);
325 }
326 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
327 return(NOEXCEPTION);
328 }
329 /* is denormalized, adjust exponent */
330 Dbl_clear_signexponent(opnd1p1);
331 Dbl_leftshiftby1(opnd1p1,opnd1p2);
332 Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
333 }
334 /* opnd2 needs to have hidden bit set with msb in hidden bit */
335 if (Dbl_isnotzero_exponent(opnd2p1)) {
336 Dbl_clear_signexponent_set_hidden(opnd2p1);
337 }
338 else {
339 /* check for zero */
340 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
341 /*
342 * Perform the add opnd3 with zero here.
343 */
344 if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
345 if (Is_rounding_mode(ROUNDMINUS)) {
346 Dbl_or_signs(opnd3p1,resultp1);
347 } else {
348 Dbl_and_signs(opnd3p1,resultp1);
349 }
350 }
351 /*
352 * Now let's check for trapped underflow case.
353 */
354 else if (Dbl_iszero_exponent(opnd3p1) &&
355 Is_underflowtrap_enabled()) {
356 /* need to normalize results mantissa */
357 sign_save = Dbl_signextendedsign(opnd3p1);
358 result_exponent = 0;
359 Dbl_leftshiftby1(opnd3p1,opnd3p2);
360 Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
361 Dbl_set_sign(opnd3p1,/*using*/sign_save);
362 Dbl_setwrapped_exponent(opnd3p1,result_exponent,
363 unfl);
364 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
365 /* inexact = FALSE */
366 return(OPC_2E_UNDERFLOWEXCEPTION);
367 }
368 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
369 return(NOEXCEPTION);
370 }
371 /* is denormalized; want to normalize */
372 Dbl_clear_signexponent(opnd2p1);
373 Dbl_leftshiftby1(opnd2p1,opnd2p2);
374 Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
375 }
376
377 /* Multiply the first two source mantissas together */
378
379 /*
380 * The intermediate result will be kept in tmpres,
381 * which needs enough room for 106 bits of mantissa,
382 * so lets call it a Double extended.
383 */
384 Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
385
386 /*
387 * Four bits at a time are inspected in each loop, and a
388 * simple shift and add multiply algorithm is used.
389 */
390 for (count = DBL_P-1; count >= 0; count -= 4) {
391 Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
392 if (Dbit28p2(opnd1p2)) {
393 /* Fourword_add should be an ADD followed by 3 ADDC's */
394 Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
395 opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
396 }
397 if (Dbit29p2(opnd1p2)) {
398 Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
399 opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
400 }
401 if (Dbit30p2(opnd1p2)) {
402 Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
403 opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
404 }
405 if (Dbit31p2(opnd1p2)) {
406 Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
407 opnd2p1, opnd2p2, 0, 0);
408 }
409 Dbl_rightshiftby4(opnd1p1,opnd1p2);
410 }
411 if (Is_dexthiddenoverflow(tmpresp1)) {
412 /* result mantissa >= 2 (mantissa overflow) */
413 mpy_exponent++;
414 Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
415 }
416
417 /*
418 * Restore the sign of the mpy result which was saved in resultp1.
419 * The exponent will continue to be kept in mpy_exponent.
420 */
421 Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
422
423 /*
424 * No rounding is required, since the result of the multiply
425 * is exact in the extended format.
426 */
427
428 /*
429 * Now we are ready to perform the add portion of the operation.
430 *
431 * The exponents need to be kept as integers for now, since the
432 * multiply result might not fit into the exponent field. We
433 * can't overflow or underflow because of this yet, since the
434 * add could bring the final result back into range.
435 */
436 add_exponent = Dbl_exponent(opnd3p1);
437
438 /*
439 * Check for denormalized or zero add operand.
440 */
441 if (add_exponent == 0) {
442 /* check for zero */
443 if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
444 /* right is zero */
445 /* Left can't be zero and must be result.
446 *
447 * The final result is now in tmpres and mpy_exponent,
448 * and needs to be rounded and squeezed back into
449 * double precision format from double extended.
450 */
451 result_exponent = mpy_exponent;
452 Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
453 resultp1,resultp2,resultp3,resultp4);
454 sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
455 goto round;
456 }
457
458 /*
459 * Neither are zeroes.
460 * Adjust exponent and normalize add operand.
461 */
462 sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */
463 Dbl_clear_signexponent(opnd3p1);
464 Dbl_leftshiftby1(opnd3p1,opnd3p2);
465 Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
466 Dbl_set_sign(opnd3p1,sign_save); /* restore sign */
467 } else {
468 Dbl_clear_exponent_set_hidden(opnd3p1);
469 }
470 /*
471 * Copy opnd3 to the double extended variable called right.
472 */
473 Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
474
475 /*
476 * A zero "save" helps discover equal operands (for later),
477 * and is used in swapping operands (if needed).
478 */
479 Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
480
481 /*
482 * Compare magnitude of operands.
483 */
484 Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
485 Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
486 if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
487 Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
488 /*
489 * Set the left operand to the larger one by XOR swap.
490 * First finish the first word "save".
491 */
492 Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
493 Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
494 Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
495 rightp2,rightp3,rightp4);
496 /* also setup exponents used in rest of routine */
497 diff_exponent = add_exponent - mpy_exponent;
498 result_exponent = add_exponent;
499 } else {
500 /* also setup exponents used in rest of routine */
501 diff_exponent = mpy_exponent - add_exponent;
502 result_exponent = mpy_exponent;
503 }
504 /* Invariant: left is not smaller than right. */
505
506 /*
507 * Special case alignment of operands that would force alignment
508 * beyond the extent of the extension. A further optimization
509 * could special case this but only reduces the path length for
510 * this infrequent case.
511 */
512 if (diff_exponent > DBLEXT_THRESHOLD) {
513 diff_exponent = DBLEXT_THRESHOLD;
514 }
515
516 /* Align right operand by shifting it to the right */
517 Dblext_clear_sign(rightp1);
518 Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
519 /*shifted by*/diff_exponent);
520
521 /* Treat sum and difference of the operands separately. */
522 if ((int)save < 0) {
523 /*
524 * Difference of the two operands. Overflow can occur if the
525 * multiply overflowed. A borrow can occur out of the hidden
526 * bit and force a post normalization phase.
527 */
528 Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
529 rightp1,rightp2,rightp3,rightp4,
530 resultp1,resultp2,resultp3,resultp4);
531 sign_save = Dbl_signextendedsign(resultp1);
532 if (Dbl_iszero_hidden(resultp1)) {
533 /* Handle normalization */
534 /* A straight foward algorithm would now shift the
535 * result and extension left until the hidden bit
536 * becomes one. Not all of the extension bits need
537 * participate in the shift. Only the two most
538 * significant bits (round and guard) are needed.
539 * If only a single shift is needed then the guard
540 * bit becomes a significant low order bit and the
541 * extension must participate in the rounding.
542 * If more than a single shift is needed, then all
543 * bits to the right of the guard bit are zeros,
544 * and the guard bit may or may not be zero. */
545 Dblext_leftshiftby1(resultp1,resultp2,resultp3,
546 resultp4);
547
548 /* Need to check for a zero result. The sign and
549 * exponent fields have already been zeroed. The more
550 * efficient test of the full object can be used.
551 */
552 if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){
553 /* Must have been "x-x" or "x+(-x)". */
554 if (Is_rounding_mode(ROUNDMINUS))
555 Dbl_setone_sign(resultp1);
556 Dbl_copytoptr(resultp1,resultp2,dstptr);
557 return(NOEXCEPTION);
558 }
559 result_exponent--;
560
561 /* Look to see if normalization is finished. */
562 if (Dbl_isone_hidden(resultp1)) {
563 /* No further normalization is needed */
564 goto round;
565 }
566
567 /* Discover first one bit to determine shift amount.
568 * Use a modified binary search. We have already
569 * shifted the result one position right and still
570 * not found a one so the remainder of the extension
571 * must be zero and simplifies rounding. */
572 /* Scan bytes */
573 while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
574 Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
575 result_exponent -= 8;
576 }
577 /* Now narrow it down to the nibble */
578 if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
579 /* The lower nibble contains the
580 * normalizing one */
581 Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
582 result_exponent -= 4;
583 }
584 /* Select case where first bit is set (already
585 * normalized) otherwise select the proper shift. */
586 jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
587 if (jumpsize <= 7) switch(jumpsize) {
588 case 1:
589 Dblext_leftshiftby3(resultp1,resultp2,resultp3,
590 resultp4);
591 result_exponent -= 3;
592 break;
593 case 2:
594 case 3:
595 Dblext_leftshiftby2(resultp1,resultp2,resultp3,
596 resultp4);
597 result_exponent -= 2;
598 break;
599 case 4:
600 case 5:
601 case 6:
602 case 7:
603 Dblext_leftshiftby1(resultp1,resultp2,resultp3,
604 resultp4);
605 result_exponent -= 1;
606 break;
607 }
608 } /* end if (hidden...)... */
609 /* Fall through and round */
610 } /* end if (save < 0)... */
611 else {
612 /* Add magnitudes */
613 Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
614 rightp1,rightp2,rightp3,rightp4,
615 /*to*/resultp1,resultp2,resultp3,resultp4);
616 sign_save = Dbl_signextendedsign(resultp1);
617 if (Dbl_isone_hiddenoverflow(resultp1)) {
618 /* Prenormalization required. */
619 Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
620 resultp4);
621 result_exponent++;
622 } /* end if hiddenoverflow... */
623 } /* end else ...add magnitudes... */
624
625 /* Round the result. If the extension and lower two words are
626 * all zeros, then the result is exact. Otherwise round in the
627 * correct direction. Underflow is possible. If a postnormalization
628 * is necessary, then the mantissa is all zeros so no shift is needed.
629 */
630 round:
631 if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
632 Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
633 result_exponent,is_tiny);
634 }
635 Dbl_set_sign(resultp1,/*using*/sign_save);
636 if (Dblext_isnotzero_mantissap3(resultp3) ||
637 Dblext_isnotzero_mantissap4(resultp4)) {
638 inexact = TRUE;
639 switch(Rounding_mode()) {
640 case ROUNDNEAREST: /* The default. */
641 if (Dblext_isone_highp3(resultp3)) {
642 /* at least 1/2 ulp */
643 if (Dblext_isnotzero_low31p3(resultp3) ||
644 Dblext_isnotzero_mantissap4(resultp4) ||
645 Dblext_isone_lowp2(resultp2)) {
646 /* either exactly half way and odd or
647 * more than 1/2ulp */
648 Dbl_increment(resultp1,resultp2);
649 }
650 }
651 break;
652
653 case ROUNDPLUS:
654 if (Dbl_iszero_sign(resultp1)) {
655 /* Round up positive results */
656 Dbl_increment(resultp1,resultp2);
657 }
658 break;
659
660 case ROUNDMINUS:
661 if (Dbl_isone_sign(resultp1)) {
662 /* Round down negative results */
663 Dbl_increment(resultp1,resultp2);
664 }
665
666 case ROUNDZERO:;
667 /* truncate is simple */
668 } /* end switch... */
669 if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
670 }
671 if (result_exponent >= DBL_INFINITY_EXPONENT) {
672 /* trap if OVERFLOWTRAP enabled */
673 if (Is_overflowtrap_enabled()) {
674 /*
675 * Adjust bias of result
676 */
677 Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
678 Dbl_copytoptr(resultp1,resultp2,dstptr);
679 if (inexact)
680 if (Is_inexacttrap_enabled())
681 return (OPC_2E_OVERFLOWEXCEPTION |
682 OPC_2E_INEXACTEXCEPTION);
683 else Set_inexactflag();
684 return (OPC_2E_OVERFLOWEXCEPTION);
685 }
686 inexact = TRUE;
687 Set_overflowflag();
688 /* set result to infinity or largest number */
689 Dbl_setoverflow(resultp1,resultp2);
690
691 } else if (result_exponent <= 0) { /* underflow case */
692 if (Is_underflowtrap_enabled()) {
693 /*
694 * Adjust bias of result
695 */
696 Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
697 Dbl_copytoptr(resultp1,resultp2,dstptr);
698 if (inexact)
699 if (Is_inexacttrap_enabled())
700 return (OPC_2E_UNDERFLOWEXCEPTION |
701 OPC_2E_INEXACTEXCEPTION);
702 else Set_inexactflag();
703 return(OPC_2E_UNDERFLOWEXCEPTION);
704 }
705 else if (inexact && is_tiny) Set_underflowflag();
706 }
707 else Dbl_set_exponent(resultp1,result_exponent);
708 Dbl_copytoptr(resultp1,resultp2,dstptr);
709 if (inexact)
710 if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
711 else Set_inexactflag();
712 return(NOEXCEPTION);
713}
714
715/*
716 * Double Floating-point Multiply Negate Fused Add
717 */
718
719dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
720
721dbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
722unsigned int *status;
723{
724 unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
725 register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
726 unsigned int rightp1, rightp2, rightp3, rightp4;
727 unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
728 register int mpy_exponent, add_exponent, count;
729 boolean inexact = FALSE, is_tiny = FALSE;
730
731 unsigned int signlessleft1, signlessright1, save;
732 register int result_exponent, diff_exponent;
733 int sign_save, jumpsize;
734
735 Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
736 Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
737 Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
738
739 /*
740 * set sign bit of result of multiply
741 */
742 if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
743 Dbl_setzerop1(resultp1);
744 else
745 Dbl_setnegativezerop1(resultp1);
746
747 /*
748 * Generate multiply exponent
749 */
750 mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
751
752 /*
753 * check first operand for NaN's or infinity
754 */
755 if (Dbl_isinfinity_exponent(opnd1p1)) {
756 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
757 if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
758 Dbl_isnotnan(opnd3p1,opnd3p2)) {
759 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
760 /*
761 * invalid since operands are infinity
762 * and zero
763 */
764 if (Is_invalidtrap_enabled())
765 return(OPC_2E_INVALIDEXCEPTION);
766 Set_invalidflag();
767 Dbl_makequietnan(resultp1,resultp2);
768 Dbl_copytoptr(resultp1,resultp2,dstptr);
769 return(NOEXCEPTION);
770 }
771 /*
772 * Check third operand for infinity with a
773 * sign opposite of the multiply result
774 */
775 if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
776 (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
777 /*
778 * invalid since attempting a magnitude
779 * subtraction of infinities
780 */
781 if (Is_invalidtrap_enabled())
782 return(OPC_2E_INVALIDEXCEPTION);
783 Set_invalidflag();
784 Dbl_makequietnan(resultp1,resultp2);
785 Dbl_copytoptr(resultp1,resultp2,dstptr);
786 return(NOEXCEPTION);
787 }
788
789 /*
790 * return infinity
791 */
792 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
793 Dbl_copytoptr(resultp1,resultp2,dstptr);
794 return(NOEXCEPTION);
795 }
796 }
797 else {
798 /*
799 * is NaN; signaling or quiet?
800 */
801 if (Dbl_isone_signaling(opnd1p1)) {
802 /* trap if INVALIDTRAP enabled */
803 if (Is_invalidtrap_enabled())
804 return(OPC_2E_INVALIDEXCEPTION);
805 /* make NaN quiet */
806 Set_invalidflag();
807 Dbl_set_quiet(opnd1p1);
808 }
809 /*
810 * is second operand a signaling NaN?
811 */
812 else if (Dbl_is_signalingnan(opnd2p1)) {
813 /* trap if INVALIDTRAP enabled */
814 if (Is_invalidtrap_enabled())
815 return(OPC_2E_INVALIDEXCEPTION);
816 /* make NaN quiet */
817 Set_invalidflag();
818 Dbl_set_quiet(opnd2p1);
819 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
820 return(NOEXCEPTION);
821 }
822 /*
823 * is third operand a signaling NaN?
824 */
825 else if (Dbl_is_signalingnan(opnd3p1)) {
826 /* trap if INVALIDTRAP enabled */
827 if (Is_invalidtrap_enabled())
828 return(OPC_2E_INVALIDEXCEPTION);
829 /* make NaN quiet */
830 Set_invalidflag();
831 Dbl_set_quiet(opnd3p1);
832 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
833 return(NOEXCEPTION);
834 }
835 /*
836 * return quiet NaN
837 */
838 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
839 return(NOEXCEPTION);
840 }
841 }
842
843 /*
844 * check second operand for NaN's or infinity
845 */
846 if (Dbl_isinfinity_exponent(opnd2p1)) {
847 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
848 if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
849 if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
850 /*
851 * invalid since multiply operands are
852 * zero & infinity
853 */
854 if (Is_invalidtrap_enabled())
855 return(OPC_2E_INVALIDEXCEPTION);
856 Set_invalidflag();
857 Dbl_makequietnan(opnd2p1,opnd2p2);
858 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
859 return(NOEXCEPTION);
860 }
861
862 /*
863 * Check third operand for infinity with a
864 * sign opposite of the multiply result
865 */
866 if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
867 (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
868 /*
869 * invalid since attempting a magnitude
870 * subtraction of infinities
871 */
872 if (Is_invalidtrap_enabled())
873 return(OPC_2E_INVALIDEXCEPTION);
874 Set_invalidflag();
875 Dbl_makequietnan(resultp1,resultp2);
876 Dbl_copytoptr(resultp1,resultp2,dstptr);
877 return(NOEXCEPTION);
878 }
879
880 /*
881 * return infinity
882 */
883 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
884 Dbl_copytoptr(resultp1,resultp2,dstptr);
885 return(NOEXCEPTION);
886 }
887 }
888 else {
889 /*
890 * is NaN; signaling or quiet?
891 */
892 if (Dbl_isone_signaling(opnd2p1)) {
893 /* trap if INVALIDTRAP enabled */
894 if (Is_invalidtrap_enabled())
895 return(OPC_2E_INVALIDEXCEPTION);
896 /* make NaN quiet */
897 Set_invalidflag();
898 Dbl_set_quiet(opnd2p1);
899 }
900 /*
901 * is third operand a signaling NaN?
902 */
903 else if (Dbl_is_signalingnan(opnd3p1)) {
904 /* trap if INVALIDTRAP enabled */
905 if (Is_invalidtrap_enabled())
906 return(OPC_2E_INVALIDEXCEPTION);
907 /* make NaN quiet */
908 Set_invalidflag();
909 Dbl_set_quiet(opnd3p1);
910 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
911 return(NOEXCEPTION);
912 }
913 /*
914 * return quiet NaN
915 */
916 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
917 return(NOEXCEPTION);
918 }
919 }
920
921 /*
922 * check third operand for NaN's or infinity
923 */
924 if (Dbl_isinfinity_exponent(opnd3p1)) {
925 if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
926 /* return infinity */
927 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
928 return(NOEXCEPTION);
929 } else {
930 /*
931 * is NaN; signaling or quiet?
932 */
933 if (Dbl_isone_signaling(opnd3p1)) {
934 /* trap if INVALIDTRAP enabled */
935 if (Is_invalidtrap_enabled())
936 return(OPC_2E_INVALIDEXCEPTION);
937 /* make NaN quiet */
938 Set_invalidflag();
939 Dbl_set_quiet(opnd3p1);
940 }
941 /*
942 * return quiet NaN
943 */
944 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
945 return(NOEXCEPTION);
946 }
947 }
948
949 /*
950 * Generate multiply mantissa
951 */
952 if (Dbl_isnotzero_exponent(opnd1p1)) {
953 /* set hidden bit */
954 Dbl_clear_signexponent_set_hidden(opnd1p1);
955 }
956 else {
957 /* check for zero */
958 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
959 /*
960 * Perform the add opnd3 with zero here.
961 */
962 if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
963 if (Is_rounding_mode(ROUNDMINUS)) {
964 Dbl_or_signs(opnd3p1,resultp1);
965 } else {
966 Dbl_and_signs(opnd3p1,resultp1);
967 }
968 }
969 /*
970 * Now let's check for trapped underflow case.
971 */
972 else if (Dbl_iszero_exponent(opnd3p1) &&
973 Is_underflowtrap_enabled()) {
974 /* need to normalize results mantissa */
975 sign_save = Dbl_signextendedsign(opnd3p1);
976 result_exponent = 0;
977 Dbl_leftshiftby1(opnd3p1,opnd3p2);
978 Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
979 Dbl_set_sign(opnd3p1,/*using*/sign_save);
980 Dbl_setwrapped_exponent(opnd3p1,result_exponent,
981 unfl);
982 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
983 /* inexact = FALSE */
984 return(OPC_2E_UNDERFLOWEXCEPTION);
985 }
986 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
987 return(NOEXCEPTION);
988 }
989 /* is denormalized, adjust exponent */
990 Dbl_clear_signexponent(opnd1p1);
991 Dbl_leftshiftby1(opnd1p1,opnd1p2);
992 Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
993 }
994 /* opnd2 needs to have hidden bit set with msb in hidden bit */
995 if (Dbl_isnotzero_exponent(opnd2p1)) {
996 Dbl_clear_signexponent_set_hidden(opnd2p1);
997 }
998 else {
999 /* check for zero */
1000 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
1001 /*
1002 * Perform the add opnd3 with zero here.
1003 */
1004 if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
1005 if (Is_rounding_mode(ROUNDMINUS)) {
1006 Dbl_or_signs(opnd3p1,resultp1);
1007 } else {
1008 Dbl_and_signs(opnd3p1,resultp1);
1009 }
1010 }
1011 /*
1012 * Now let's check for trapped underflow case.
1013 */
1014 else if (Dbl_iszero_exponent(opnd3p1) &&
1015 Is_underflowtrap_enabled()) {
1016 /* need to normalize results mantissa */
1017 sign_save = Dbl_signextendedsign(opnd3p1);
1018 result_exponent = 0;
1019 Dbl_leftshiftby1(opnd3p1,opnd3p2);
1020 Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
1021 Dbl_set_sign(opnd3p1,/*using*/sign_save);
1022 Dbl_setwrapped_exponent(opnd3p1,result_exponent,
1023 unfl);
1024 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
1025 /* inexact = FALSE */
1026 return(OPC_2E_UNDERFLOWEXCEPTION);
1027 }
1028 Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
1029 return(NOEXCEPTION);
1030 }
1031 /* is denormalized; want to normalize */
1032 Dbl_clear_signexponent(opnd2p1);
1033 Dbl_leftshiftby1(opnd2p1,opnd2p2);
1034 Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
1035 }
1036
1037 /* Multiply the first two source mantissas together */
1038
1039 /*
1040 * The intermediate result will be kept in tmpres,
1041 * which needs enough room for 106 bits of mantissa,
1042 * so lets call it a Double extended.
1043 */
1044 Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
1045
1046 /*
1047 * Four bits at a time are inspected in each loop, and a
1048 * simple shift and add multiply algorithm is used.
1049 */
1050 for (count = DBL_P-1; count >= 0; count -= 4) {
1051 Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
1052 if (Dbit28p2(opnd1p2)) {
1053 /* Fourword_add should be an ADD followed by 3 ADDC's */
1054 Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
1055 opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
1056 }
1057 if (Dbit29p2(opnd1p2)) {
1058 Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
1059 opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
1060 }
1061 if (Dbit30p2(opnd1p2)) {
1062 Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
1063 opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
1064 }
1065 if (Dbit31p2(opnd1p2)) {
1066 Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
1067 opnd2p1, opnd2p2, 0, 0);
1068 }
1069 Dbl_rightshiftby4(opnd1p1,opnd1p2);
1070 }
1071 if (Is_dexthiddenoverflow(tmpresp1)) {
1072 /* result mantissa >= 2 (mantissa overflow) */
1073 mpy_exponent++;
1074 Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
1075 }
1076
1077 /*
1078 * Restore the sign of the mpy result which was saved in resultp1.
1079 * The exponent will continue to be kept in mpy_exponent.
1080 */
1081 Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
1082
1083 /*
1084 * No rounding is required, since the result of the multiply
1085 * is exact in the extended format.
1086 */
1087
1088 /*
1089 * Now we are ready to perform the add portion of the operation.
1090 *
1091 * The exponents need to be kept as integers for now, since the
1092 * multiply result might not fit into the exponent field. We
1093 * can't overflow or underflow because of this yet, since the
1094 * add could bring the final result back into range.
1095 */
1096 add_exponent = Dbl_exponent(opnd3p1);
1097
1098 /*
1099 * Check for denormalized or zero add operand.
1100 */
1101 if (add_exponent == 0) {
1102 /* check for zero */
1103 if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
1104 /* right is zero */
1105 /* Left can't be zero and must be result.
1106 *
1107 * The final result is now in tmpres and mpy_exponent,
1108 * and needs to be rounded and squeezed back into
1109 * double precision format from double extended.
1110 */
1111 result_exponent = mpy_exponent;
1112 Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
1113 resultp1,resultp2,resultp3,resultp4);
1114 sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
1115 goto round;
1116 }
1117
1118 /*
1119 * Neither are zeroes.
1120 * Adjust exponent and normalize add operand.
1121 */
1122 sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */
1123 Dbl_clear_signexponent(opnd3p1);
1124 Dbl_leftshiftby1(opnd3p1,opnd3p2);
1125 Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
1126 Dbl_set_sign(opnd3p1,sign_save); /* restore sign */
1127 } else {
1128 Dbl_clear_exponent_set_hidden(opnd3p1);
1129 }
1130 /*
1131 * Copy opnd3 to the double extended variable called right.
1132 */
1133 Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
1134
1135 /*
1136 * A zero "save" helps discover equal operands (for later),
1137 * and is used in swapping operands (if needed).
1138 */
1139 Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
1140
1141 /*
1142 * Compare magnitude of operands.
1143 */
1144 Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
1145 Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
1146 if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
1147 Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
1148 /*
1149 * Set the left operand to the larger one by XOR swap.
1150 * First finish the first word "save".
1151 */
1152 Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
1153 Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
1154 Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
1155 rightp2,rightp3,rightp4);
1156 /* also setup exponents used in rest of routine */
1157 diff_exponent = add_exponent - mpy_exponent;
1158 result_exponent = add_exponent;
1159 } else {
1160 /* also setup exponents used in rest of routine */
1161 diff_exponent = mpy_exponent - add_exponent;
1162 result_exponent = mpy_exponent;
1163 }
1164 /* Invariant: left is not smaller than right. */
1165
1166 /*
1167 * Special case alignment of operands that would force alignment
1168 * beyond the extent of the extension. A further optimization
1169 * could special case this but only reduces the path length for
1170 * this infrequent case.
1171 */
1172 if (diff_exponent > DBLEXT_THRESHOLD) {
1173 diff_exponent = DBLEXT_THRESHOLD;
1174 }
1175
1176 /* Align right operand by shifting it to the right */
1177 Dblext_clear_sign(rightp1);
1178 Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
1179 /*shifted by*/diff_exponent);
1180
1181 /* Treat sum and difference of the operands separately. */
1182 if ((int)save < 0) {
1183 /*
1184 * Difference of the two operands. Overflow can occur if the
1185 * multiply overflowed. A borrow can occur out of the hidden
1186 * bit and force a post normalization phase.
1187 */
1188 Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
1189 rightp1,rightp2,rightp3,rightp4,
1190 resultp1,resultp2,resultp3,resultp4);
1191 sign_save = Dbl_signextendedsign(resultp1);
1192 if (Dbl_iszero_hidden(resultp1)) {
1193 /* Handle normalization */
1194 /* A straight foward algorithm would now shift the
1195 * result and extension left until the hidden bit
1196 * becomes one. Not all of the extension bits need
1197 * participate in the shift. Only the two most
1198 * significant bits (round and guard) are needed.
1199 * If only a single shift is needed then the guard
1200 * bit becomes a significant low order bit and the
1201 * extension must participate in the rounding.
1202 * If more than a single shift is needed, then all
1203 * bits to the right of the guard bit are zeros,
1204 * and the guard bit may or may not be zero. */
1205 Dblext_leftshiftby1(resultp1,resultp2,resultp3,
1206 resultp4);
1207
1208 /* Need to check for a zero result. The sign and
1209 * exponent fields have already been zeroed. The more
1210 * efficient test of the full object can be used.
1211 */
1212 if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) {
1213 /* Must have been "x-x" or "x+(-x)". */
1214 if (Is_rounding_mode(ROUNDMINUS))
1215 Dbl_setone_sign(resultp1);
1216 Dbl_copytoptr(resultp1,resultp2,dstptr);
1217 return(NOEXCEPTION);
1218 }
1219 result_exponent--;
1220
1221 /* Look to see if normalization is finished. */
1222 if (Dbl_isone_hidden(resultp1)) {
1223 /* No further normalization is needed */
1224 goto round;
1225 }
1226
1227 /* Discover first one bit to determine shift amount.
1228 * Use a modified binary search. We have already
1229 * shifted the result one position right and still
1230 * not found a one so the remainder of the extension
1231 * must be zero and simplifies rounding. */
1232 /* Scan bytes */
1233 while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
1234 Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
1235 result_exponent -= 8;
1236 }
1237 /* Now narrow it down to the nibble */
1238 if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
1239 /* The lower nibble contains the
1240 * normalizing one */
1241 Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
1242 result_exponent -= 4;
1243 }
1244 /* Select case where first bit is set (already
1245 * normalized) otherwise select the proper shift. */
1246 jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
1247 if (jumpsize <= 7) switch(jumpsize) {
1248 case 1:
1249 Dblext_leftshiftby3(resultp1,resultp2,resultp3,
1250 resultp4);
1251 result_exponent -= 3;
1252 break;
1253 case 2:
1254 case 3:
1255 Dblext_leftshiftby2(resultp1,resultp2,resultp3,
1256 resultp4);
1257 result_exponent -= 2;
1258 break;
1259 case 4:
1260 case 5:
1261 case 6:
1262 case 7:
1263 Dblext_leftshiftby1(resultp1,resultp2,resultp3,
1264 resultp4);
1265 result_exponent -= 1;
1266 break;
1267 }
1268 } /* end if (hidden...)... */
1269 /* Fall through and round */
1270 } /* end if (save < 0)... */
1271 else {
1272 /* Add magnitudes */
1273 Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
1274 rightp1,rightp2,rightp3,rightp4,
1275 /*to*/resultp1,resultp2,resultp3,resultp4);
1276 sign_save = Dbl_signextendedsign(resultp1);
1277 if (Dbl_isone_hiddenoverflow(resultp1)) {
1278 /* Prenormalization required. */
1279 Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
1280 resultp4);
1281 result_exponent++;
1282 } /* end if hiddenoverflow... */
1283 } /* end else ...add magnitudes... */
1284
1285 /* Round the result. If the extension and lower two words are
1286 * all zeros, then the result is exact. Otherwise round in the
1287 * correct direction. Underflow is possible. If a postnormalization
1288 * is necessary, then the mantissa is all zeros so no shift is needed.
1289 */
1290 round:
1291 if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
1292 Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
1293 result_exponent,is_tiny);
1294 }
1295 Dbl_set_sign(resultp1,/*using*/sign_save);
1296 if (Dblext_isnotzero_mantissap3(resultp3) ||
1297 Dblext_isnotzero_mantissap4(resultp4)) {
1298 inexact = TRUE;
1299 switch(Rounding_mode()) {
1300 case ROUNDNEAREST: /* The default. */
1301 if (Dblext_isone_highp3(resultp3)) {
1302 /* at least 1/2 ulp */
1303 if (Dblext_isnotzero_low31p3(resultp3) ||
1304 Dblext_isnotzero_mantissap4(resultp4) ||
1305 Dblext_isone_lowp2(resultp2)) {
1306 /* either exactly half way and odd or
1307 * more than 1/2ulp */
1308 Dbl_increment(resultp1,resultp2);
1309 }
1310 }
1311 break;
1312
1313 case ROUNDPLUS:
1314 if (Dbl_iszero_sign(resultp1)) {
1315 /* Round up positive results */
1316 Dbl_increment(resultp1,resultp2);
1317 }
1318 break;
1319
1320 case ROUNDMINUS:
1321 if (Dbl_isone_sign(resultp1)) {
1322 /* Round down negative results */
1323 Dbl_increment(resultp1,resultp2);
1324 }
1325
1326 case ROUNDZERO:;
1327 /* truncate is simple */
1328 } /* end switch... */
1329 if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
1330 }
1331 if (result_exponent >= DBL_INFINITY_EXPONENT) {
1332 /* Overflow */
1333 if (Is_overflowtrap_enabled()) {
1334 /*
1335 * Adjust bias of result
1336 */
1337 Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
1338 Dbl_copytoptr(resultp1,resultp2,dstptr);
1339 if (inexact)
1340 if (Is_inexacttrap_enabled())
1341 return (OPC_2E_OVERFLOWEXCEPTION |
1342 OPC_2E_INEXACTEXCEPTION);
1343 else Set_inexactflag();
1344 return (OPC_2E_OVERFLOWEXCEPTION);
1345 }
1346 inexact = TRUE;
1347 Set_overflowflag();
1348 Dbl_setoverflow(resultp1,resultp2);
1349 } else if (result_exponent <= 0) { /* underflow case */
1350 if (Is_underflowtrap_enabled()) {
1351 /*
1352 * Adjust bias of result
1353 */
1354 Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
1355 Dbl_copytoptr(resultp1,resultp2,dstptr);
1356 if (inexact)
1357 if (Is_inexacttrap_enabled())
1358 return (OPC_2E_UNDERFLOWEXCEPTION |
1359 OPC_2E_INEXACTEXCEPTION);
1360 else Set_inexactflag();
1361 return(OPC_2E_UNDERFLOWEXCEPTION);
1362 }
1363 else if (inexact && is_tiny) Set_underflowflag();
1364 }
1365 else Dbl_set_exponent(resultp1,result_exponent);
1366 Dbl_copytoptr(resultp1,resultp2,dstptr);
1367 if (inexact)
1368 if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
1369 else Set_inexactflag();
1370 return(NOEXCEPTION);
1371}
1372
1373/*
1374 * Single Floating-point Multiply Fused Add
1375 */
1376
1377sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
1378
1379sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
1380unsigned int *status;
1381{
1382 unsigned int opnd1, opnd2, opnd3;
1383 register unsigned int tmpresp1, tmpresp2;
1384 unsigned int rightp1, rightp2;
1385 unsigned int resultp1, resultp2 = 0;
1386 register int mpy_exponent, add_exponent, count;
1387 boolean inexact = FALSE, is_tiny = FALSE;
1388
1389 unsigned int signlessleft1, signlessright1, save;
1390 register int result_exponent, diff_exponent;
1391 int sign_save, jumpsize;
1392
1393 Sgl_copyfromptr(src1ptr,opnd1);
1394 Sgl_copyfromptr(src2ptr,opnd2);
1395 Sgl_copyfromptr(src3ptr,opnd3);
1396
1397 /*
1398 * set sign bit of result of multiply
1399 */
1400 if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2))
1401 Sgl_setnegativezero(resultp1);
1402 else Sgl_setzero(resultp1);
1403
1404 /*
1405 * Generate multiply exponent
1406 */
1407 mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
1408
1409 /*
1410 * check first operand for NaN's or infinity
1411 */
1412 if (Sgl_isinfinity_exponent(opnd1)) {
1413 if (Sgl_iszero_mantissa(opnd1)) {
1414 if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
1415 if (Sgl_iszero_exponentmantissa(opnd2)) {
1416 /*
1417 * invalid since operands are infinity
1418 * and zero
1419 */
1420 if (Is_invalidtrap_enabled())
1421 return(OPC_2E_INVALIDEXCEPTION);
1422 Set_invalidflag();
1423 Sgl_makequietnan(resultp1);
1424 Sgl_copytoptr(resultp1,dstptr);
1425 return(NOEXCEPTION);
1426 }
1427 /*
1428 * Check third operand for infinity with a
1429 * sign opposite of the multiply result
1430 */
1431 if (Sgl_isinfinity(opnd3) &&
1432 (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
1433 /*
1434 * invalid since attempting a magnitude
1435 * subtraction of infinities
1436 */
1437 if (Is_invalidtrap_enabled())
1438 return(OPC_2E_INVALIDEXCEPTION);
1439 Set_invalidflag();
1440 Sgl_makequietnan(resultp1);
1441 Sgl_copytoptr(resultp1,dstptr);
1442 return(NOEXCEPTION);
1443 }
1444
1445 /*
1446 * return infinity
1447 */
1448 Sgl_setinfinity_exponentmantissa(resultp1);
1449 Sgl_copytoptr(resultp1,dstptr);
1450 return(NOEXCEPTION);
1451 }
1452 }
1453 else {
1454 /*
1455 * is NaN; signaling or quiet?
1456 */
1457 if (Sgl_isone_signaling(opnd1)) {
1458 /* trap if INVALIDTRAP enabled */
1459 if (Is_invalidtrap_enabled())
1460 return(OPC_2E_INVALIDEXCEPTION);
1461 /* make NaN quiet */
1462 Set_invalidflag();
1463 Sgl_set_quiet(opnd1);
1464 }
1465 /*
1466 * is second operand a signaling NaN?
1467 */
1468 else if (Sgl_is_signalingnan(opnd2)) {
1469 /* trap if INVALIDTRAP enabled */
1470 if (Is_invalidtrap_enabled())
1471 return(OPC_2E_INVALIDEXCEPTION);
1472 /* make NaN quiet */
1473 Set_invalidflag();
1474 Sgl_set_quiet(opnd2);
1475 Sgl_copytoptr(opnd2,dstptr);
1476 return(NOEXCEPTION);
1477 }
1478 /*
1479 * is third operand a signaling NaN?
1480 */
1481 else if (Sgl_is_signalingnan(opnd3)) {
1482 /* trap if INVALIDTRAP enabled */
1483 if (Is_invalidtrap_enabled())
1484 return(OPC_2E_INVALIDEXCEPTION);
1485 /* make NaN quiet */
1486 Set_invalidflag();
1487 Sgl_set_quiet(opnd3);
1488 Sgl_copytoptr(opnd3,dstptr);
1489 return(NOEXCEPTION);
1490 }
1491 /*
1492 * return quiet NaN
1493 */
1494 Sgl_copytoptr(opnd1,dstptr);
1495 return(NOEXCEPTION);
1496 }
1497 }
1498
1499 /*
1500 * check second operand for NaN's or infinity
1501 */
1502 if (Sgl_isinfinity_exponent(opnd2)) {
1503 if (Sgl_iszero_mantissa(opnd2)) {
1504 if (Sgl_isnotnan(opnd3)) {
1505 if (Sgl_iszero_exponentmantissa(opnd1)) {
1506 /*
1507 * invalid since multiply operands are
1508 * zero & infinity
1509 */
1510 if (Is_invalidtrap_enabled())
1511 return(OPC_2E_INVALIDEXCEPTION);
1512 Set_invalidflag();
1513 Sgl_makequietnan(opnd2);
1514 Sgl_copytoptr(opnd2,dstptr);
1515 return(NOEXCEPTION);
1516 }
1517
1518 /*
1519 * Check third operand for infinity with a
1520 * sign opposite of the multiply result
1521 */
1522 if (Sgl_isinfinity(opnd3) &&
1523 (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
1524 /*
1525 * invalid since attempting a magnitude
1526 * subtraction of infinities
1527 */
1528 if (Is_invalidtrap_enabled())
1529 return(OPC_2E_INVALIDEXCEPTION);
1530 Set_invalidflag();
1531 Sgl_makequietnan(resultp1);
1532 Sgl_copytoptr(resultp1,dstptr);
1533 return(NOEXCEPTION);
1534 }
1535
1536 /*
1537 * return infinity
1538 */
1539 Sgl_setinfinity_exponentmantissa(resultp1);
1540 Sgl_copytoptr(resultp1,dstptr);
1541 return(NOEXCEPTION);
1542 }
1543 }
1544 else {
1545 /*
1546 * is NaN; signaling or quiet?
1547 */
1548 if (Sgl_isone_signaling(opnd2)) {
1549 /* trap if INVALIDTRAP enabled */
1550 if (Is_invalidtrap_enabled())
1551 return(OPC_2E_INVALIDEXCEPTION);
1552 /* make NaN quiet */
1553 Set_invalidflag();
1554 Sgl_set_quiet(opnd2);
1555 }
1556 /*
1557 * is third operand a signaling NaN?
1558 */
1559 else if (Sgl_is_signalingnan(opnd3)) {
1560 /* trap if INVALIDTRAP enabled */
1561 if (Is_invalidtrap_enabled())
1562 return(OPC_2E_INVALIDEXCEPTION);
1563 /* make NaN quiet */
1564 Set_invalidflag();
1565 Sgl_set_quiet(opnd3);
1566 Sgl_copytoptr(opnd3,dstptr);
1567 return(NOEXCEPTION);
1568 }
1569 /*
1570 * return quiet NaN
1571 */
1572 Sgl_copytoptr(opnd2,dstptr);
1573 return(NOEXCEPTION);
1574 }
1575 }
1576
1577 /*
1578 * check third operand for NaN's or infinity
1579 */
1580 if (Sgl_isinfinity_exponent(opnd3)) {
1581 if (Sgl_iszero_mantissa(opnd3)) {
1582 /* return infinity */
1583 Sgl_copytoptr(opnd3,dstptr);
1584 return(NOEXCEPTION);
1585 } else {
1586 /*
1587 * is NaN; signaling or quiet?
1588 */
1589 if (Sgl_isone_signaling(opnd3)) {
1590 /* trap if INVALIDTRAP enabled */
1591 if (Is_invalidtrap_enabled())
1592 return(OPC_2E_INVALIDEXCEPTION);
1593 /* make NaN quiet */
1594 Set_invalidflag();
1595 Sgl_set_quiet(opnd3);
1596 }
1597 /*
1598 * return quiet NaN
1599 */
1600 Sgl_copytoptr(opnd3,dstptr);
1601 return(NOEXCEPTION);
1602 }
1603 }
1604
1605 /*
1606 * Generate multiply mantissa
1607 */
1608 if (Sgl_isnotzero_exponent(opnd1)) {
1609 /* set hidden bit */
1610 Sgl_clear_signexponent_set_hidden(opnd1);
1611 }
1612 else {
1613 /* check for zero */
1614 if (Sgl_iszero_mantissa(opnd1)) {
1615 /*
1616 * Perform the add opnd3 with zero here.
1617 */
1618 if (Sgl_iszero_exponentmantissa(opnd3)) {
1619 if (Is_rounding_mode(ROUNDMINUS)) {
1620 Sgl_or_signs(opnd3,resultp1);
1621 } else {
1622 Sgl_and_signs(opnd3,resultp1);
1623 }
1624 }
1625 /*
1626 * Now let's check for trapped underflow case.
1627 */
1628 else if (Sgl_iszero_exponent(opnd3) &&
1629 Is_underflowtrap_enabled()) {
1630 /* need to normalize results mantissa */
1631 sign_save = Sgl_signextendedsign(opnd3);
1632 result_exponent = 0;
1633 Sgl_leftshiftby1(opnd3);
1634 Sgl_normalize(opnd3,result_exponent);
1635 Sgl_set_sign(opnd3,/*using*/sign_save);
1636 Sgl_setwrapped_exponent(opnd3,result_exponent,
1637 unfl);
1638 Sgl_copytoptr(opnd3,dstptr);
1639 /* inexact = FALSE */
1640 return(OPC_2E_UNDERFLOWEXCEPTION);
1641 }
1642 Sgl_copytoptr(opnd3,dstptr);
1643 return(NOEXCEPTION);
1644 }
1645 /* is denormalized, adjust exponent */
1646 Sgl_clear_signexponent(opnd1);
1647 Sgl_leftshiftby1(opnd1);
1648 Sgl_normalize(opnd1,mpy_exponent);
1649 }
1650 /* opnd2 needs to have hidden bit set with msb in hidden bit */
1651 if (Sgl_isnotzero_exponent(opnd2)) {
1652 Sgl_clear_signexponent_set_hidden(opnd2);
1653 }
1654 else {
1655 /* check for zero */
1656 if (Sgl_iszero_mantissa(opnd2)) {
1657 /*
1658 * Perform the add opnd3 with zero here.
1659 */
1660 if (Sgl_iszero_exponentmantissa(opnd3)) {
1661 if (Is_rounding_mode(ROUNDMINUS)) {
1662 Sgl_or_signs(opnd3,resultp1);
1663 } else {
1664 Sgl_and_signs(opnd3,resultp1);
1665 }
1666 }
1667 /*
1668 * Now let's check for trapped underflow case.
1669 */
1670 else if (Sgl_iszero_exponent(opnd3) &&
1671 Is_underflowtrap_enabled()) {
1672 /* need to normalize results mantissa */
1673 sign_save = Sgl_signextendedsign(opnd3);
1674 result_exponent = 0;
1675 Sgl_leftshiftby1(opnd3);
1676 Sgl_normalize(opnd3,result_exponent);
1677 Sgl_set_sign(opnd3,/*using*/sign_save);
1678 Sgl_setwrapped_exponent(opnd3,result_exponent,
1679 unfl);
1680 Sgl_copytoptr(opnd3,dstptr);
1681 /* inexact = FALSE */
1682 return(OPC_2E_UNDERFLOWEXCEPTION);
1683 }
1684 Sgl_copytoptr(opnd3,dstptr);
1685 return(NOEXCEPTION);
1686 }
1687 /* is denormalized; want to normalize */
1688 Sgl_clear_signexponent(opnd2);
1689 Sgl_leftshiftby1(opnd2);
1690 Sgl_normalize(opnd2,mpy_exponent);
1691 }
1692
1693 /* Multiply the first two source mantissas together */
1694
1695 /*
1696 * The intermediate result will be kept in tmpres,
1697 * which needs enough room for 106 bits of mantissa,
1698 * so lets call it a Double extended.
1699 */
1700 Sglext_setzero(tmpresp1,tmpresp2);
1701
1702 /*
1703 * Four bits at a time are inspected in each loop, and a
1704 * simple shift and add multiply algorithm is used.
1705 */
1706 for (count = SGL_P-1; count >= 0; count -= 4) {
1707 Sglext_rightshiftby4(tmpresp1,tmpresp2);
1708 if (Sbit28(opnd1)) {
1709 /* Twoword_add should be an ADD followed by 2 ADDC's */
1710 Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
1711 }
1712 if (Sbit29(opnd1)) {
1713 Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
1714 }
1715 if (Sbit30(opnd1)) {
1716 Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
1717 }
1718 if (Sbit31(opnd1)) {
1719 Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
1720 }
1721 Sgl_rightshiftby4(opnd1);
1722 }
1723 if (Is_sexthiddenoverflow(tmpresp1)) {
1724 /* result mantissa >= 2 (mantissa overflow) */
1725 mpy_exponent++;
1726 Sglext_rightshiftby4(tmpresp1,tmpresp2);
1727 } else {
1728 Sglext_rightshiftby3(tmpresp1,tmpresp2);
1729 }
1730
1731 /*
1732 * Restore the sign of the mpy result which was saved in resultp1.
1733 * The exponent will continue to be kept in mpy_exponent.
1734 */
1735 Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
1736
1737 /*
1738 * No rounding is required, since the result of the multiply
1739 * is exact in the extended format.
1740 */
1741
1742 /*
1743 * Now we are ready to perform the add portion of the operation.
1744 *
1745 * The exponents need to be kept as integers for now, since the
1746 * multiply result might not fit into the exponent field. We
1747 * can't overflow or underflow because of this yet, since the
1748 * add could bring the final result back into range.
1749 */
1750 add_exponent = Sgl_exponent(opnd3);
1751
1752 /*
1753 * Check for denormalized or zero add operand.
1754 */
1755 if (add_exponent == 0) {
1756 /* check for zero */
1757 if (Sgl_iszero_mantissa(opnd3)) {
1758 /* right is zero */
1759 /* Left can't be zero and must be result.
1760 *
1761 * The final result is now in tmpres and mpy_exponent,
1762 * and needs to be rounded and squeezed back into
1763 * double precision format from double extended.
1764 */
1765 result_exponent = mpy_exponent;
1766 Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
1767 sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
1768 goto round;
1769 }
1770
1771 /*
1772 * Neither are zeroes.
1773 * Adjust exponent and normalize add operand.
1774 */
1775 sign_save = Sgl_signextendedsign(opnd3); /* save sign */
1776 Sgl_clear_signexponent(opnd3);
1777 Sgl_leftshiftby1(opnd3);
1778 Sgl_normalize(opnd3,add_exponent);
1779 Sgl_set_sign(opnd3,sign_save); /* restore sign */
1780 } else {
1781 Sgl_clear_exponent_set_hidden(opnd3);
1782 }
1783 /*
1784 * Copy opnd3 to the double extended variable called right.
1785 */
1786 Sgl_copyto_sglext(opnd3,rightp1,rightp2);
1787
1788 /*
1789 * A zero "save" helps discover equal operands (for later),
1790 * and is used in swapping operands (if needed).
1791 */
1792 Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
1793
1794 /*
1795 * Compare magnitude of operands.
1796 */
1797 Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
1798 Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
1799 if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
1800 Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
1801 /*
1802 * Set the left operand to the larger one by XOR swap.
1803 * First finish the first word "save".
1804 */
1805 Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
1806 Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
1807 Sglext_swap_lower(tmpresp2,rightp2);
1808 /* also setup exponents used in rest of routine */
1809 diff_exponent = add_exponent - mpy_exponent;
1810 result_exponent = add_exponent;
1811 } else {
1812 /* also setup exponents used in rest of routine */
1813 diff_exponent = mpy_exponent - add_exponent;
1814 result_exponent = mpy_exponent;
1815 }
1816 /* Invariant: left is not smaller than right. */
1817
1818 /*
1819 * Special case alignment of operands that would force alignment
1820 * beyond the extent of the extension. A further optimization
1821 * could special case this but only reduces the path length for
1822 * this infrequent case.
1823 */
1824 if (diff_exponent > SGLEXT_THRESHOLD) {
1825 diff_exponent = SGLEXT_THRESHOLD;
1826 }
1827
1828 /* Align right operand by shifting it to the right */
1829 Sglext_clear_sign(rightp1);
1830 Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
1831
1832 /* Treat sum and difference of the operands separately. */
1833 if ((int)save < 0) {
1834 /*
1835 * Difference of the two operands. Overflow can occur if the
1836 * multiply overflowed. A borrow can occur out of the hidden
1837 * bit and force a post normalization phase.
1838 */
1839 Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
1840 resultp1,resultp2);
1841 sign_save = Sgl_signextendedsign(resultp1);
1842 if (Sgl_iszero_hidden(resultp1)) {
1843 /* Handle normalization */
1844 /* A straight foward algorithm would now shift the
1845 * result and extension left until the hidden bit
1846 * becomes one. Not all of the extension bits need
1847 * participate in the shift. Only the two most
1848 * significant bits (round and guard) are needed.
1849 * If only a single shift is needed then the guard
1850 * bit becomes a significant low order bit and the
1851 * extension must participate in the rounding.
1852 * If more than a single shift is needed, then all
1853 * bits to the right of the guard bit are zeros,
1854 * and the guard bit may or may not be zero. */
1855 Sglext_leftshiftby1(resultp1,resultp2);
1856
1857 /* Need to check for a zero result. The sign and
1858 * exponent fields have already been zeroed. The more
1859 * efficient test of the full object can be used.
1860 */
1861 if (Sglext_iszero(resultp1,resultp2)) {
1862 /* Must have been "x-x" or "x+(-x)". */
1863 if (Is_rounding_mode(ROUNDMINUS))
1864 Sgl_setone_sign(resultp1);
1865 Sgl_copytoptr(resultp1,dstptr);
1866 return(NOEXCEPTION);
1867 }
1868 result_exponent--;
1869
1870 /* Look to see if normalization is finished. */
1871 if (Sgl_isone_hidden(resultp1)) {
1872 /* No further normalization is needed */
1873 goto round;
1874 }
1875
1876 /* Discover first one bit to determine shift amount.
1877 * Use a modified binary search. We have already
1878 * shifted the result one position right and still
1879 * not found a one so the remainder of the extension
1880 * must be zero and simplifies rounding. */
1881 /* Scan bytes */
1882 while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
1883 Sglext_leftshiftby8(resultp1,resultp2);
1884 result_exponent -= 8;
1885 }
1886 /* Now narrow it down to the nibble */
1887 if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
1888 /* The lower nibble contains the
1889 * normalizing one */
1890 Sglext_leftshiftby4(resultp1,resultp2);
1891 result_exponent -= 4;
1892 }
1893 /* Select case where first bit is set (already
1894 * normalized) otherwise select the proper shift. */
1895 jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
1896 if (jumpsize <= 7) switch(jumpsize) {
1897 case 1:
1898 Sglext_leftshiftby3(resultp1,resultp2);
1899 result_exponent -= 3;
1900 break;
1901 case 2:
1902 case 3:
1903 Sglext_leftshiftby2(resultp1,resultp2);
1904 result_exponent -= 2;
1905 break;
1906 case 4:
1907 case 5:
1908 case 6:
1909 case 7:
1910 Sglext_leftshiftby1(resultp1,resultp2);
1911 result_exponent -= 1;
1912 break;
1913 }
1914 } /* end if (hidden...)... */
1915 /* Fall through and round */
1916 } /* end if (save < 0)... */
1917 else {
1918 /* Add magnitudes */
1919 Sglext_addition(tmpresp1,tmpresp2,
1920 rightp1,rightp2, /*to*/resultp1,resultp2);
1921 sign_save = Sgl_signextendedsign(resultp1);
1922 if (Sgl_isone_hiddenoverflow(resultp1)) {
1923 /* Prenormalization required. */
1924 Sglext_arithrightshiftby1(resultp1,resultp2);
1925 result_exponent++;
1926 } /* end if hiddenoverflow... */
1927 } /* end else ...add magnitudes... */
1928
1929 /* Round the result. If the extension and lower two words are
1930 * all zeros, then the result is exact. Otherwise round in the
1931 * correct direction. Underflow is possible. If a postnormalization
1932 * is necessary, then the mantissa is all zeros so no shift is needed.
1933 */
1934 round:
1935 if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
1936 Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
1937 }
1938 Sgl_set_sign(resultp1,/*using*/sign_save);
1939 if (Sglext_isnotzero_mantissap2(resultp2)) {
1940 inexact = TRUE;
1941 switch(Rounding_mode()) {
1942 case ROUNDNEAREST: /* The default. */
1943 if (Sglext_isone_highp2(resultp2)) {
1944 /* at least 1/2 ulp */
1945 if (Sglext_isnotzero_low31p2(resultp2) ||
1946 Sglext_isone_lowp1(resultp1)) {
1947 /* either exactly half way and odd or
1948 * more than 1/2ulp */
1949 Sgl_increment(resultp1);
1950 }
1951 }
1952 break;
1953
1954 case ROUNDPLUS:
1955 if (Sgl_iszero_sign(resultp1)) {
1956 /* Round up positive results */
1957 Sgl_increment(resultp1);
1958 }
1959 break;
1960
1961 case ROUNDMINUS:
1962 if (Sgl_isone_sign(resultp1)) {
1963 /* Round down negative results */
1964 Sgl_increment(resultp1);
1965 }
1966
1967 case ROUNDZERO:;
1968 /* truncate is simple */
1969 } /* end switch... */
1970 if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
1971 }
1972 if (result_exponent >= SGL_INFINITY_EXPONENT) {
1973 /* Overflow */
1974 if (Is_overflowtrap_enabled()) {
1975 /*
1976 * Adjust bias of result
1977 */
1978 Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
1979 Sgl_copytoptr(resultp1,dstptr);
1980 if (inexact)
1981 if (Is_inexacttrap_enabled())
1982 return (OPC_2E_OVERFLOWEXCEPTION |
1983 OPC_2E_INEXACTEXCEPTION);
1984 else Set_inexactflag();
1985 return (OPC_2E_OVERFLOWEXCEPTION);
1986 }
1987 inexact = TRUE;
1988 Set_overflowflag();
1989 Sgl_setoverflow(resultp1);
1990 } else if (result_exponent <= 0) { /* underflow case */
1991 if (Is_underflowtrap_enabled()) {
1992 /*
1993 * Adjust bias of result
1994 */
1995 Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
1996 Sgl_copytoptr(resultp1,dstptr);
1997 if (inexact)
1998 if (Is_inexacttrap_enabled())
1999 return (OPC_2E_UNDERFLOWEXCEPTION |
2000 OPC_2E_INEXACTEXCEPTION);
2001 else Set_inexactflag();
2002 return(OPC_2E_UNDERFLOWEXCEPTION);
2003 }
2004 else if (inexact && is_tiny) Set_underflowflag();
2005 }
2006 else Sgl_set_exponent(resultp1,result_exponent);
2007 Sgl_copytoptr(resultp1,dstptr);
2008 if (inexact)
2009 if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
2010 else Set_inexactflag();
2011 return(NOEXCEPTION);
2012}
2013
2014/*
2015 * Single Floating-point Multiply Negate Fused Add
2016 */
2017
2018sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
2019
2020sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
2021unsigned int *status;
2022{
2023 unsigned int opnd1, opnd2, opnd3;
2024 register unsigned int tmpresp1, tmpresp2;
2025 unsigned int rightp1, rightp2;
2026 unsigned int resultp1, resultp2 = 0;
2027 register int mpy_exponent, add_exponent, count;
2028 boolean inexact = FALSE, is_tiny = FALSE;
2029
2030 unsigned int signlessleft1, signlessright1, save;
2031 register int result_exponent, diff_exponent;
2032 int sign_save, jumpsize;
2033
2034 Sgl_copyfromptr(src1ptr,opnd1);
2035 Sgl_copyfromptr(src2ptr,opnd2);
2036 Sgl_copyfromptr(src3ptr,opnd3);
2037
2038 /*
2039 * set sign bit of result of multiply
2040 */
2041 if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2))
2042 Sgl_setzero(resultp1);
2043 else
2044 Sgl_setnegativezero(resultp1);
2045
2046 /*
2047 * Generate multiply exponent
2048 */
2049 mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
2050
2051 /*
2052 * check first operand for NaN's or infinity
2053 */
2054 if (Sgl_isinfinity_exponent(opnd1)) {
2055 if (Sgl_iszero_mantissa(opnd1)) {
2056 if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
2057 if (Sgl_iszero_exponentmantissa(opnd2)) {
2058 /*
2059 * invalid since operands are infinity
2060 * and zero
2061 */
2062 if (Is_invalidtrap_enabled())
2063 return(OPC_2E_INVALIDEXCEPTION);
2064 Set_invalidflag();
2065 Sgl_makequietnan(resultp1);
2066 Sgl_copytoptr(resultp1,dstptr);
2067 return(NOEXCEPTION);
2068 }
2069 /*
2070 * Check third operand for infinity with a
2071 * sign opposite of the multiply result
2072 */
2073 if (Sgl_isinfinity(opnd3) &&
2074 (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
2075 /*
2076 * invalid since attempting a magnitude
2077 * subtraction of infinities
2078 */
2079 if (Is_invalidtrap_enabled())
2080 return(OPC_2E_INVALIDEXCEPTION);
2081 Set_invalidflag();
2082 Sgl_makequietnan(resultp1);
2083 Sgl_copytoptr(resultp1,dstptr);
2084 return(NOEXCEPTION);
2085 }
2086
2087 /*
2088 * return infinity
2089 */
2090 Sgl_setinfinity_exponentmantissa(resultp1);
2091 Sgl_copytoptr(resultp1,dstptr);
2092 return(NOEXCEPTION);
2093 }
2094 }
2095 else {
2096 /*
2097 * is NaN; signaling or quiet?
2098 */
2099 if (Sgl_isone_signaling(opnd1)) {
2100 /* trap if INVALIDTRAP enabled */
2101 if (Is_invalidtrap_enabled())
2102 return(OPC_2E_INVALIDEXCEPTION);
2103 /* make NaN quiet */
2104 Set_invalidflag();
2105 Sgl_set_quiet(opnd1);
2106 }
2107 /*
2108 * is second operand a signaling NaN?
2109 */
2110 else if (Sgl_is_signalingnan(opnd2)) {
2111 /* trap if INVALIDTRAP enabled */
2112 if (Is_invalidtrap_enabled())
2113 return(OPC_2E_INVALIDEXCEPTION);
2114 /* make NaN quiet */
2115 Set_invalidflag();
2116 Sgl_set_quiet(opnd2);
2117 Sgl_copytoptr(opnd2,dstptr);
2118 return(NOEXCEPTION);
2119 }
2120 /*
2121 * is third operand a signaling NaN?
2122 */
2123 else if (Sgl_is_signalingnan(opnd3)) {
2124 /* trap if INVALIDTRAP enabled */
2125 if (Is_invalidtrap_enabled())
2126 return(OPC_2E_INVALIDEXCEPTION);
2127 /* make NaN quiet */
2128 Set_invalidflag();
2129 Sgl_set_quiet(opnd3);
2130 Sgl_copytoptr(opnd3,dstptr);
2131 return(NOEXCEPTION);
2132 }
2133 /*
2134 * return quiet NaN
2135 */
2136 Sgl_copytoptr(opnd1,dstptr);
2137 return(NOEXCEPTION);
2138 }
2139 }
2140
2141 /*
2142 * check second operand for NaN's or infinity
2143 */
2144 if (Sgl_isinfinity_exponent(opnd2)) {
2145 if (Sgl_iszero_mantissa(opnd2)) {
2146 if (Sgl_isnotnan(opnd3)) {
2147 if (Sgl_iszero_exponentmantissa(opnd1)) {
2148 /*
2149 * invalid since multiply operands are
2150 * zero & infinity
2151 */
2152 if (Is_invalidtrap_enabled())
2153 return(OPC_2E_INVALIDEXCEPTION);
2154 Set_invalidflag();
2155 Sgl_makequietnan(opnd2);
2156 Sgl_copytoptr(opnd2,dstptr);
2157 return(NOEXCEPTION);
2158 }
2159
2160 /*
2161 * Check third operand for infinity with a
2162 * sign opposite of the multiply result
2163 */
2164 if (Sgl_isinfinity(opnd3) &&
2165 (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
2166 /*
2167 * invalid since attempting a magnitude
2168 * subtraction of infinities
2169 */
2170 if (Is_invalidtrap_enabled())
2171 return(OPC_2E_INVALIDEXCEPTION);
2172 Set_invalidflag();
2173 Sgl_makequietnan(resultp1);
2174 Sgl_copytoptr(resultp1,dstptr);
2175 return(NOEXCEPTION);
2176 }
2177
2178 /*
2179 * return infinity
2180 */
2181 Sgl_setinfinity_exponentmantissa(resultp1);
2182 Sgl_copytoptr(resultp1,dstptr);
2183 return(NOEXCEPTION);
2184 }
2185 }
2186 else {
2187 /*
2188 * is NaN; signaling or quiet?
2189 */
2190 if (Sgl_isone_signaling(opnd2)) {
2191 /* trap if INVALIDTRAP enabled */
2192 if (Is_invalidtrap_enabled())
2193 return(OPC_2E_INVALIDEXCEPTION);
2194 /* make NaN quiet */
2195 Set_invalidflag();
2196 Sgl_set_quiet(opnd2);
2197 }
2198 /*
2199 * is third operand a signaling NaN?
2200 */
2201 else if (Sgl_is_signalingnan(opnd3)) {
2202 /* trap if INVALIDTRAP enabled */
2203 if (Is_invalidtrap_enabled())
2204 return(OPC_2E_INVALIDEXCEPTION);
2205 /* make NaN quiet */
2206 Set_invalidflag();
2207 Sgl_set_quiet(opnd3);
2208 Sgl_copytoptr(opnd3,dstptr);
2209 return(NOEXCEPTION);
2210 }
2211 /*
2212 * return quiet NaN
2213 */
2214 Sgl_copytoptr(opnd2,dstptr);
2215 return(NOEXCEPTION);
2216 }
2217 }
2218
2219 /*
2220 * check third operand for NaN's or infinity
2221 */
2222 if (Sgl_isinfinity_exponent(opnd3)) {
2223 if (Sgl_iszero_mantissa(opnd3)) {
2224 /* return infinity */
2225 Sgl_copytoptr(opnd3,dstptr);
2226 return(NOEXCEPTION);
2227 } else {
2228 /*
2229 * is NaN; signaling or quiet?
2230 */
2231 if (Sgl_isone_signaling(opnd3)) {
2232 /* trap if INVALIDTRAP enabled */
2233 if (Is_invalidtrap_enabled())
2234 return(OPC_2E_INVALIDEXCEPTION);
2235 /* make NaN quiet */
2236 Set_invalidflag();
2237 Sgl_set_quiet(opnd3);
2238 }
2239 /*
2240 * return quiet NaN
2241 */
2242 Sgl_copytoptr(opnd3,dstptr);
2243 return(NOEXCEPTION);
2244 }
2245 }
2246
2247 /*
2248 * Generate multiply mantissa
2249 */
2250 if (Sgl_isnotzero_exponent(opnd1)) {
2251 /* set hidden bit */
2252 Sgl_clear_signexponent_set_hidden(opnd1);
2253 }
2254 else {
2255 /* check for zero */
2256 if (Sgl_iszero_mantissa(opnd1)) {
2257 /*
2258 * Perform the add opnd3 with zero here.
2259 */
2260 if (Sgl_iszero_exponentmantissa(opnd3)) {
2261 if (Is_rounding_mode(ROUNDMINUS)) {
2262 Sgl_or_signs(opnd3,resultp1);
2263 } else {
2264 Sgl_and_signs(opnd3,resultp1);
2265 }
2266 }
2267 /*
2268 * Now let's check for trapped underflow case.
2269 */
2270 else if (Sgl_iszero_exponent(opnd3) &&
2271 Is_underflowtrap_enabled()) {
2272 /* need to normalize results mantissa */
2273 sign_save = Sgl_signextendedsign(opnd3);
2274 result_exponent = 0;
2275 Sgl_leftshiftby1(opnd3);
2276 Sgl_normalize(opnd3,result_exponent);
2277 Sgl_set_sign(opnd3,/*using*/sign_save);
2278 Sgl_setwrapped_exponent(opnd3,result_exponent,
2279 unfl);
2280 Sgl_copytoptr(opnd3,dstptr);
2281 /* inexact = FALSE */
2282 return(OPC_2E_UNDERFLOWEXCEPTION);
2283 }
2284 Sgl_copytoptr(opnd3,dstptr);
2285 return(NOEXCEPTION);
2286 }
2287 /* is denormalized, adjust exponent */
2288 Sgl_clear_signexponent(opnd1);
2289 Sgl_leftshiftby1(opnd1);
2290 Sgl_normalize(opnd1,mpy_exponent);
2291 }
2292 /* opnd2 needs to have hidden bit set with msb in hidden bit */
2293 if (Sgl_isnotzero_exponent(opnd2)) {
2294 Sgl_clear_signexponent_set_hidden(opnd2);
2295 }
2296 else {
2297 /* check for zero */
2298 if (Sgl_iszero_mantissa(opnd2)) {
2299 /*
2300 * Perform the add opnd3 with zero here.
2301 */
2302 if (Sgl_iszero_exponentmantissa(opnd3)) {
2303 if (Is_rounding_mode(ROUNDMINUS)) {
2304 Sgl_or_signs(opnd3,resultp1);
2305 } else {
2306 Sgl_and_signs(opnd3,resultp1);
2307 }
2308 }
2309 /*
2310 * Now let's check for trapped underflow case.
2311 */
2312 else if (Sgl_iszero_exponent(opnd3) &&
2313 Is_underflowtrap_enabled()) {
2314 /* need to normalize results mantissa */
2315 sign_save = Sgl_signextendedsign(opnd3);
2316 result_exponent = 0;
2317 Sgl_leftshiftby1(opnd3);
2318 Sgl_normalize(opnd3,result_exponent);
2319 Sgl_set_sign(opnd3,/*using*/sign_save);
2320 Sgl_setwrapped_exponent(opnd3,result_exponent,
2321 unfl);
2322 Sgl_copytoptr(opnd3,dstptr);
2323 /* inexact = FALSE */
2324 return(OPC_2E_UNDERFLOWEXCEPTION);
2325 }
2326 Sgl_copytoptr(opnd3,dstptr);
2327 return(NOEXCEPTION);
2328 }
2329 /* is denormalized; want to normalize */
2330 Sgl_clear_signexponent(opnd2);
2331 Sgl_leftshiftby1(opnd2);
2332 Sgl_normalize(opnd2,mpy_exponent);
2333 }
2334
2335 /* Multiply the first two source mantissas together */
2336
2337 /*
2338 * The intermediate result will be kept in tmpres,
2339 * which needs enough room for 106 bits of mantissa,
2340 * so lets call it a Double extended.
2341 */
2342 Sglext_setzero(tmpresp1,tmpresp2);
2343
2344 /*
2345 * Four bits at a time are inspected in each loop, and a
2346 * simple shift and add multiply algorithm is used.
2347 */
2348 for (count = SGL_P-1; count >= 0; count -= 4) {
2349 Sglext_rightshiftby4(tmpresp1,tmpresp2);
2350 if (Sbit28(opnd1)) {
2351 /* Twoword_add should be an ADD followed by 2 ADDC's */
2352 Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
2353 }
2354 if (Sbit29(opnd1)) {
2355 Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
2356 }
2357 if (Sbit30(opnd1)) {
2358 Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
2359 }
2360 if (Sbit31(opnd1)) {
2361 Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
2362 }
2363 Sgl_rightshiftby4(opnd1);
2364 }
2365 if (Is_sexthiddenoverflow(tmpresp1)) {
2366 /* result mantissa >= 2 (mantissa overflow) */
2367 mpy_exponent++;
2368 Sglext_rightshiftby4(tmpresp1,tmpresp2);
2369 } else {
2370 Sglext_rightshiftby3(tmpresp1,tmpresp2);
2371 }
2372
2373 /*
2374 * Restore the sign of the mpy result which was saved in resultp1.
2375 * The exponent will continue to be kept in mpy_exponent.
2376 */
2377 Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
2378
2379 /*
2380 * No rounding is required, since the result of the multiply
2381 * is exact in the extended format.
2382 */
2383
2384 /*
2385 * Now we are ready to perform the add portion of the operation.
2386 *
2387 * The exponents need to be kept as integers for now, since the
2388 * multiply result might not fit into the exponent field. We
2389 * can't overflow or underflow because of this yet, since the
2390 * add could bring the final result back into range.
2391 */
2392 add_exponent = Sgl_exponent(opnd3);
2393
2394 /*
2395 * Check for denormalized or zero add operand.
2396 */
2397 if (add_exponent == 0) {
2398 /* check for zero */
2399 if (Sgl_iszero_mantissa(opnd3)) {
2400 /* right is zero */
2401 /* Left can't be zero and must be result.
2402 *
2403 * The final result is now in tmpres and mpy_exponent,
2404 * and needs to be rounded and squeezed back into
2405 * double precision format from double extended.
2406 */
2407 result_exponent = mpy_exponent;
2408 Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
2409 sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
2410 goto round;
2411 }
2412
2413 /*
2414 * Neither are zeroes.
2415 * Adjust exponent and normalize add operand.
2416 */
2417 sign_save = Sgl_signextendedsign(opnd3); /* save sign */
2418 Sgl_clear_signexponent(opnd3);
2419 Sgl_leftshiftby1(opnd3);
2420 Sgl_normalize(opnd3,add_exponent);
2421 Sgl_set_sign(opnd3,sign_save); /* restore sign */
2422 } else {
2423 Sgl_clear_exponent_set_hidden(opnd3);
2424 }
2425 /*
2426 * Copy opnd3 to the double extended variable called right.
2427 */
2428 Sgl_copyto_sglext(opnd3,rightp1,rightp2);
2429
2430 /*
2431 * A zero "save" helps discover equal operands (for later),
2432 * and is used in swapping operands (if needed).
2433 */
2434 Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
2435
2436 /*
2437 * Compare magnitude of operands.
2438 */
2439 Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
2440 Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
2441 if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
2442 Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
2443 /*
2444 * Set the left operand to the larger one by XOR swap.
2445 * First finish the first word "save".
2446 */
2447 Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
2448 Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
2449 Sglext_swap_lower(tmpresp2,rightp2);
2450 /* also setup exponents used in rest of routine */
2451 diff_exponent = add_exponent - mpy_exponent;
2452 result_exponent = add_exponent;
2453 } else {
2454 /* also setup exponents used in rest of routine */
2455 diff_exponent = mpy_exponent - add_exponent;
2456 result_exponent = mpy_exponent;
2457 }
2458 /* Invariant: left is not smaller than right. */
2459
2460 /*
2461 * Special case alignment of operands that would force alignment
2462 * beyond the extent of the extension. A further optimization
2463 * could special case this but only reduces the path length for
2464 * this infrequent case.
2465 */
2466 if (diff_exponent > SGLEXT_THRESHOLD) {
2467 diff_exponent = SGLEXT_THRESHOLD;
2468 }
2469
2470 /* Align right operand by shifting it to the right */
2471 Sglext_clear_sign(rightp1);
2472 Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
2473
2474 /* Treat sum and difference of the operands separately. */
2475 if ((int)save < 0) {
2476 /*
2477 * Difference of the two operands. Overflow can occur if the
2478 * multiply overflowed. A borrow can occur out of the hidden
2479 * bit and force a post normalization phase.
2480 */
2481 Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
2482 resultp1,resultp2);
2483 sign_save = Sgl_signextendedsign(resultp1);
2484 if (Sgl_iszero_hidden(resultp1)) {
2485 /* Handle normalization */
2486 /* A straight foward algorithm would now shift the
2487 * result and extension left until the hidden bit
2488 * becomes one. Not all of the extension bits need
2489 * participate in the shift. Only the two most
2490 * significant bits (round and guard) are needed.
2491 * If only a single shift is needed then the guard
2492 * bit becomes a significant low order bit and the
2493 * extension must participate in the rounding.
2494 * If more than a single shift is needed, then all
2495 * bits to the right of the guard bit are zeros,
2496 * and the guard bit may or may not be zero. */
2497 Sglext_leftshiftby1(resultp1,resultp2);
2498
2499 /* Need to check for a zero result. The sign and
2500 * exponent fields have already been zeroed. The more
2501 * efficient test of the full object can be used.
2502 */
2503 if (Sglext_iszero(resultp1,resultp2)) {
2504 /* Must have been "x-x" or "x+(-x)". */
2505 if (Is_rounding_mode(ROUNDMINUS))
2506 Sgl_setone_sign(resultp1);
2507 Sgl_copytoptr(resultp1,dstptr);
2508 return(NOEXCEPTION);
2509 }
2510 result_exponent--;
2511
2512 /* Look to see if normalization is finished. */
2513 if (Sgl_isone_hidden(resultp1)) {
2514 /* No further normalization is needed */
2515 goto round;
2516 }
2517
2518 /* Discover first one bit to determine shift amount.
2519 * Use a modified binary search. We have already
2520 * shifted the result one position right and still
2521 * not found a one so the remainder of the extension
2522 * must be zero and simplifies rounding. */
2523 /* Scan bytes */
2524 while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
2525 Sglext_leftshiftby8(resultp1,resultp2);
2526 result_exponent -= 8;
2527 }
2528 /* Now narrow it down to the nibble */
2529 if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
2530 /* The lower nibble contains the
2531 * normalizing one */
2532 Sglext_leftshiftby4(resultp1,resultp2);
2533 result_exponent -= 4;
2534 }
2535 /* Select case where first bit is set (already
2536 * normalized) otherwise select the proper shift. */
2537 jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
2538 if (jumpsize <= 7) switch(jumpsize) {
2539 case 1:
2540 Sglext_leftshiftby3(resultp1,resultp2);
2541 result_exponent -= 3;
2542 break;
2543 case 2:
2544 case 3:
2545 Sglext_leftshiftby2(resultp1,resultp2);
2546 result_exponent -= 2;
2547 break;
2548 case 4:
2549 case 5:
2550 case 6:
2551 case 7:
2552 Sglext_leftshiftby1(resultp1,resultp2);
2553 result_exponent -= 1;
2554 break;
2555 }
2556 } /* end if (hidden...)... */
2557 /* Fall through and round */
2558 } /* end if (save < 0)... */
2559 else {
2560 /* Add magnitudes */
2561 Sglext_addition(tmpresp1,tmpresp2,
2562 rightp1,rightp2, /*to*/resultp1,resultp2);
2563 sign_save = Sgl_signextendedsign(resultp1);
2564 if (Sgl_isone_hiddenoverflow(resultp1)) {
2565 /* Prenormalization required. */
2566 Sglext_arithrightshiftby1(resultp1,resultp2);
2567 result_exponent++;
2568 } /* end if hiddenoverflow... */
2569 } /* end else ...add magnitudes... */
2570
2571 /* Round the result. If the extension and lower two words are
2572 * all zeros, then the result is exact. Otherwise round in the
2573 * correct direction. Underflow is possible. If a postnormalization
2574 * is necessary, then the mantissa is all zeros so no shift is needed.
2575 */
2576 round:
2577 if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
2578 Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
2579 }
2580 Sgl_set_sign(resultp1,/*using*/sign_save);
2581 if (Sglext_isnotzero_mantissap2(resultp2)) {
2582 inexact = TRUE;
2583 switch(Rounding_mode()) {
2584 case ROUNDNEAREST: /* The default. */
2585 if (Sglext_isone_highp2(resultp2)) {
2586 /* at least 1/2 ulp */
2587 if (Sglext_isnotzero_low31p2(resultp2) ||
2588 Sglext_isone_lowp1(resultp1)) {
2589 /* either exactly half way and odd or
2590 * more than 1/2ulp */
2591 Sgl_increment(resultp1);
2592 }
2593 }
2594 break;
2595
2596 case ROUNDPLUS:
2597 if (Sgl_iszero_sign(resultp1)) {
2598 /* Round up positive results */
2599 Sgl_increment(resultp1);
2600 }
2601 break;
2602
2603 case ROUNDMINUS:
2604 if (Sgl_isone_sign(resultp1)) {
2605 /* Round down negative results */
2606 Sgl_increment(resultp1);
2607 }
2608
2609 case ROUNDZERO:;
2610 /* truncate is simple */
2611 } /* end switch... */
2612 if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
2613 }
2614 if (result_exponent >= SGL_INFINITY_EXPONENT) {
2615 /* Overflow */
2616 if (Is_overflowtrap_enabled()) {
2617 /*
2618 * Adjust bias of result
2619 */
2620 Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
2621 Sgl_copytoptr(resultp1,dstptr);
2622 if (inexact)
2623 if (Is_inexacttrap_enabled())
2624 return (OPC_2E_OVERFLOWEXCEPTION |
2625 OPC_2E_INEXACTEXCEPTION);
2626 else Set_inexactflag();
2627 return (OPC_2E_OVERFLOWEXCEPTION);
2628 }
2629 inexact = TRUE;
2630 Set_overflowflag();
2631 Sgl_setoverflow(resultp1);
2632 } else if (result_exponent <= 0) { /* underflow case */
2633 if (Is_underflowtrap_enabled()) {
2634 /*
2635 * Adjust bias of result
2636 */
2637 Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
2638 Sgl_copytoptr(resultp1,dstptr);
2639 if (inexact)
2640 if (Is_inexacttrap_enabled())
2641 return (OPC_2E_UNDERFLOWEXCEPTION |
2642 OPC_2E_INEXACTEXCEPTION);
2643 else Set_inexactflag();
2644 return(OPC_2E_UNDERFLOWEXCEPTION);
2645 }
2646 else if (inexact && is_tiny) Set_underflowflag();
2647 }
2648 else Sgl_set_exponent(resultp1,result_exponent);
2649 Sgl_copytoptr(resultp1,dstptr);
2650 if (inexact)
2651 if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
2652 else Set_inexactflag();
2653 return(NOEXCEPTION);
2654}
2655
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifdef __NO_PA_HDRS
23 PA header file -- do not include this header file for non-PA builds.
24#endif
25
26
27/*
28 * These macros are designed to be portable to all machines that have
29 * a wordsize greater than or equal to 32 bits that support the portable
30 * C compiler and the standard C preprocessor. Wordsize (default 32)
31 * and bitfield assignment (default left-to-right, unlike VAX, PDP-11)
32 * should be predefined using the constants HOSTWDSZ and BITFRL and
33 * the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20).
34 * Note that the macro arguments assume that the integer being referenced
35 * is a 32-bit integer (right-justified on the 20) and that bit 0 is the
36 * most significant bit.
37 */
38
39#ifndef HOSTWDSZ
40#define HOSTWDSZ 32
41#endif
42
43
44/*########################### Macros ######################################*/
45
46/*-------------------------------------------------------------------------
47 * NewDeclareBitField_Reference - Declare a structure similar to the simulator
48 * function "DeclBitfR" except its use is restricted to occur within a larger
49 * enclosing structure or union definition. This declaration is an unnamed
50 * structure with the argument, name, as the member name and the argument,
51 * uname, as the element name.
52 *----------------------------------------------------------------------- */
53#define Bitfield_extract(start, length, object) \
54 ((object) >> (HOSTWDSZ - (start) - (length)) & \
55 ((unsigned)-1 >> (HOSTWDSZ - (length))))
56
57#define Bitfield_signed_extract(start, length, object) \
58 ((int)((object) << start) >> (HOSTWDSZ - (length)))
59
60#define Bitfield_mask(start, len, object) \
61 ((object) & (((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len)))
62
63#define Bitfield_deposit(value,start,len,object) object = \
64 ((object) & ~(((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | \
65 (((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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/fp/fpu.h $Revision: 1.1 $
26 *
27 * Purpose:
28 * <<please update with a synopis of the functionality provided by this file>>
29 *
30 *
31 * END_DESC
32*/
33
34#ifdef __NO_PA_HDRS
35 PA header file -- do not include this header file for non-PA builds.
36#endif
37
38
39#ifndef _MACHINE_FPU_INCLUDED /* allows multiple inclusion */
40#define _MACHINE_FPU_INCLUDED
41
42#if 0
43#ifndef _SYS_STDSYMS_INCLUDED
44# include <sys/stdsyms.h>
45#endif /* _SYS_STDSYMS_INCLUDED */
46#include <machine/pdc/pdc_rqsts.h>
47#endif
48
49#define PA83_FPU_FLAG 0x00000001
50#define PA89_FPU_FLAG 0x00000002
51#define PA2_0_FPU_FLAG 0x00000010
52
53#define TIMEX_EXTEN_FLAG 0x00000004
54
55#define ROLEX_EXTEN_FLAG 0x00000008
56#define COPR_FP 0x00000080 /* Floating point -- Coprocessor 0 */
57#define SFU_MPY_DIVIDE 0x00008000 /* Multiply/Divide __ SFU 0 */
58
59
60#define EM_FPU_TYPE_OFFSET 272
61
62/* version of EMULATION software for COPR,0,0 instruction */
63#define EMULATION_VERSION 4
64
65/*
66 * The only was to differeniate between TIMEX and ROLEX (or PCX-S and PCX-T)
67 * is thorough the potential type field from the PDC_MODEL call. The
68 * following flags are used at assist this differeniation.
69 */
70
71#define ROLEX_POTENTIAL_KEY_FLAGS PDC_MODEL_CPU_KEY_WORD_TO_IO
72#define TIMEX_POTENTIAL_KEY_FLAGS (PDC_MODEL_CPU_KEY_QUAD_STORE | \
73 PDC_MODEL_CPU_KEY_RECIP_SQRT)
74
75
76#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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * <<please update with a synopsis of the functionality provided by this file>>
29 *
30 * External Interfaces:
31 * <<the following list was autogenerated, please review>>
32 * emfpudispatch(ir, dummy1, dummy2, fpregs)
33 * fpudispatch(ir, excp_code, holder, fpregs)
34 *
35 * Internal Interfaces:
36 * <<the following list was autogenerated, please review>>
37 * static u_int decode_06(u_int, u_int *)
38 * static u_int decode_0c(u_int, u_int, u_int, u_int *)
39 * static u_int decode_0e(u_int, u_int, u_int, u_int *)
40 * static u_int decode_26(u_int, u_int *)
41 * static u_int decode_2e(u_int, u_int *)
42 * static void update_status_cbit(u_int *, u_int, u_int, u_int)
43 *
44 * Theory:
45 * <<please update with a overview of the operation of this file>>
46 *
47 * END_DESC
48*/
49
50#define FPUDEBUG 0
51
52#include "float.h"
53#include <linux/kernel.h>
54#include <asm/processor.h>
55/* #include <sys/debug.h> */
56/* #include <machine/sys/mdep_private.h> */
57
58#define COPR_INST 0x30000000
59
60/*
61 * definition of extru macro. If pos and len are constants, the compiler
62 * will generate an extru instruction when optimized
63 */
64#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
65/* definitions of bit field locations in the instruction */
66#define fpmajorpos 5
67#define fpr1pos 10
68#define fpr2pos 15
69#define fptpos 31
70#define fpsubpos 18
71#define fpclass1subpos 16
72#define fpclasspos 22
73#define fpfmtpos 20
74#define fpdfpos 18
75#define fpnulpos 26
76/*
77 * the following are the extra bits for the 0E major op
78 */
79#define fpxr1pos 24
80#define fpxr2pos 19
81#define fpxtpos 25
82#define fpxpos 23
83#define fp0efmtpos 20
84/*
85 * the following are for the multi-ops
86 */
87#define fprm1pos 10
88#define fprm2pos 15
89#define fptmpos 31
90#define fprapos 25
91#define fptapos 20
92#define fpmultifmt 26
93/*
94 * the following are for the fused FP instructions
95 */
96 /* fprm1pos 10 */
97 /* fprm2pos 15 */
98#define fpraupos 18
99#define fpxrm2pos 19
100 /* fpfmtpos 20 */
101#define fpralpos 23
102#define fpxrm1pos 24
103 /* fpxtpos 25 */
104#define fpfusedsubop 26
105 /* fptpos 31 */
106
107/*
108 * offset to constant zero in the FP emulation registers
109 */
110#define fpzeroreg (32*sizeof(double)/sizeof(u_int))
111
112/*
113 * extract the major opcode from the instruction
114 */
115#define get_major(op) extru(op,fpmajorpos,6)
116/*
117 * extract the two bit class field from the FP instruction. The class is at bit
118 * positions 21-22
119 */
120#define get_class(op) extru(op,fpclasspos,2)
121/*
122 * extract the 3 bit subop field. For all but class 1 instructions, it is
123 * located at bit positions 16-18
124 */
125#define get_subop(op) extru(op,fpsubpos,3)
126/*
127 * extract the 2 or 3 bit subop field from class 1 instructions. It is located
128 * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
129 */
130#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */
131#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */
132
133/* definitions of unimplemented exceptions */
134#define MAJOR_0C_EXCP 0x09
135#define MAJOR_0E_EXCP 0x0b
136#define MAJOR_06_EXCP 0x03
137#define MAJOR_26_EXCP 0x23
138#define MAJOR_2E_EXCP 0x2b
139#define PA83_UNIMP_EXCP 0x01
140
141/*
142 * Special Defines for TIMEX specific code
143 */
144
145#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
146#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
147
148/*
149 * Static function definitions
150 */
151#define _PROTOTYPES
152#if defined(_PROTOTYPES) || defined(_lint)
153static u_int decode_0c(u_int, u_int, u_int, u_int *);
154static u_int decode_0e(u_int, u_int, u_int, u_int *);
155static u_int decode_06(u_int, u_int *);
156static u_int decode_26(u_int, u_int *);
157static u_int decode_2e(u_int, u_int *);
158static void update_status_cbit(u_int *, u_int, u_int, u_int);
159#else /* !_PROTOTYPES&&!_lint */
160static u_int decode_0c();
161static u_int decode_0e();
162static u_int decode_06();
163static u_int decode_26();
164static u_int decode_2e();
165static void update_status_cbit();
166#endif /* _PROTOTYPES&&!_lint */
167
168#define VASSERT(x)
169
170static void parisc_linux_get_fpu_type(u_int fpregs[])
171{
172 /* on pa-linux the fpu type is not filled in by the
173 * caller; it is constructed here
174 */
175 if (boot_cpu_data.cpu_type == pcxs)
176 fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
177 else if (boot_cpu_data.cpu_type == pcxt ||
178 boot_cpu_data.cpu_type == pcxt_)
179 fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
180 else if (boot_cpu_data.cpu_type >= pcxu)
181 fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
182}
183
184/*
185 * this routine will decode the excepting floating point instruction and
186 * call the approiate emulation routine.
187 * It is called by decode_fpu with the following parameters:
188 * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
189 * where current_ir is the instruction to be emulated,
190 * unimplemented_code is the exception_code that the hardware generated
191 * and &Fpu_register is the address of emulated FP reg 0.
192 */
193u_int
194fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
195{
196 u_int class, subop;
197 u_int fpu_type_flags;
198
199 /* All FP emulation code assumes that ints are 4-bytes in length */
200 VASSERT(sizeof(int) == 4);
201
202 parisc_linux_get_fpu_type(fpregs);
203
204 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
205
206 class = get_class(ir);
207 if (class == 1) {
208 if (fpu_type_flags & PA2_0_FPU_FLAG)
209 subop = get_subop1_PA2_0(ir);
210 else
211 subop = get_subop1_PA1_1(ir);
212 }
213 else
214 subop = get_subop(ir);
215
216 if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
217
218 switch (excp_code) {
219 case MAJOR_0C_EXCP:
220 case PA83_UNIMP_EXCP:
221 return(decode_0c(ir,class,subop,fpregs));
222 case MAJOR_0E_EXCP:
223 return(decode_0e(ir,class,subop,fpregs));
224 case MAJOR_06_EXCP:
225 return(decode_06(ir,fpregs));
226 case MAJOR_26_EXCP:
227 return(decode_26(ir,fpregs));
228 case MAJOR_2E_EXCP:
229 return(decode_2e(ir,fpregs));
230 default:
231 /* "crashme Night Gallery painting nr 2. (asm_crash.s).
232 * This was fixed for multi-user kernels, but
233 * workstation kernels had a panic here. This allowed
234 * any arbitrary user to panic the kernel by executing
235 * setting the FP exception registers to strange values
236 * and generating an emulation trap. The emulation and
237 * exception code must never be able to panic the
238 * kernel.
239 */
240 return(UNIMPLEMENTEDEXCEPTION);
241 }
242}
243
244/*
245 * this routine is called by $emulation_trap to emulate a coprocessor
246 * instruction if one doesn't exist
247 */
248u_int
249emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
250{
251 u_int class, subop, major;
252 u_int fpu_type_flags;
253
254 /* All FP emulation code assumes that ints are 4-bytes in length */
255 VASSERT(sizeof(int) == 4);
256
257 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
258
259 major = get_major(ir);
260 class = get_class(ir);
261 if (class == 1) {
262 if (fpu_type_flags & PA2_0_FPU_FLAG)
263 subop = get_subop1_PA2_0(ir);
264 else
265 subop = get_subop1_PA1_1(ir);
266 }
267 else
268 subop = get_subop(ir);
269 switch (major) {
270 case 0x0C:
271 return(decode_0c(ir,class,subop,fpregs));
272 case 0x0E:
273 return(decode_0e(ir,class,subop,fpregs));
274 case 0x06:
275 return(decode_06(ir,fpregs));
276 case 0x26:
277 return(decode_26(ir,fpregs));
278 case 0x2E:
279 return(decode_2e(ir,fpregs));
280 default:
281 return(PA83_UNIMP_EXCP);
282 }
283}
284
285
286static u_int
287decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
288{
289 u_int r1,r2,t; /* operand register offsets */
290 u_int fmt; /* also sf for class 1 conversions */
291 u_int df; /* for class 1 conversions */
292 u_int *status;
293 u_int retval, local_status;
294 u_int fpu_type_flags;
295
296 if (ir == COPR_INST) {
297 fpregs[0] = EMULATION_VERSION << 11;
298 return(NOEXCEPTION);
299 }
300 status = &fpregs[0]; /* fp status register */
301 local_status = fpregs[0]; /* and local copy */
302 r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
303 if (r1 == 0) /* map fr0 source to constant zero */
304 r1 = fpzeroreg;
305 t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
306 if (t == 0 && class != 2) /* don't allow fr0 as a dest */
307 return(MAJOR_0C_EXCP);
308 fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
309
310 switch (class) {
311 case 0:
312 switch (subop) {
313 case 0: /* COPR 0,0 emulated above*/
314 case 1:
315 return(MAJOR_0C_EXCP);
316 case 2: /* FCPY */
317 switch (fmt) {
318 case 2: /* illegal */
319 return(MAJOR_0C_EXCP);
320 case 3: /* quad */
321 t &= ~3; /* force to even reg #s */
322 r1 &= ~3;
323 fpregs[t+3] = fpregs[r1+3];
324 fpregs[t+2] = fpregs[r1+2];
325 case 1: /* double */
326 fpregs[t+1] = fpregs[r1+1];
327 case 0: /* single */
328 fpregs[t] = fpregs[r1];
329 return(NOEXCEPTION);
330 }
331 case 3: /* FABS */
332 switch (fmt) {
333 case 2: /* illegal */
334 return(MAJOR_0C_EXCP);
335 case 3: /* quad */
336 t &= ~3; /* force to even reg #s */
337 r1 &= ~3;
338 fpregs[t+3] = fpregs[r1+3];
339 fpregs[t+2] = fpregs[r1+2];
340 case 1: /* double */
341 fpregs[t+1] = fpregs[r1+1];
342 case 0: /* single */
343 /* copy and clear sign bit */
344 fpregs[t] = fpregs[r1] & 0x7fffffff;
345 return(NOEXCEPTION);
346 }
347 case 6: /* FNEG */
348 switch (fmt) {
349 case 2: /* illegal */
350 return(MAJOR_0C_EXCP);
351 case 3: /* quad */
352 t &= ~3; /* force to even reg #s */
353 r1 &= ~3;
354 fpregs[t+3] = fpregs[r1+3];
355 fpregs[t+2] = fpregs[r1+2];
356 case 1: /* double */
357 fpregs[t+1] = fpregs[r1+1];
358 case 0: /* single */
359 /* copy and invert sign bit */
360 fpregs[t] = fpregs[r1] ^ 0x80000000;
361 return(NOEXCEPTION);
362 }
363 case 7: /* FNEGABS */
364 switch (fmt) {
365 case 2: /* illegal */
366 return(MAJOR_0C_EXCP);
367 case 3: /* quad */
368 t &= ~3; /* force to even reg #s */
369 r1 &= ~3;
370 fpregs[t+3] = fpregs[r1+3];
371 fpregs[t+2] = fpregs[r1+2];
372 case 1: /* double */
373 fpregs[t+1] = fpregs[r1+1];
374 case 0: /* single */
375 /* copy and set sign bit */
376 fpregs[t] = fpregs[r1] | 0x80000000;
377 return(NOEXCEPTION);
378 }
379 case 4: /* FSQRT */
380 switch (fmt) {
381 case 0:
382 return(sgl_fsqrt(&fpregs[r1],0,
383 &fpregs[t],status));
384 case 1:
385 return(dbl_fsqrt(&fpregs[r1],0,
386 &fpregs[t],status));
387 case 2:
388 case 3: /* quad not implemented */
389 return(MAJOR_0C_EXCP);
390 }
391 case 5: /* FRND */
392 switch (fmt) {
393 case 0:
394 return(sgl_frnd(&fpregs[r1],0,
395 &fpregs[t],status));
396 case 1:
397 return(dbl_frnd(&fpregs[r1],0,
398 &fpregs[t],status));
399 case 2:
400 case 3: /* quad not implemented */
401 return(MAJOR_0C_EXCP);
402 }
403 } /* end of switch (subop) */
404
405 case 1: /* class 1 */
406 df = extru(ir,fpdfpos,2); /* get dest format */
407 if ((df & 2) || (fmt & 2)) {
408 /*
409 * fmt's 2 and 3 are illegal of not implemented
410 * quad conversions
411 */
412 return(MAJOR_0C_EXCP);
413 }
414 /*
415 * encode source and dest formats into 2 bits.
416 * high bit is source, low bit is dest.
417 * bit = 1 --> double precision
418 */
419 fmt = (fmt << 1) | df;
420 switch (subop) {
421 case 0: /* FCNVFF */
422 switch(fmt) {
423 case 0: /* sgl/sgl */
424 return(MAJOR_0C_EXCP);
425 case 1: /* sgl/dbl */
426 return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
427 &fpregs[t],status));
428 case 2: /* dbl/sgl */
429 return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
430 &fpregs[t],status));
431 case 3: /* dbl/dbl */
432 return(MAJOR_0C_EXCP);
433 }
434 case 1: /* FCNVXF */
435 switch(fmt) {
436 case 0: /* sgl/sgl */
437 return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
438 &fpregs[t],status));
439 case 1: /* sgl/dbl */
440 return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
441 &fpregs[t],status));
442 case 2: /* dbl/sgl */
443 return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
444 &fpregs[t],status));
445 case 3: /* dbl/dbl */
446 return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
447 &fpregs[t],status));
448 }
449 case 2: /* FCNVFX */
450 switch(fmt) {
451 case 0: /* sgl/sgl */
452 return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
453 &fpregs[t],status));
454 case 1: /* sgl/dbl */
455 return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
456 &fpregs[t],status));
457 case 2: /* dbl/sgl */
458 return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
459 &fpregs[t],status));
460 case 3: /* dbl/dbl */
461 return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
462 &fpregs[t],status));
463 }
464 case 3: /* FCNVFXT */
465 switch(fmt) {
466 case 0: /* sgl/sgl */
467 return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
468 &fpregs[t],status));
469 case 1: /* sgl/dbl */
470 return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
471 &fpregs[t],status));
472 case 2: /* dbl/sgl */
473 return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
474 &fpregs[t],status));
475 case 3: /* dbl/dbl */
476 return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
477 &fpregs[t],status));
478 }
479 case 5: /* FCNVUF (PA2.0 only) */
480 switch(fmt) {
481 case 0: /* sgl/sgl */
482 return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
483 &fpregs[t],status));
484 case 1: /* sgl/dbl */
485 return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
486 &fpregs[t],status));
487 case 2: /* dbl/sgl */
488 return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
489 &fpregs[t],status));
490 case 3: /* dbl/dbl */
491 return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
492 &fpregs[t],status));
493 }
494 case 6: /* FCNVFU (PA2.0 only) */
495 switch(fmt) {
496 case 0: /* sgl/sgl */
497 return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
498 &fpregs[t],status));
499 case 1: /* sgl/dbl */
500 return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
501 &fpregs[t],status));
502 case 2: /* dbl/sgl */
503 return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
504 &fpregs[t],status));
505 case 3: /* dbl/dbl */
506 return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
507 &fpregs[t],status));
508 }
509 case 7: /* FCNVFUT (PA2.0 only) */
510 switch(fmt) {
511 case 0: /* sgl/sgl */
512 return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
513 &fpregs[t],status));
514 case 1: /* sgl/dbl */
515 return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
516 &fpregs[t],status));
517 case 2: /* dbl/sgl */
518 return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
519 &fpregs[t],status));
520 case 3: /* dbl/dbl */
521 return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
522 &fpregs[t],status));
523 }
524 case 4: /* undefined */
525 return(MAJOR_0C_EXCP);
526 } /* end of switch subop */
527
528 case 2: /* class 2 */
529 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
530 r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
531 if (r2 == 0)
532 r2 = fpzeroreg;
533 if (fpu_type_flags & PA2_0_FPU_FLAG) {
534 /* FTEST if nullify bit set, otherwise FCMP */
535 if (extru(ir, fpnulpos, 1)) { /* FTEST */
536 switch (fmt) {
537 case 0:
538 /*
539 * arg0 is not used
540 * second param is the t field used for
541 * ftest,acc and ftest,rej
542 * third param is the subop (y-field)
543 */
544 BUG();
545 /* Unsupported
546 * return(ftest(0L,extru(ir,fptpos,5),
547 * &fpregs[0],subop));
548 */
549 case 1:
550 case 2:
551 case 3:
552 return(MAJOR_0C_EXCP);
553 }
554 } else { /* FCMP */
555 switch (fmt) {
556 case 0:
557 retval = sgl_fcmp(&fpregs[r1],
558 &fpregs[r2],extru(ir,fptpos,5),
559 &local_status);
560 update_status_cbit(status,local_status,
561 fpu_type_flags, subop);
562 return(retval);
563 case 1:
564 retval = dbl_fcmp(&fpregs[r1],
565 &fpregs[r2],extru(ir,fptpos,5),
566 &local_status);
567 update_status_cbit(status,local_status,
568 fpu_type_flags, subop);
569 return(retval);
570 case 2: /* illegal */
571 case 3: /* quad not implemented */
572 return(MAJOR_0C_EXCP);
573 }
574 }
575 } /* end of if for PA2.0 */
576 else { /* PA1.0 & PA1.1 */
577 switch (subop) {
578 case 2:
579 case 3:
580 case 4:
581 case 5:
582 case 6:
583 case 7:
584 return(MAJOR_0C_EXCP);
585 case 0: /* FCMP */
586 switch (fmt) {
587 case 0:
588 retval = sgl_fcmp(&fpregs[r1],
589 &fpregs[r2],extru(ir,fptpos,5),
590 &local_status);
591 update_status_cbit(status,local_status,
592 fpu_type_flags, subop);
593 return(retval);
594 case 1:
595 retval = dbl_fcmp(&fpregs[r1],
596 &fpregs[r2],extru(ir,fptpos,5),
597 &local_status);
598 update_status_cbit(status,local_status,
599 fpu_type_flags, subop);
600 return(retval);
601 case 2: /* illegal */
602 case 3: /* quad not implemented */
603 return(MAJOR_0C_EXCP);
604 }
605 case 1: /* FTEST */
606 switch (fmt) {
607 case 0:
608 /*
609 * arg0 is not used
610 * second param is the t field used for
611 * ftest,acc and ftest,rej
612 * third param is the subop (y-field)
613 */
614 BUG();
615 /* unsupported
616 * return(ftest(0L,extru(ir,fptpos,5),
617 * &fpregs[0],subop));
618 */
619 case 1:
620 case 2:
621 case 3:
622 return(MAJOR_0C_EXCP);
623 }
624 } /* end of switch subop */
625 } /* end of else for PA1.0 & PA1.1 */
626 case 3: /* class 3 */
627 r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
628 if (r2 == 0)
629 r2 = fpzeroreg;
630 switch (subop) {
631 case 5:
632 case 6:
633 case 7:
634 return(MAJOR_0C_EXCP);
635
636 case 0: /* FADD */
637 switch (fmt) {
638 case 0:
639 return(sgl_fadd(&fpregs[r1],&fpregs[r2],
640 &fpregs[t],status));
641 case 1:
642 return(dbl_fadd(&fpregs[r1],&fpregs[r2],
643 &fpregs[t],status));
644 case 2: /* illegal */
645 case 3: /* quad not implemented */
646 return(MAJOR_0C_EXCP);
647 }
648 case 1: /* FSUB */
649 switch (fmt) {
650 case 0:
651 return(sgl_fsub(&fpregs[r1],&fpregs[r2],
652 &fpregs[t],status));
653 case 1:
654 return(dbl_fsub(&fpregs[r1],&fpregs[r2],
655 &fpregs[t],status));
656 case 2: /* illegal */
657 case 3: /* quad not implemented */
658 return(MAJOR_0C_EXCP);
659 }
660 case 2: /* FMPY */
661 switch (fmt) {
662 case 0:
663 return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
664 &fpregs[t],status));
665 case 1:
666 return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
667 &fpregs[t],status));
668 case 2: /* illegal */
669 case 3: /* quad not implemented */
670 return(MAJOR_0C_EXCP);
671 }
672 case 3: /* FDIV */
673 switch (fmt) {
674 case 0:
675 return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
676 &fpregs[t],status));
677 case 1:
678 return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
679 &fpregs[t],status));
680 case 2: /* illegal */
681 case 3: /* quad not implemented */
682 return(MAJOR_0C_EXCP);
683 }
684 case 4: /* FREM */
685 switch (fmt) {
686 case 0:
687 return(sgl_frem(&fpregs[r1],&fpregs[r2],
688 &fpregs[t],status));
689 case 1:
690 return(dbl_frem(&fpregs[r1],&fpregs[r2],
691 &fpregs[t],status));
692 case 2: /* illegal */
693 case 3: /* quad not implemented */
694 return(MAJOR_0C_EXCP);
695 }
696 } /* end of class 3 switch */
697 } /* end of switch(class) */
698
699 /* If we get here, something is really wrong! */
700 return(MAJOR_0C_EXCP);
701}
702
703static u_int
704decode_0e(ir,class,subop,fpregs)
705u_int ir,class,subop;
706u_int fpregs[];
707{
708 u_int r1,r2,t; /* operand register offsets */
709 u_int fmt; /* also sf for class 1 conversions */
710 u_int df; /* dest format for class 1 conversions */
711 u_int *status;
712 u_int retval, local_status;
713 u_int fpu_type_flags;
714
715 status = &fpregs[0];
716 local_status = fpregs[0];
717 r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
718 if (r1 == 0)
719 r1 = fpzeroreg;
720 t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
721 if (t == 0 && class != 2)
722 return(MAJOR_0E_EXCP);
723 if (class < 2) /* class 0 or 1 has 2 bit fmt */
724 fmt = extru(ir,fpfmtpos,2);
725 else /* class 2 and 3 have 1 bit fmt */
726 fmt = extru(ir,fp0efmtpos,1);
727 /*
728 * An undefined combination, double precision accessing the
729 * right half of a FPR, can get us into trouble.
730 * Let's just force proper alignment on it.
731 */
732 if (fmt == DBL) {
733 r1 &= ~1;
734 if (class != 1)
735 t &= ~1;
736 }
737
738 switch (class) {
739 case 0:
740 switch (subop) {
741 case 0: /* unimplemented */
742 case 1:
743 return(MAJOR_0E_EXCP);
744 case 2: /* FCPY */
745 switch (fmt) {
746 case 2:
747 case 3:
748 return(MAJOR_0E_EXCP);
749 case 1: /* double */
750 fpregs[t+1] = fpregs[r1+1];
751 case 0: /* single */
752 fpregs[t] = fpregs[r1];
753 return(NOEXCEPTION);
754 }
755 case 3: /* FABS */
756 switch (fmt) {
757 case 2:
758 case 3:
759 return(MAJOR_0E_EXCP);
760 case 1: /* double */
761 fpregs[t+1] = fpregs[r1+1];
762 case 0: /* single */
763 fpregs[t] = fpregs[r1] & 0x7fffffff;
764 return(NOEXCEPTION);
765 }
766 case 6: /* FNEG */
767 switch (fmt) {
768 case 2:
769 case 3:
770 return(MAJOR_0E_EXCP);
771 case 1: /* double */
772 fpregs[t+1] = fpregs[r1+1];
773 case 0: /* single */
774 fpregs[t] = fpregs[r1] ^ 0x80000000;
775 return(NOEXCEPTION);
776 }
777 case 7: /* FNEGABS */
778 switch (fmt) {
779 case 2:
780 case 3:
781 return(MAJOR_0E_EXCP);
782 case 1: /* double */
783 fpregs[t+1] = fpregs[r1+1];
784 case 0: /* single */
785 fpregs[t] = fpregs[r1] | 0x80000000;
786 return(NOEXCEPTION);
787 }
788 case 4: /* FSQRT */
789 switch (fmt) {
790 case 0:
791 return(sgl_fsqrt(&fpregs[r1],0,
792 &fpregs[t], status));
793 case 1:
794 return(dbl_fsqrt(&fpregs[r1],0,
795 &fpregs[t], status));
796 case 2:
797 case 3:
798 return(MAJOR_0E_EXCP);
799 }
800 case 5: /* FRMD */
801 switch (fmt) {
802 case 0:
803 return(sgl_frnd(&fpregs[r1],0,
804 &fpregs[t], status));
805 case 1:
806 return(dbl_frnd(&fpregs[r1],0,
807 &fpregs[t], status));
808 case 2:
809 case 3:
810 return(MAJOR_0E_EXCP);
811 }
812 } /* end of switch (subop */
813
814 case 1: /* class 1 */
815 df = extru(ir,fpdfpos,2); /* get dest format */
816 /*
817 * Fix Crashme problem (writing to 31R in double precision)
818 * here too.
819 */
820 if (df == DBL) {
821 t &= ~1;
822 }
823 if ((df & 2) || (fmt & 2))
824 return(MAJOR_0E_EXCP);
825
826 fmt = (fmt << 1) | df;
827 switch (subop) {
828 case 0: /* FCNVFF */
829 switch(fmt) {
830 case 0: /* sgl/sgl */
831 return(MAJOR_0E_EXCP);
832 case 1: /* sgl/dbl */
833 return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
834 &fpregs[t],status));
835 case 2: /* dbl/sgl */
836 return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
837 &fpregs[t],status));
838 case 3: /* dbl/dbl */
839 return(MAJOR_0E_EXCP);
840 }
841 case 1: /* FCNVXF */
842 switch(fmt) {
843 case 0: /* sgl/sgl */
844 return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
845 &fpregs[t],status));
846 case 1: /* sgl/dbl */
847 return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
848 &fpregs[t],status));
849 case 2: /* dbl/sgl */
850 return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
851 &fpregs[t],status));
852 case 3: /* dbl/dbl */
853 return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
854 &fpregs[t],status));
855 }
856 case 2: /* FCNVFX */
857 switch(fmt) {
858 case 0: /* sgl/sgl */
859 return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
860 &fpregs[t],status));
861 case 1: /* sgl/dbl */
862 return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
863 &fpregs[t],status));
864 case 2: /* dbl/sgl */
865 return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
866 &fpregs[t],status));
867 case 3: /* dbl/dbl */
868 return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
869 &fpregs[t],status));
870 }
871 case 3: /* FCNVFXT */
872 switch(fmt) {
873 case 0: /* sgl/sgl */
874 return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
875 &fpregs[t],status));
876 case 1: /* sgl/dbl */
877 return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
878 &fpregs[t],status));
879 case 2: /* dbl/sgl */
880 return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
881 &fpregs[t],status));
882 case 3: /* dbl/dbl */
883 return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
884 &fpregs[t],status));
885 }
886 case 5: /* FCNVUF (PA2.0 only) */
887 switch(fmt) {
888 case 0: /* sgl/sgl */
889 return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
890 &fpregs[t],status));
891 case 1: /* sgl/dbl */
892 return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
893 &fpregs[t],status));
894 case 2: /* dbl/sgl */
895 return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
896 &fpregs[t],status));
897 case 3: /* dbl/dbl */
898 return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
899 &fpregs[t],status));
900 }
901 case 6: /* FCNVFU (PA2.0 only) */
902 switch(fmt) {
903 case 0: /* sgl/sgl */
904 return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
905 &fpregs[t],status));
906 case 1: /* sgl/dbl */
907 return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
908 &fpregs[t],status));
909 case 2: /* dbl/sgl */
910 return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
911 &fpregs[t],status));
912 case 3: /* dbl/dbl */
913 return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
914 &fpregs[t],status));
915 }
916 case 7: /* FCNVFUT (PA2.0 only) */
917 switch(fmt) {
918 case 0: /* sgl/sgl */
919 return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
920 &fpregs[t],status));
921 case 1: /* sgl/dbl */
922 return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
923 &fpregs[t],status));
924 case 2: /* dbl/sgl */
925 return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
926 &fpregs[t],status));
927 case 3: /* dbl/dbl */
928 return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
929 &fpregs[t],status));
930 }
931 case 4: /* undefined */
932 return(MAJOR_0C_EXCP);
933 } /* end of switch subop */
934 case 2: /* class 2 */
935 /*
936 * Be careful out there.
937 * Crashme can generate cases where FR31R is specified
938 * as the source or target of a double precision operation.
939 * Since we just pass the address of the floating-point
940 * register to the emulation routines, this can cause
941 * corruption of fpzeroreg.
942 */
943 if (fmt == DBL)
944 r2 = (extru(ir,fpr2pos,5)<<1);
945 else
946 r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
947 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
948 if (r2 == 0)
949 r2 = fpzeroreg;
950 if (fpu_type_flags & PA2_0_FPU_FLAG) {
951 /* FTEST if nullify bit set, otherwise FCMP */
952 if (extru(ir, fpnulpos, 1)) { /* FTEST */
953 /* not legal */
954 return(MAJOR_0E_EXCP);
955 } else { /* FCMP */
956 switch (fmt) {
957 /*
958 * fmt is only 1 bit long
959 */
960 case 0:
961 retval = sgl_fcmp(&fpregs[r1],
962 &fpregs[r2],extru(ir,fptpos,5),
963 &local_status);
964 update_status_cbit(status,local_status,
965 fpu_type_flags, subop);
966 return(retval);
967 case 1:
968 retval = dbl_fcmp(&fpregs[r1],
969 &fpregs[r2],extru(ir,fptpos,5),
970 &local_status);
971 update_status_cbit(status,local_status,
972 fpu_type_flags, subop);
973 return(retval);
974 }
975 }
976 } /* end of if for PA2.0 */
977 else { /* PA1.0 & PA1.1 */
978 switch (subop) {
979 case 1:
980 case 2:
981 case 3:
982 case 4:
983 case 5:
984 case 6:
985 case 7:
986 return(MAJOR_0E_EXCP);
987 case 0: /* FCMP */
988 switch (fmt) {
989 /*
990 * fmt is only 1 bit long
991 */
992 case 0:
993 retval = sgl_fcmp(&fpregs[r1],
994 &fpregs[r2],extru(ir,fptpos,5),
995 &local_status);
996 update_status_cbit(status,local_status,
997 fpu_type_flags, subop);
998 return(retval);
999 case 1:
1000 retval = dbl_fcmp(&fpregs[r1],
1001 &fpregs[r2],extru(ir,fptpos,5),
1002 &local_status);
1003 update_status_cbit(status,local_status,
1004 fpu_type_flags, subop);
1005 return(retval);
1006 }
1007 } /* end of switch subop */
1008 } /* end of else for PA1.0 & PA1.1 */
1009 case 3: /* class 3 */
1010 /*
1011 * Be careful out there.
1012 * Crashme can generate cases where FR31R is specified
1013 * as the source or target of a double precision operation.
1014 * Since we just pass the address of the floating-point
1015 * register to the emulation routines, this can cause
1016 * corruption of fpzeroreg.
1017 */
1018 if (fmt == DBL)
1019 r2 = (extru(ir,fpr2pos,5)<<1);
1020 else
1021 r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
1022 if (r2 == 0)
1023 r2 = fpzeroreg;
1024 switch (subop) {
1025 case 5:
1026 case 6:
1027 case 7:
1028 return(MAJOR_0E_EXCP);
1029
1030 /*
1031 * Note that fmt is only 1 bit for class 3 */
1032 case 0: /* FADD */
1033 switch (fmt) {
1034 case 0:
1035 return(sgl_fadd(&fpregs[r1],&fpregs[r2],
1036 &fpregs[t],status));
1037 case 1:
1038 return(dbl_fadd(&fpregs[r1],&fpregs[r2],
1039 &fpregs[t],status));
1040 }
1041 case 1: /* FSUB */
1042 switch (fmt) {
1043 case 0:
1044 return(sgl_fsub(&fpregs[r1],&fpregs[r2],
1045 &fpregs[t],status));
1046 case 1:
1047 return(dbl_fsub(&fpregs[r1],&fpregs[r2],
1048 &fpregs[t],status));
1049 }
1050 case 2: /* FMPY or XMPYU */
1051 /*
1052 * check for integer multiply (x bit set)
1053 */
1054 if (extru(ir,fpxpos,1)) {
1055 /*
1056 * emulate XMPYU
1057 */
1058 switch (fmt) {
1059 case 0:
1060 /*
1061 * bad instruction if t specifies
1062 * the right half of a register
1063 */
1064 if (t & 1)
1065 return(MAJOR_0E_EXCP);
1066 BUG();
1067 /* unsupported
1068 * impyu(&fpregs[r1],&fpregs[r2],
1069 * &fpregs[t]);
1070 */
1071 return(NOEXCEPTION);
1072 case 1:
1073 return(MAJOR_0E_EXCP);
1074 }
1075 }
1076 else { /* FMPY */
1077 switch (fmt) {
1078 case 0:
1079 return(sgl_fmpy(&fpregs[r1],
1080 &fpregs[r2],&fpregs[t],status));
1081 case 1:
1082 return(dbl_fmpy(&fpregs[r1],
1083 &fpregs[r2],&fpregs[t],status));
1084 }
1085 }
1086 case 3: /* FDIV */
1087 switch (fmt) {
1088 case 0:
1089 return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
1090 &fpregs[t],status));
1091 case 1:
1092 return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
1093 &fpregs[t],status));
1094 }
1095 case 4: /* FREM */
1096 switch (fmt) {
1097 case 0:
1098 return(sgl_frem(&fpregs[r1],&fpregs[r2],
1099 &fpregs[t],status));
1100 case 1:
1101 return(dbl_frem(&fpregs[r1],&fpregs[r2],
1102 &fpregs[t],status));
1103 }
1104 } /* end of class 3 switch */
1105 } /* end of switch(class) */
1106
1107 /* If we get here, something is really wrong! */
1108 return(MAJOR_0E_EXCP);
1109}
1110
1111
1112/*
1113 * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
1114 */
1115static u_int
1116decode_06(ir,fpregs)
1117u_int ir;
1118u_int fpregs[];
1119{
1120 u_int rm1, rm2, tm, ra, ta; /* operands */
1121 u_int fmt;
1122 u_int error = 0;
1123 u_int status;
1124 u_int fpu_type_flags;
1125 union {
1126 double dbl;
1127 float flt;
1128 struct { u_int i1; u_int i2; } ints;
1129 } mtmp, atmp;
1130
1131
1132 status = fpregs[0]; /* use a local copy of status reg */
1133 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
1134 fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
1135 if (fmt == 0) { /* DBL */
1136 rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
1137 if (rm1 == 0)
1138 rm1 = fpzeroreg;
1139 rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
1140 if (rm2 == 0)
1141 rm2 = fpzeroreg;
1142 tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
1143 if (tm == 0)
1144 return(MAJOR_06_EXCP);
1145 ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
1146 ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
1147 if (ta == 0)
1148 return(MAJOR_06_EXCP);
1149
1150 if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) {
1151
1152 if (ra == 0) {
1153 /* special case FMPYCFXT, see sgl case below */
1154 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
1155 &mtmp.ints.i1,&status))
1156 error = 1;
1157 if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
1158 &atmp.ints.i1,&atmp.ints.i1,&status))
1159 error = 1;
1160 }
1161 else {
1162
1163 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1164 &status))
1165 error = 1;
1166 if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1167 &status))
1168 error = 1;
1169 }
1170 }
1171
1172 else
1173
1174 {
1175 if (ra == 0)
1176 ra = fpzeroreg;
1177
1178 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1179 &status))
1180 error = 1;
1181 if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1182 &status))
1183 error = 1;
1184
1185 }
1186
1187 if (error)
1188 return(MAJOR_06_EXCP);
1189 else {
1190 /* copy results */
1191 fpregs[tm] = mtmp.ints.i1;
1192 fpregs[tm+1] = mtmp.ints.i2;
1193 fpregs[ta] = atmp.ints.i1;
1194 fpregs[ta+1] = atmp.ints.i2;
1195 fpregs[0] = status;
1196 return(NOEXCEPTION);
1197 }
1198 }
1199 else { /* SGL */
1200 /*
1201 * calculate offsets for single precision numbers
1202 * See table 6-14 in PA-89 architecture for mapping
1203 */
1204 rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
1205 rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
1206
1207 rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
1208 rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
1209
1210 tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
1211 tm |= extru(ir,fptmpos-4,1); /* add right word offset */
1212
1213 ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
1214 ra |= extru(ir,fprapos-4,1); /* add right word offset */
1215
1216 ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
1217 ta |= extru(ir,fptapos-4,1); /* add right word offset */
1218
1219 if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
1220 /* special case FMPYCFXT (really 0)
1221 * This instruction is only present on the Timex and
1222 * Rolex fpu's in so if it is the special case and
1223 * one of these fpu's we run the FMPYCFXT instruction
1224 */
1225 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1226 &status))
1227 error = 1;
1228 if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
1229 &atmp.ints.i1,&status))
1230 error = 1;
1231 }
1232 else {
1233 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1234 &status))
1235 error = 1;
1236 if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1237 &status))
1238 error = 1;
1239 }
1240 if (error)
1241 return(MAJOR_06_EXCP);
1242 else {
1243 /* copy results */
1244 fpregs[tm] = mtmp.ints.i1;
1245 fpregs[ta] = atmp.ints.i1;
1246 fpregs[0] = status;
1247 return(NOEXCEPTION);
1248 }
1249 }
1250}
1251
1252/*
1253 * routine to decode the 26 (FMPYSUB) instruction
1254 */
1255static u_int
1256decode_26(ir,fpregs)
1257u_int ir;
1258u_int fpregs[];
1259{
1260 u_int rm1, rm2, tm, ra, ta; /* operands */
1261 u_int fmt;
1262 u_int error = 0;
1263 u_int status;
1264 union {
1265 double dbl;
1266 float flt;
1267 struct { u_int i1; u_int i2; } ints;
1268 } mtmp, atmp;
1269
1270
1271 status = fpregs[0];
1272 fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
1273 if (fmt == 0) { /* DBL */
1274 rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
1275 if (rm1 == 0)
1276 rm1 = fpzeroreg;
1277 rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
1278 if (rm2 == 0)
1279 rm2 = fpzeroreg;
1280 tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
1281 if (tm == 0)
1282 return(MAJOR_26_EXCP);
1283 ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
1284 if (ra == 0)
1285 return(MAJOR_26_EXCP);
1286 ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
1287 if (ta == 0)
1288 return(MAJOR_26_EXCP);
1289
1290 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
1291 error = 1;
1292 if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
1293 error = 1;
1294 if (error)
1295 return(MAJOR_26_EXCP);
1296 else {
1297 /* copy results */
1298 fpregs[tm] = mtmp.ints.i1;
1299 fpregs[tm+1] = mtmp.ints.i2;
1300 fpregs[ta] = atmp.ints.i1;
1301 fpregs[ta+1] = atmp.ints.i2;
1302 fpregs[0] = status;
1303 return(NOEXCEPTION);
1304 }
1305 }
1306 else { /* SGL */
1307 /*
1308 * calculate offsets for single precision numbers
1309 * See table 6-14 in PA-89 architecture for mapping
1310 */
1311 rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
1312 rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
1313
1314 rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
1315 rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
1316
1317 tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
1318 tm |= extru(ir,fptmpos-4,1); /* add right word offset */
1319
1320 ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
1321 ra |= extru(ir,fprapos-4,1); /* add right word offset */
1322
1323 ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
1324 ta |= extru(ir,fptapos-4,1); /* add right word offset */
1325
1326 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
1327 error = 1;
1328 if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
1329 error = 1;
1330 if (error)
1331 return(MAJOR_26_EXCP);
1332 else {
1333 /* copy results */
1334 fpregs[tm] = mtmp.ints.i1;
1335 fpregs[ta] = atmp.ints.i1;
1336 fpregs[0] = status;
1337 return(NOEXCEPTION);
1338 }
1339 }
1340
1341}
1342
1343/*
1344 * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
1345 */
1346static u_int
1347decode_2e(ir,fpregs)
1348u_int ir;
1349u_int fpregs[];
1350{
1351 u_int rm1, rm2, ra, t; /* operands */
1352 u_int fmt;
1353
1354 fmt = extru(ir,fpfmtpos,1); /* get fmt completer */
1355 if (fmt == DBL) { /* DBL */
1356 rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
1357 if (rm1 == 0)
1358 rm1 = fpzeroreg;
1359 rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
1360 if (rm2 == 0)
1361 rm2 = fpzeroreg;
1362 ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
1363 sizeof(double)/sizeof(u_int);
1364 if (ra == 0)
1365 ra = fpzeroreg;
1366 t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
1367 if (t == 0)
1368 return(MAJOR_2E_EXCP);
1369
1370 if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
1371 return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
1372 &fpregs[ra], &fpregs[0], &fpregs[t]));
1373 } else {
1374 return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
1375 &fpregs[ra], &fpregs[0], &fpregs[t]));
1376 }
1377 } /* end DBL */
1378 else { /* SGL */
1379 rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
1380 if (rm1 == 0)
1381 rm1 = fpzeroreg;
1382 rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
1383 if (rm2 == 0)
1384 rm2 = fpzeroreg;
1385 ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
1386 if (ra == 0)
1387 ra = fpzeroreg;
1388 t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
1389 if (t == 0)
1390 return(MAJOR_2E_EXCP);
1391
1392 if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
1393 return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
1394 &fpregs[ra], &fpregs[0], &fpregs[t]));
1395 } else {
1396 return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
1397 &fpregs[ra], &fpregs[0], &fpregs[t]));
1398 }
1399 } /* end SGL */
1400}
1401
1402/*
1403 * update_status_cbit
1404 *
1405 * This routine returns the correct FP status register value in
1406 * *status, based on the C-bit & V-bit returned by the FCMP
1407 * emulation routine in new_status. The architecture type
1408 * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field
1409 * and the architecture type are used to determine what flavor
1410 * of FCMP is being emulated.
1411 */
1412static void
1413update_status_cbit(status, new_status, fpu_type, y_field)
1414u_int *status, new_status;
1415u_int fpu_type;
1416u_int y_field;
1417{
1418 /*
1419 * For PA89 FPU's which implement the Compare Queue and
1420 * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
1421 * otherwise update the specified bit in the Compare Array.
1422 * Note that the y-field will always be 0 for non-PA2.0 FPU's.
1423 */
1424 if ((fpu_type & TIMEX_EXTEN_FLAG) ||
1425 (fpu_type & ROLEX_EXTEN_FLAG) ||
1426 (fpu_type & PA2_0_FPU_FLAG)) {
1427 if (y_field == 0) {
1428 *status = ((*status & 0x04000000) >> 5) | /* old Cbit */
1429 ((*status & 0x003ff000) >> 1) | /* old CQ */
1430 (new_status & 0xffc007ff); /* all other bits*/
1431 } else {
1432 *status = (*status & 0x04000000) | /* old Cbit */
1433 ((new_status & 0x04000000) >> (y_field+4)) |
1434 (new_status & ~0x04000000 & /* other bits */
1435 ~(0x04000000 >> (y_field+4)));
1436 }
1437 }
1438 /* if PA83, just update the C-bit */
1439 else {
1440 *status = new_status;
1441 }
1442}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * Purpose:
25 * Single Floating-point Round to Integer
26 * Double Floating-point Round to Integer
27 * Quad Floating-point Round to Integer (returns unimplemented)
28 *
29 * External Interfaces:
30 * dbl_frnd(srcptr,nullptr,dstptr,status)
31 * sgl_frnd(srcptr,nullptr,dstptr,status)
32 *
33 * END_DESC
34*/
35
36
37#include "float.h"
38#include "sgl_float.h"
39#include "dbl_float.h"
40#include "cnv_float.h"
41
42/*
43 * Single Floating-point Round to Integer
44 */
45
46/*ARGSUSED*/
47int
48sgl_frnd(sgl_floating_point *srcptr,
49 unsigned int *nullptr,
50 sgl_floating_point *dstptr,
51 unsigned int *status)
52{
53 register unsigned int src, result;
54 register int src_exponent;
55 register boolean inexact = FALSE;
56
57 src = *srcptr;
58 /*
59 * check source operand for NaN or infinity
60 */
61 if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
62 /*
63 * is signaling NaN?
64 */
65 if (Sgl_isone_signaling(src)) {
66 /* trap if INVALIDTRAP enabled */
67 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
68 /* make NaN quiet */
69 Set_invalidflag();
70 Sgl_set_quiet(src);
71 }
72 /*
73 * return quiet NaN or infinity
74 */
75 *dstptr = src;
76 return(NOEXCEPTION);
77 }
78 /*
79 * Need to round?
80 */
81 if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
82 *dstptr = src;
83 return(NOEXCEPTION);
84 }
85 /*
86 * Generate result
87 */
88 if (src_exponent >= 0) {
89 Sgl_clear_exponent_set_hidden(src);
90 result = src;
91 Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
92 /* check for inexact */
93 if (Sgl_isinexact_to_fix(src,src_exponent)) {
94 inexact = TRUE;
95 /* round result */
96 switch (Rounding_mode()) {
97 case ROUNDPLUS:
98 if (Sgl_iszero_sign(src)) Sgl_increment(result);
99 break;
100 case ROUNDMINUS:
101 if (Sgl_isone_sign(src)) Sgl_increment(result);
102 break;
103 case ROUNDNEAREST:
104 if (Sgl_isone_roundbit(src,src_exponent))
105 if (Sgl_isone_stickybit(src,src_exponent)
106 || (Sgl_isone_lowmantissa(result)))
107 Sgl_increment(result);
108 }
109 }
110 Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
111 if (Sgl_isone_hiddenoverflow(result))
112 Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
113 else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
114 }
115 else {
116 result = src; /* set sign */
117 Sgl_setzero_exponentmantissa(result);
118 /* check for inexact */
119 if (Sgl_isnotzero_exponentmantissa(src)) {
120 inexact = TRUE;
121 /* round result */
122 switch (Rounding_mode()) {
123 case ROUNDPLUS:
124 if (Sgl_iszero_sign(src))
125 Sgl_set_exponent(result,SGL_BIAS);
126 break;
127 case ROUNDMINUS:
128 if (Sgl_isone_sign(src))
129 Sgl_set_exponent(result,SGL_BIAS);
130 break;
131 case ROUNDNEAREST:
132 if (src_exponent == -1)
133 if (Sgl_isnotzero_mantissa(src))
134 Sgl_set_exponent(result,SGL_BIAS);
135 }
136 }
137 }
138 *dstptr = result;
139 if (inexact) {
140 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
141 else Set_inexactflag();
142 }
143 return(NOEXCEPTION);
144}
145
146/*
147 * Double Floating-point Round to Integer
148 */
149
150/*ARGSUSED*/
151int
152dbl_frnd(
153 dbl_floating_point *srcptr,
154 unsigned int *nullptr,
155 dbl_floating_point *dstptr,
156 unsigned int *status)
157{
158 register unsigned int srcp1, srcp2, resultp1, resultp2;
159 register int src_exponent;
160 register boolean inexact = FALSE;
161
162 Dbl_copyfromptr(srcptr,srcp1,srcp2);
163 /*
164 * check source operand for NaN or infinity
165 */
166 if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
167 /*
168 * is signaling NaN?
169 */
170 if (Dbl_isone_signaling(srcp1)) {
171 /* trap if INVALIDTRAP enabled */
172 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
173 /* make NaN quiet */
174 Set_invalidflag();
175 Dbl_set_quiet(srcp1);
176 }
177 /*
178 * return quiet NaN or infinity
179 */
180 Dbl_copytoptr(srcp1,srcp2,dstptr);
181 return(NOEXCEPTION);
182 }
183 /*
184 * Need to round?
185 */
186 if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
187 Dbl_copytoptr(srcp1,srcp2,dstptr);
188 return(NOEXCEPTION);
189 }
190 /*
191 * Generate result
192 */
193 if (src_exponent >= 0) {
194 Dbl_clear_exponent_set_hidden(srcp1);
195 resultp1 = srcp1;
196 resultp2 = srcp2;
197 Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
198 /* check for inexact */
199 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
200 inexact = TRUE;
201 /* round result */
202 switch (Rounding_mode()) {
203 case ROUNDPLUS:
204 if (Dbl_iszero_sign(srcp1))
205 Dbl_increment(resultp1,resultp2);
206 break;
207 case ROUNDMINUS:
208 if (Dbl_isone_sign(srcp1))
209 Dbl_increment(resultp1,resultp2);
210 break;
211 case ROUNDNEAREST:
212 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
213 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
214 || (Dbl_isone_lowmantissap2(resultp2)))
215 Dbl_increment(resultp1,resultp2);
216 }
217 }
218 Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
219 if (Dbl_isone_hiddenoverflow(resultp1))
220 Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
221 else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
222 }
223 else {
224 resultp1 = srcp1; /* set sign */
225 Dbl_setzero_exponentmantissa(resultp1,resultp2);
226 /* check for inexact */
227 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
228 inexact = TRUE;
229 /* round result */
230 switch (Rounding_mode()) {
231 case ROUNDPLUS:
232 if (Dbl_iszero_sign(srcp1))
233 Dbl_set_exponent(resultp1,DBL_BIAS);
234 break;
235 case ROUNDMINUS:
236 if (Dbl_isone_sign(srcp1))
237 Dbl_set_exponent(resultp1,DBL_BIAS);
238 break;
239 case ROUNDNEAREST:
240 if (src_exponent == -1)
241 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
242 Dbl_set_exponent(resultp1,DBL_BIAS);
243 }
244 }
245 }
246 Dbl_copytoptr(resultp1,resultp2,dstptr);
247 if (inexact) {
248 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
249 else Set_inexactflag();
250 }
251 return(NOEXCEPTION);
252}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifdef __NO_PA_HDRS
23 PA header file -- do not include this header file for non-PA builds.
24#endif
25
26
27/* amount is assumed to be a constant between 0 and 32 (non-inclusive) */
28#define Shiftdouble(left,right,amount,dest) \
29 /* int left, right, amount, dest; */ \
30 dest = ((left) << (32-(amount))) | ((unsigned int)(right) >> (amount))
31
32/* amount must be less than 32 */
33#define Variableshiftdouble(left,right,amount,dest) \
34 /* unsigned int left, right; int amount, dest; */ \
35 if (amount == 0) dest = right; \
36 else dest = ((((unsigned) left)&0x7fffffff) << (32-(amount))) | \
37 ((unsigned) right >> (amount))
38
39/* amount must be between 0 and 32 (non-inclusive) */
40#define Variable_shift_double(left,right,amount,dest) \
41 /* unsigned int left, right; int amount, dest; */ \
42 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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#ifndef _PARISC_MATH_EMU_H
22#define _PARISC_MATH_EMU_H
23
24#include <asm/ptrace.h>
25extern int handle_fpe(struct pt_regs *regs);
26
27#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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/sfadd.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single_add: add two single precision values.
29 *
30 * External Interfaces:
31 * sgl_fadd(leftptr, rightptr, dstptr, status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "sgl_float.h"
44
45/*
46 * Single_add: add two single precision values.
47 */
48int
49sgl_fadd(
50 sgl_floating_point *leftptr,
51 sgl_floating_point *rightptr,
52 sgl_floating_point *dstptr,
53 unsigned int *status)
54 {
55 register unsigned int left, right, result, extent;
56 register unsigned int signless_upper_left, signless_upper_right, save;
57
58
59 register int result_exponent, right_exponent, diff_exponent;
60 register int sign_save, jumpsize;
61 register boolean inexact = FALSE;
62 register boolean underflowtrap;
63
64 /* Create local copies of the numbers */
65 left = *leftptr;
66 right = *rightptr;
67
68 /* A zero "save" helps discover equal operands (for later), *
69 * and is used in swapping operands (if needed). */
70 Sgl_xortointp1(left,right,/*to*/save);
71
72 /*
73 * check first operand for NaN's or infinity
74 */
75 if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
76 {
77 if (Sgl_iszero_mantissa(left))
78 {
79 if (Sgl_isnotnan(right))
80 {
81 if (Sgl_isinfinity(right) && save!=0)
82 {
83 /*
84 * invalid since operands are opposite signed infinity's
85 */
86 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
87 Set_invalidflag();
88 Sgl_makequietnan(result);
89 *dstptr = result;
90 return(NOEXCEPTION);
91 }
92 /*
93 * return infinity
94 */
95 *dstptr = left;
96 return(NOEXCEPTION);
97 }
98 }
99 else
100 {
101 /*
102 * is NaN; signaling or quiet?
103 */
104 if (Sgl_isone_signaling(left))
105 {
106 /* trap if INVALIDTRAP enabled */
107 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
108 /* make NaN quiet */
109 Set_invalidflag();
110 Sgl_set_quiet(left);
111 }
112 /*
113 * is second operand a signaling NaN?
114 */
115 else if (Sgl_is_signalingnan(right))
116 {
117 /* trap if INVALIDTRAP enabled */
118 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
119 /* make NaN quiet */
120 Set_invalidflag();
121 Sgl_set_quiet(right);
122 *dstptr = right;
123 return(NOEXCEPTION);
124 }
125 /*
126 * return quiet NaN
127 */
128 *dstptr = left;
129 return(NOEXCEPTION);
130 }
131 } /* End left NaN or Infinity processing */
132 /*
133 * check second operand for NaN's or infinity
134 */
135 if (Sgl_isinfinity_exponent(right))
136 {
137 if (Sgl_iszero_mantissa(right))
138 {
139 /* return infinity */
140 *dstptr = right;
141 return(NOEXCEPTION);
142 }
143 /*
144 * is NaN; signaling or quiet?
145 */
146 if (Sgl_isone_signaling(right))
147 {
148 /* trap if INVALIDTRAP enabled */
149 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
150 /* make NaN quiet */
151 Set_invalidflag();
152 Sgl_set_quiet(right);
153 }
154 /*
155 * return quiet NaN
156 */
157 *dstptr = right;
158 return(NOEXCEPTION);
159 } /* End right NaN or Infinity processing */
160
161 /* Invariant: Must be dealing with finite numbers */
162
163 /* Compare operands by removing the sign */
164 Sgl_copytoint_exponentmantissa(left,signless_upper_left);
165 Sgl_copytoint_exponentmantissa(right,signless_upper_right);
166
167 /* sign difference selects add or sub operation. */
168 if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
169 {
170 /* Set the left operand to the larger one by XOR swap *
171 * First finish the first word using "save" */
172 Sgl_xorfromintp1(save,right,/*to*/right);
173 Sgl_xorfromintp1(save,left,/*to*/left);
174 result_exponent = Sgl_exponent(left);
175 }
176 /* Invariant: left is not smaller than right. */
177
178 if((right_exponent = Sgl_exponent(right)) == 0)
179 {
180 /* Denormalized operands. First look for zeroes */
181 if(Sgl_iszero_mantissa(right))
182 {
183 /* right is zero */
184 if(Sgl_iszero_exponentmantissa(left))
185 {
186 /* Both operands are zeros */
187 if(Is_rounding_mode(ROUNDMINUS))
188 {
189 Sgl_or_signs(left,/*with*/right);
190 }
191 else
192 {
193 Sgl_and_signs(left,/*with*/right);
194 }
195 }
196 else
197 {
198 /* Left is not a zero and must be the result. Trapped
199 * underflows are signaled if left is denormalized. Result
200 * is always exact. */
201 if( (result_exponent == 0) && Is_underflowtrap_enabled() )
202 {
203 /* need to normalize results mantissa */
204 sign_save = Sgl_signextendedsign(left);
205 Sgl_leftshiftby1(left);
206 Sgl_normalize(left,result_exponent);
207 Sgl_set_sign(left,/*using*/sign_save);
208 Sgl_setwrapped_exponent(left,result_exponent,unfl);
209 *dstptr = left;
210 return(UNDERFLOWEXCEPTION);
211 }
212 }
213 *dstptr = left;
214 return(NOEXCEPTION);
215 }
216
217 /* Neither are zeroes */
218 Sgl_clear_sign(right); /* Exponent is already cleared */
219 if(result_exponent == 0 )
220 {
221 /* Both operands are denormalized. The result must be exact
222 * and is simply calculated. A sum could become normalized and a
223 * difference could cancel to a true zero. */
224 if( (/*signed*/int) save < 0 )
225 {
226 Sgl_subtract(left,/*minus*/right,/*into*/result);
227 if(Sgl_iszero_mantissa(result))
228 {
229 if(Is_rounding_mode(ROUNDMINUS))
230 {
231 Sgl_setone_sign(result);
232 }
233 else
234 {
235 Sgl_setzero_sign(result);
236 }
237 *dstptr = result;
238 return(NOEXCEPTION);
239 }
240 }
241 else
242 {
243 Sgl_addition(left,right,/*into*/result);
244 if(Sgl_isone_hidden(result))
245 {
246 *dstptr = result;
247 return(NOEXCEPTION);
248 }
249 }
250 if(Is_underflowtrap_enabled())
251 {
252 /* need to normalize result */
253 sign_save = Sgl_signextendedsign(result);
254 Sgl_leftshiftby1(result);
255 Sgl_normalize(result,result_exponent);
256 Sgl_set_sign(result,/*using*/sign_save);
257 Sgl_setwrapped_exponent(result,result_exponent,unfl);
258 *dstptr = result;
259 return(UNDERFLOWEXCEPTION);
260 }
261 *dstptr = result;
262 return(NOEXCEPTION);
263 }
264 right_exponent = 1; /* Set exponent to reflect different bias
265 * with denomalized numbers. */
266 }
267 else
268 {
269 Sgl_clear_signexponent_set_hidden(right);
270 }
271 Sgl_clear_exponent_set_hidden(left);
272 diff_exponent = result_exponent - right_exponent;
273
274 /*
275 * Special case alignment of operands that would force alignment
276 * beyond the extent of the extension. A further optimization
277 * could special case this but only reduces the path length for this
278 * infrequent case.
279 */
280 if(diff_exponent > SGL_THRESHOLD)
281 {
282 diff_exponent = SGL_THRESHOLD;
283 }
284
285 /* Align right operand by shifting to right */
286 Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
287 /*and lower to*/extent);
288
289 /* Treat sum and difference of the operands separately. */
290 if( (/*signed*/int) save < 0 )
291 {
292 /*
293 * Difference of the two operands. Their can be no overflow. A
294 * borrow can occur out of the hidden bit and force a post
295 * normalization phase.
296 */
297 Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
298 if(Sgl_iszero_hidden(result))
299 {
300 /* Handle normalization */
301 /* A straight foward algorithm would now shift the result
302 * and extension left until the hidden bit becomes one. Not
303 * all of the extension bits need participate in the shift.
304 * Only the two most significant bits (round and guard) are
305 * needed. If only a single shift is needed then the guard
306 * bit becomes a significant low order bit and the extension
307 * must participate in the rounding. If more than a single
308 * shift is needed, then all bits to the right of the guard
309 * bit are zeros, and the guard bit may or may not be zero. */
310 sign_save = Sgl_signextendedsign(result);
311 Sgl_leftshiftby1_withextent(result,extent,result);
312
313 /* Need to check for a zero result. The sign and exponent
314 * fields have already been zeroed. The more efficient test
315 * of the full object can be used.
316 */
317 if(Sgl_iszero(result))
318 /* Must have been "x-x" or "x+(-x)". */
319 {
320 if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
321 *dstptr = result;
322 return(NOEXCEPTION);
323 }
324 result_exponent--;
325 /* Look to see if normalization is finished. */
326 if(Sgl_isone_hidden(result))
327 {
328 if(result_exponent==0)
329 {
330 /* Denormalized, exponent should be zero. Left operand *
331 * was normalized, so extent (guard, round) was zero */
332 goto underflow;
333 }
334 else
335 {
336 /* No further normalization is needed. */
337 Sgl_set_sign(result,/*using*/sign_save);
338 Ext_leftshiftby1(extent);
339 goto round;
340 }
341 }
342
343 /* Check for denormalized, exponent should be zero. Left *
344 * operand was normalized, so extent (guard, round) was zero */
345 if(!(underflowtrap = Is_underflowtrap_enabled()) &&
346 result_exponent==0) goto underflow;
347
348 /* Shift extension to complete one bit of normalization and
349 * update exponent. */
350 Ext_leftshiftby1(extent);
351
352 /* Discover first one bit to determine shift amount. Use a
353 * modified binary search. We have already shifted the result
354 * one position right and still not found a one so the remainder
355 * of the extension must be zero and simplifies rounding. */
356 /* Scan bytes */
357 while(Sgl_iszero_hiddenhigh7mantissa(result))
358 {
359 Sgl_leftshiftby8(result);
360 if((result_exponent -= 8) <= 0 && !underflowtrap)
361 goto underflow;
362 }
363 /* Now narrow it down to the nibble */
364 if(Sgl_iszero_hiddenhigh3mantissa(result))
365 {
366 /* The lower nibble contains the normalizing one */
367 Sgl_leftshiftby4(result);
368 if((result_exponent -= 4) <= 0 && !underflowtrap)
369 goto underflow;
370 }
371 /* Select case were first bit is set (already normalized)
372 * otherwise select the proper shift. */
373 if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
374 {
375 /* Already normalized */
376 if(result_exponent <= 0) goto underflow;
377 Sgl_set_sign(result,/*using*/sign_save);
378 Sgl_set_exponent(result,/*using*/result_exponent);
379 *dstptr = result;
380 return(NOEXCEPTION);
381 }
382 Sgl_sethigh4bits(result,/*using*/sign_save);
383 switch(jumpsize)
384 {
385 case 1:
386 {
387 Sgl_leftshiftby3(result);
388 result_exponent -= 3;
389 break;
390 }
391 case 2:
392 case 3:
393 {
394 Sgl_leftshiftby2(result);
395 result_exponent -= 2;
396 break;
397 }
398 case 4:
399 case 5:
400 case 6:
401 case 7:
402 {
403 Sgl_leftshiftby1(result);
404 result_exponent -= 1;
405 break;
406 }
407 }
408 if(result_exponent > 0)
409 {
410 Sgl_set_exponent(result,/*using*/result_exponent);
411 *dstptr = result;
412 return(NOEXCEPTION); /* Sign bit is already set */
413 }
414 /* Fixup potential underflows */
415 underflow:
416 if(Is_underflowtrap_enabled())
417 {
418 Sgl_set_sign(result,sign_save);
419 Sgl_setwrapped_exponent(result,result_exponent,unfl);
420 *dstptr = result;
421 /* inexact = FALSE; */
422 return(UNDERFLOWEXCEPTION);
423 }
424 /*
425 * Since we cannot get an inexact denormalized result,
426 * we can now return.
427 */
428 Sgl_right_align(result,/*by*/(1-result_exponent),extent);
429 Sgl_clear_signexponent(result);
430 Sgl_set_sign(result,sign_save);
431 *dstptr = result;
432 return(NOEXCEPTION);
433 } /* end if(hidden...)... */
434 /* Fall through and round */
435 } /* end if(save < 0)... */
436 else
437 {
438 /* Add magnitudes */
439 Sgl_addition(left,right,/*to*/result);
440 if(Sgl_isone_hiddenoverflow(result))
441 {
442 /* Prenormalization required. */
443 Sgl_rightshiftby1_withextent(result,extent,extent);
444 Sgl_arithrightshiftby1(result);
445 result_exponent++;
446 } /* end if hiddenoverflow... */
447 } /* end else ...add magnitudes... */
448
449 /* Round the result. If the extension is all zeros,then the result is
450 * exact. Otherwise round in the correct direction. No underflow is
451 * possible. If a postnormalization is necessary, then the mantissa is
452 * all zeros so no shift is needed. */
453 round:
454 if(Ext_isnotzero(extent))
455 {
456 inexact = TRUE;
457 switch(Rounding_mode())
458 {
459 case ROUNDNEAREST: /* The default. */
460 if(Ext_isone_sign(extent))
461 {
462 /* at least 1/2 ulp */
463 if(Ext_isnotzero_lower(extent) ||
464 Sgl_isone_lowmantissa(result))
465 {
466 /* either exactly half way and odd or more than 1/2ulp */
467 Sgl_increment(result);
468 }
469 }
470 break;
471
472 case ROUNDPLUS:
473 if(Sgl_iszero_sign(result))
474 {
475 /* Round up positive results */
476 Sgl_increment(result);
477 }
478 break;
479
480 case ROUNDMINUS:
481 if(Sgl_isone_sign(result))
482 {
483 /* Round down negative results */
484 Sgl_increment(result);
485 }
486
487 case ROUNDZERO:;
488 /* truncate is simple */
489 } /* end switch... */
490 if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
491 }
492 if(result_exponent == SGL_INFINITY_EXPONENT)
493 {
494 /* Overflow */
495 if(Is_overflowtrap_enabled())
496 {
497 Sgl_setwrapped_exponent(result,result_exponent,ovfl);
498 *dstptr = result;
499 if (inexact)
500 if (Is_inexacttrap_enabled())
501 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
502 else Set_inexactflag();
503 return(OVERFLOWEXCEPTION);
504 }
505 else
506 {
507 Set_overflowflag();
508 inexact = TRUE;
509 Sgl_setoverflow(result);
510 }
511 }
512 else Sgl_set_exponent(result,result_exponent);
513 *dstptr = result;
514 if(inexact)
515 if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
516 else Set_inexactflag();
517 return(NOEXCEPTION);
518 }
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/sfcmp.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * sgl_cmp: compare two values
29 *
30 * External Interfaces:
31 * sgl_fcmp(leftptr, rightptr, cond, status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "sgl_float.h"
44
45/*
46 * sgl_cmp: compare two values
47 */
48int
49sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr,
50 unsigned int cond, unsigned int *status)
51
52 /* The predicate to be tested */
53
54 {
55 register unsigned int left, right;
56 register int xorresult;
57
58 /* Create local copies of the numbers */
59 left = *leftptr;
60 right = *rightptr;
61
62 /*
63 * Test for NaN
64 */
65 if( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
66 || (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) )
67 {
68 /* Check if a NaN is involved. Signal an invalid exception when
69 * comparing a signaling NaN or when comparing quiet NaNs and the
70 * low bit of the condition is set */
71 if( ( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
72 && Sgl_isnotzero_mantissa(left)
73 && (Exception(cond) || Sgl_isone_signaling(left)))
74 ||
75 ( (Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
76 && Sgl_isnotzero_mantissa(right)
77 && (Exception(cond) || Sgl_isone_signaling(right)) ) )
78 {
79 if( Is_invalidtrap_enabled() ) {
80 Set_status_cbit(Unordered(cond));
81 return(INVALIDEXCEPTION);
82 }
83 else Set_invalidflag();
84 Set_status_cbit(Unordered(cond));
85 return(NOEXCEPTION);
86 }
87 /* All the exceptional conditions are handled, now special case
88 NaN compares */
89 else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
90 && Sgl_isnotzero_mantissa(left))
91 ||
92 ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
93 && Sgl_isnotzero_mantissa(right)) )
94 {
95 /* NaNs always compare unordered. */
96 Set_status_cbit(Unordered(cond));
97 return(NOEXCEPTION);
98 }
99 /* infinities will drop down to the normal compare mechanisms */
100 }
101 /* First compare for unequal signs => less or greater or
102 * special equal case */
103 Sgl_xortointp1(left,right,xorresult);
104 if( xorresult < 0 )
105 {
106 /* left negative => less, left positive => greater.
107 * equal is possible if both operands are zeros. */
108 if( Sgl_iszero_exponentmantissa(left)
109 && Sgl_iszero_exponentmantissa(right) )
110 {
111 Set_status_cbit(Equal(cond));
112 }
113 else if( Sgl_isone_sign(left) )
114 {
115 Set_status_cbit(Lessthan(cond));
116 }
117 else
118 {
119 Set_status_cbit(Greaterthan(cond));
120 }
121 }
122 /* Signs are the same. Treat negative numbers separately
123 * from the positives because of the reversed sense. */
124 else if( Sgl_all(left) == Sgl_all(right) )
125 {
126 Set_status_cbit(Equal(cond));
127 }
128 else if( Sgl_iszero_sign(left) )
129 {
130 /* Positive compare */
131 if( Sgl_all(left) < Sgl_all(right) )
132 {
133 Set_status_cbit(Lessthan(cond));
134 }
135 else
136 {
137 Set_status_cbit(Greaterthan(cond));
138 }
139 }
140 else
141 {
142 /* Negative compare. Signed or unsigned compares
143 * both work the same. That distinction is only
144 * important when the sign bits differ. */
145 if( Sgl_all(left) > Sgl_all(right) )
146 {
147 Set_status_cbit(Lessthan(cond));
148 }
149 else
150 {
151 Set_status_cbit(Greaterthan(cond));
152 }
153 }
154 return(NOEXCEPTION);
155 }
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/sfdiv.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single Precision Floating-point Divide
29 *
30 * External Interfaces:
31 * sgl_fdiv(srcptr1,srcptr2,dstptr,status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "sgl_float.h"
44
45/*
46 * Single Precision Floating-point Divide
47 */
48
49int
50sgl_fdiv (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
51 sgl_floating_point * dstptr, unsigned int *status)
52{
53 register unsigned int opnd1, opnd2, opnd3, result;
54 register int dest_exponent, count;
55 register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
56 boolean is_tiny;
57
58 opnd1 = *srcptr1;
59 opnd2 = *srcptr2;
60 /*
61 * set sign bit of result
62 */
63 if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);
64 else Sgl_setzero(result);
65 /*
66 * check first operand for NaN's or infinity
67 */
68 if (Sgl_isinfinity_exponent(opnd1)) {
69 if (Sgl_iszero_mantissa(opnd1)) {
70 if (Sgl_isnotnan(opnd2)) {
71 if (Sgl_isinfinity(opnd2)) {
72 /*
73 * invalid since both operands
74 * are infinity
75 */
76 if (Is_invalidtrap_enabled())
77 return(INVALIDEXCEPTION);
78 Set_invalidflag();
79 Sgl_makequietnan(result);
80 *dstptr = result;
81 return(NOEXCEPTION);
82 }
83 /*
84 * return infinity
85 */
86 Sgl_setinfinity_exponentmantissa(result);
87 *dstptr = result;
88 return(NOEXCEPTION);
89 }
90 }
91 else {
92 /*
93 * is NaN; signaling or quiet?
94 */
95 if (Sgl_isone_signaling(opnd1)) {
96 /* trap if INVALIDTRAP enabled */
97 if (Is_invalidtrap_enabled())
98 return(INVALIDEXCEPTION);
99 /* make NaN quiet */
100 Set_invalidflag();
101 Sgl_set_quiet(opnd1);
102 }
103 /*
104 * is second operand a signaling NaN?
105 */
106 else if (Sgl_is_signalingnan(opnd2)) {
107 /* trap if INVALIDTRAP enabled */
108 if (Is_invalidtrap_enabled())
109 return(INVALIDEXCEPTION);
110 /* make NaN quiet */
111 Set_invalidflag();
112 Sgl_set_quiet(opnd2);
113 *dstptr = opnd2;
114 return(NOEXCEPTION);
115 }
116 /*
117 * return quiet NaN
118 */
119 *dstptr = opnd1;
120 return(NOEXCEPTION);
121 }
122 }
123 /*
124 * check second operand for NaN's or infinity
125 */
126 if (Sgl_isinfinity_exponent(opnd2)) {
127 if (Sgl_iszero_mantissa(opnd2)) {
128 /*
129 * return zero
130 */
131 Sgl_setzero_exponentmantissa(result);
132 *dstptr = result;
133 return(NOEXCEPTION);
134 }
135 /*
136 * is NaN; signaling or quiet?
137 */
138 if (Sgl_isone_signaling(opnd2)) {
139 /* trap if INVALIDTRAP enabled */
140 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
141 /* make NaN quiet */
142 Set_invalidflag();
143 Sgl_set_quiet(opnd2);
144 }
145 /*
146 * return quiet NaN
147 */
148 *dstptr = opnd2;
149 return(NOEXCEPTION);
150 }
151 /*
152 * check for division by zero
153 */
154 if (Sgl_iszero_exponentmantissa(opnd2)) {
155 if (Sgl_iszero_exponentmantissa(opnd1)) {
156 /* invalid since both operands are zero */
157 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
158 Set_invalidflag();
159 Sgl_makequietnan(result);
160 *dstptr = result;
161 return(NOEXCEPTION);
162 }
163 if (Is_divisionbyzerotrap_enabled())
164 return(DIVISIONBYZEROEXCEPTION);
165 Set_divisionbyzeroflag();
166 Sgl_setinfinity_exponentmantissa(result);
167 *dstptr = result;
168 return(NOEXCEPTION);
169 }
170 /*
171 * Generate exponent
172 */
173 dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS;
174
175 /*
176 * Generate mantissa
177 */
178 if (Sgl_isnotzero_exponent(opnd1)) {
179 /* set hidden bit */
180 Sgl_clear_signexponent_set_hidden(opnd1);
181 }
182 else {
183 /* check for zero */
184 if (Sgl_iszero_mantissa(opnd1)) {
185 Sgl_setzero_exponentmantissa(result);
186 *dstptr = result;
187 return(NOEXCEPTION);
188 }
189 /* is denormalized; want to normalize */
190 Sgl_clear_signexponent(opnd1);
191 Sgl_leftshiftby1(opnd1);
192 Sgl_normalize(opnd1,dest_exponent);
193 }
194 /* opnd2 needs to have hidden bit set with msb in hidden bit */
195 if (Sgl_isnotzero_exponent(opnd2)) {
196 Sgl_clear_signexponent_set_hidden(opnd2);
197 }
198 else {
199 /* is denormalized; want to normalize */
200 Sgl_clear_signexponent(opnd2);
201 Sgl_leftshiftby1(opnd2);
202 while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) {
203 Sgl_leftshiftby8(opnd2);
204 dest_exponent += 8;
205 }
206 if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) {
207 Sgl_leftshiftby4(opnd2);
208 dest_exponent += 4;
209 }
210 while(Sgl_iszero_hidden(opnd2)) {
211 Sgl_leftshiftby1(opnd2);
212 dest_exponent += 1;
213 }
214 }
215
216 /* Divide the source mantissas */
217
218 /*
219 * A non_restoring divide algorithm is used.
220 */
221 Sgl_subtract(opnd1,opnd2,opnd1);
222 Sgl_setzero(opnd3);
223 for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) {
224 Sgl_leftshiftby1(opnd1);
225 Sgl_leftshiftby1(opnd3);
226 if (Sgl_iszero_sign(opnd1)) {
227 Sgl_setone_lowmantissa(opnd3);
228 Sgl_subtract(opnd1,opnd2,opnd1);
229 }
230 else Sgl_addition(opnd1,opnd2,opnd1);
231 }
232 if (count <= SGL_P) {
233 Sgl_leftshiftby1(opnd3);
234 Sgl_setone_lowmantissa(opnd3);
235 Sgl_leftshift(opnd3,SGL_P-count);
236 if (Sgl_iszero_hidden(opnd3)) {
237 Sgl_leftshiftby1(opnd3);
238 dest_exponent--;
239 }
240 }
241 else {
242 if (Sgl_iszero_hidden(opnd3)) {
243 /* need to get one more bit of result */
244 Sgl_leftshiftby1(opnd1);
245 Sgl_leftshiftby1(opnd3);
246 if (Sgl_iszero_sign(opnd1)) {
247 Sgl_setone_lowmantissa(opnd3);
248 Sgl_subtract(opnd1,opnd2,opnd1);
249 }
250 else Sgl_addition(opnd1,opnd2,opnd1);
251 dest_exponent--;
252 }
253 if (Sgl_iszero_sign(opnd1)) guardbit = TRUE;
254 stickybit = Sgl_all(opnd1);
255 }
256 inexact = guardbit | stickybit;
257
258 /*
259 * round result
260 */
261 if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
262 Sgl_clear_signexponent(opnd3);
263 switch (Rounding_mode()) {
264 case ROUNDPLUS:
265 if (Sgl_iszero_sign(result))
266 Sgl_increment_mantissa(opnd3);
267 break;
268 case ROUNDMINUS:
269 if (Sgl_isone_sign(result))
270 Sgl_increment_mantissa(opnd3);
271 break;
272 case ROUNDNEAREST:
273 if (guardbit) {
274 if (stickybit || Sgl_isone_lowmantissa(opnd3))
275 Sgl_increment_mantissa(opnd3);
276 }
277 }
278 if (Sgl_isone_hidden(opnd3)) dest_exponent++;
279 }
280 Sgl_set_mantissa(result,opnd3);
281
282 /*
283 * Test for overflow
284 */
285 if (dest_exponent >= SGL_INFINITY_EXPONENT) {
286 /* trap if OVERFLOWTRAP enabled */
287 if (Is_overflowtrap_enabled()) {
288 /*
289 * Adjust bias of result
290 */
291 Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
292 *dstptr = result;
293 if (inexact)
294 if (Is_inexacttrap_enabled())
295 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
296 else Set_inexactflag();
297 return(OVERFLOWEXCEPTION);
298 }
299 Set_overflowflag();
300 /* set result to infinity or largest number */
301 Sgl_setoverflow(result);
302 inexact = TRUE;
303 }
304 /*
305 * Test for underflow
306 */
307 else if (dest_exponent <= 0) {
308 /* trap if UNDERFLOWTRAP enabled */
309 if (Is_underflowtrap_enabled()) {
310 /*
311 * Adjust bias of result
312 */
313 Sgl_setwrapped_exponent(result,dest_exponent,unfl);
314 *dstptr = result;
315 if (inexact)
316 if (Is_inexacttrap_enabled())
317 return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
318 else Set_inexactflag();
319 return(UNDERFLOWEXCEPTION);
320 }
321
322 /* Determine if should set underflow flag */
323 is_tiny = TRUE;
324 if (dest_exponent == 0 && inexact) {
325 switch (Rounding_mode()) {
326 case ROUNDPLUS:
327 if (Sgl_iszero_sign(result)) {
328 Sgl_increment(opnd3);
329 if (Sgl_isone_hiddenoverflow(opnd3))
330 is_tiny = FALSE;
331 Sgl_decrement(opnd3);
332 }
333 break;
334 case ROUNDMINUS:
335 if (Sgl_isone_sign(result)) {
336 Sgl_increment(opnd3);
337 if (Sgl_isone_hiddenoverflow(opnd3))
338 is_tiny = FALSE;
339 Sgl_decrement(opnd3);
340 }
341 break;
342 case ROUNDNEAREST:
343 if (guardbit && (stickybit ||
344 Sgl_isone_lowmantissa(opnd3))) {
345 Sgl_increment(opnd3);
346 if (Sgl_isone_hiddenoverflow(opnd3))
347 is_tiny = FALSE;
348 Sgl_decrement(opnd3);
349 }
350 break;
351 }
352 }
353
354 /*
355 * denormalize result or set to signed zero
356 */
357 stickybit = inexact;
358 Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
359
360 /* return rounded number */
361 if (inexact) {
362 switch (Rounding_mode()) {
363 case ROUNDPLUS:
364 if (Sgl_iszero_sign(result)) {
365 Sgl_increment(opnd3);
366 }
367 break;
368 case ROUNDMINUS:
369 if (Sgl_isone_sign(result)) {
370 Sgl_increment(opnd3);
371 }
372 break;
373 case ROUNDNEAREST:
374 if (guardbit && (stickybit ||
375 Sgl_isone_lowmantissa(opnd3))) {
376 Sgl_increment(opnd3);
377 }
378 break;
379 }
380 if (is_tiny) Set_underflowflag();
381 }
382 Sgl_set_exponentmantissa(result,opnd3);
383 }
384 else Sgl_set_exponent(result,dest_exponent);
385 *dstptr = result;
386 /* check for inexact */
387 if (inexact) {
388 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
389 else Set_inexactflag();
390 }
391 return(NOEXCEPTION);
392}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/sfmpy.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single Precision Floating-point Multiply
29 *
30 * External Interfaces:
31 * sgl_fmpy(srcptr1,srcptr2,dstptr,status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "sgl_float.h"
44
45/*
46 * Single Precision Floating-point Multiply
47 */
48
49int
50sgl_fmpy(
51 sgl_floating_point *srcptr1,
52 sgl_floating_point *srcptr2,
53 sgl_floating_point *dstptr,
54 unsigned int *status)
55{
56 register unsigned int opnd1, opnd2, opnd3, result;
57 register int dest_exponent, count;
58 register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
59 boolean is_tiny;
60
61 opnd1 = *srcptr1;
62 opnd2 = *srcptr2;
63 /*
64 * set sign bit of result
65 */
66 if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);
67 else Sgl_setzero(result);
68 /*
69 * check first operand for NaN's or infinity
70 */
71 if (Sgl_isinfinity_exponent(opnd1)) {
72 if (Sgl_iszero_mantissa(opnd1)) {
73 if (Sgl_isnotnan(opnd2)) {
74 if (Sgl_iszero_exponentmantissa(opnd2)) {
75 /*
76 * invalid since operands are infinity
77 * and zero
78 */
79 if (Is_invalidtrap_enabled())
80 return(INVALIDEXCEPTION);
81 Set_invalidflag();
82 Sgl_makequietnan(result);
83 *dstptr = result;
84 return(NOEXCEPTION);
85 }
86 /*
87 * return infinity
88 */
89 Sgl_setinfinity_exponentmantissa(result);
90 *dstptr = result;
91 return(NOEXCEPTION);
92 }
93 }
94 else {
95 /*
96 * is NaN; signaling or quiet?
97 */
98 if (Sgl_isone_signaling(opnd1)) {
99 /* trap if INVALIDTRAP enabled */
100 if (Is_invalidtrap_enabled())
101 return(INVALIDEXCEPTION);
102 /* make NaN quiet */
103 Set_invalidflag();
104 Sgl_set_quiet(opnd1);
105 }
106 /*
107 * is second operand a signaling NaN?
108 */
109 else if (Sgl_is_signalingnan(opnd2)) {
110 /* trap if INVALIDTRAP enabled */
111 if (Is_invalidtrap_enabled())
112 return(INVALIDEXCEPTION);
113 /* make NaN quiet */
114 Set_invalidflag();
115 Sgl_set_quiet(opnd2);
116 *dstptr = opnd2;
117 return(NOEXCEPTION);
118 }
119 /*
120 * return quiet NaN
121 */
122 *dstptr = opnd1;
123 return(NOEXCEPTION);
124 }
125 }
126 /*
127 * check second operand for NaN's or infinity
128 */
129 if (Sgl_isinfinity_exponent(opnd2)) {
130 if (Sgl_iszero_mantissa(opnd2)) {
131 if (Sgl_iszero_exponentmantissa(opnd1)) {
132 /* invalid since operands are zero & infinity */
133 if (Is_invalidtrap_enabled())
134 return(INVALIDEXCEPTION);
135 Set_invalidflag();
136 Sgl_makequietnan(opnd2);
137 *dstptr = opnd2;
138 return(NOEXCEPTION);
139 }
140 /*
141 * return infinity
142 */
143 Sgl_setinfinity_exponentmantissa(result);
144 *dstptr = result;
145 return(NOEXCEPTION);
146 }
147 /*
148 * is NaN; signaling or quiet?
149 */
150 if (Sgl_isone_signaling(opnd2)) {
151 /* trap if INVALIDTRAP enabled */
152 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
153
154 /* make NaN quiet */
155 Set_invalidflag();
156 Sgl_set_quiet(opnd2);
157 }
158 /*
159 * return quiet NaN
160 */
161 *dstptr = opnd2;
162 return(NOEXCEPTION);
163 }
164 /*
165 * Generate exponent
166 */
167 dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
168
169 /*
170 * Generate mantissa
171 */
172 if (Sgl_isnotzero_exponent(opnd1)) {
173 /* set hidden bit */
174 Sgl_clear_signexponent_set_hidden(opnd1);
175 }
176 else {
177 /* check for zero */
178 if (Sgl_iszero_mantissa(opnd1)) {
179 Sgl_setzero_exponentmantissa(result);
180 *dstptr = result;
181 return(NOEXCEPTION);
182 }
183 /* is denormalized, adjust exponent */
184 Sgl_clear_signexponent(opnd1);
185 Sgl_leftshiftby1(opnd1);
186 Sgl_normalize(opnd1,dest_exponent);
187 }
188 /* opnd2 needs to have hidden bit set with msb in hidden bit */
189 if (Sgl_isnotzero_exponent(opnd2)) {
190 Sgl_clear_signexponent_set_hidden(opnd2);
191 }
192 else {
193 /* check for zero */
194 if (Sgl_iszero_mantissa(opnd2)) {
195 Sgl_setzero_exponentmantissa(result);
196 *dstptr = result;
197 return(NOEXCEPTION);
198 }
199 /* is denormalized; want to normalize */
200 Sgl_clear_signexponent(opnd2);
201 Sgl_leftshiftby1(opnd2);
202 Sgl_normalize(opnd2,dest_exponent);
203 }
204
205 /* Multiply two source mantissas together */
206
207 Sgl_leftshiftby4(opnd2); /* make room for guard bits */
208 Sgl_setzero(opnd3);
209 /*
210 * Four bits at a time are inspected in each loop, and a
211 * simple shift and add multiply algorithm is used.
212 */
213 for (count=1;count<SGL_P;count+=4) {
214 stickybit |= Slow4(opnd3);
215 Sgl_rightshiftby4(opnd3);
216 if (Sbit28(opnd1)) Sall(opnd3) += (Sall(opnd2) << 3);
217 if (Sbit29(opnd1)) Sall(opnd3) += (Sall(opnd2) << 2);
218 if (Sbit30(opnd1)) Sall(opnd3) += (Sall(opnd2) << 1);
219 if (Sbit31(opnd1)) Sall(opnd3) += Sall(opnd2);
220 Sgl_rightshiftby4(opnd1);
221 }
222 /* make sure result is left-justified */
223 if (Sgl_iszero_sign(opnd3)) {
224 Sgl_leftshiftby1(opnd3);
225 }
226 else {
227 /* result mantissa >= 2. */
228 dest_exponent++;
229 }
230 /* check for denormalized result */
231 while (Sgl_iszero_sign(opnd3)) {
232 Sgl_leftshiftby1(opnd3);
233 dest_exponent--;
234 }
235 /*
236 * check for guard, sticky and inexact bits
237 */
238 stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1);
239 guardbit = Sbit24(opnd3);
240 inexact = guardbit | stickybit;
241
242 /* re-align mantissa */
243 Sgl_rightshiftby8(opnd3);
244
245 /*
246 * round result
247 */
248 if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
249 Sgl_clear_signexponent(opnd3);
250 switch (Rounding_mode()) {
251 case ROUNDPLUS:
252 if (Sgl_iszero_sign(result))
253 Sgl_increment(opnd3);
254 break;
255 case ROUNDMINUS:
256 if (Sgl_isone_sign(result))
257 Sgl_increment(opnd3);
258 break;
259 case ROUNDNEAREST:
260 if (guardbit) {
261 if (stickybit || Sgl_isone_lowmantissa(opnd3))
262 Sgl_increment(opnd3);
263 }
264 }
265 if (Sgl_isone_hidden(opnd3)) dest_exponent++;
266 }
267 Sgl_set_mantissa(result,opnd3);
268
269 /*
270 * Test for overflow
271 */
272 if (dest_exponent >= SGL_INFINITY_EXPONENT) {
273 /* trap if OVERFLOWTRAP enabled */
274 if (Is_overflowtrap_enabled()) {
275 /*
276 * Adjust bias of result
277 */
278 Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
279 *dstptr = result;
280 if (inexact)
281 if (Is_inexacttrap_enabled())
282 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
283 else Set_inexactflag();
284 return(OVERFLOWEXCEPTION);
285 }
286 inexact = TRUE;
287 Set_overflowflag();
288 /* set result to infinity or largest number */
289 Sgl_setoverflow(result);
290 }
291 /*
292 * Test for underflow
293 */
294 else if (dest_exponent <= 0) {
295 /* trap if UNDERFLOWTRAP enabled */
296 if (Is_underflowtrap_enabled()) {
297 /*
298 * Adjust bias of result
299 */
300 Sgl_setwrapped_exponent(result,dest_exponent,unfl);
301 *dstptr = result;
302 if (inexact)
303 if (Is_inexacttrap_enabled())
304 return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
305 else Set_inexactflag();
306 return(UNDERFLOWEXCEPTION);
307 }
308
309 /* Determine if should set underflow flag */
310 is_tiny = TRUE;
311 if (dest_exponent == 0 && inexact) {
312 switch (Rounding_mode()) {
313 case ROUNDPLUS:
314 if (Sgl_iszero_sign(result)) {
315 Sgl_increment(opnd3);
316 if (Sgl_isone_hiddenoverflow(opnd3))
317 is_tiny = FALSE;
318 Sgl_decrement(opnd3);
319 }
320 break;
321 case ROUNDMINUS:
322 if (Sgl_isone_sign(result)) {
323 Sgl_increment(opnd3);
324 if (Sgl_isone_hiddenoverflow(opnd3))
325 is_tiny = FALSE;
326 Sgl_decrement(opnd3);
327 }
328 break;
329 case ROUNDNEAREST:
330 if (guardbit && (stickybit ||
331 Sgl_isone_lowmantissa(opnd3))) {
332 Sgl_increment(opnd3);
333 if (Sgl_isone_hiddenoverflow(opnd3))
334 is_tiny = FALSE;
335 Sgl_decrement(opnd3);
336 }
337 break;
338 }
339 }
340
341 /*
342 * denormalize result or set to signed zero
343 */
344 stickybit = inexact;
345 Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
346
347 /* return zero or smallest number */
348 if (inexact) {
349 switch (Rounding_mode()) {
350 case ROUNDPLUS:
351 if (Sgl_iszero_sign(result)) {
352 Sgl_increment(opnd3);
353 }
354 break;
355 case ROUNDMINUS:
356 if (Sgl_isone_sign(result)) {
357 Sgl_increment(opnd3);
358 }
359 break;
360 case ROUNDNEAREST:
361 if (guardbit && (stickybit ||
362 Sgl_isone_lowmantissa(opnd3))) {
363 Sgl_increment(opnd3);
364 }
365 break;
366 }
367 if (is_tiny) Set_underflowflag();
368 }
369 Sgl_set_exponentmantissa(result,opnd3);
370 }
371 else Sgl_set_exponent(result,dest_exponent);
372 *dstptr = result;
373
374 /* check for inexact */
375 if (inexact) {
376 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
377 else Set_inexactflag();
378 }
379 return(NOEXCEPTION);
380}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/sfrem.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single Precision Floating-point Remainder
29 *
30 * External Interfaces:
31 * sgl_frem(srcptr1,srcptr2,dstptr,status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42
43#include "float.h"
44#include "sgl_float.h"
45
46/*
47 * Single Precision Floating-point Remainder
48 */
49
50int
51sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
52 sgl_floating_point * dstptr, unsigned int *status)
53{
54 register unsigned int opnd1, opnd2, result;
55 register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
56 register boolean roundup = FALSE;
57
58 opnd1 = *srcptr1;
59 opnd2 = *srcptr2;
60 /*
61 * check first operand for NaN's or infinity
62 */
63 if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) {
64 if (Sgl_iszero_mantissa(opnd1)) {
65 if (Sgl_isnotnan(opnd2)) {
66 /* invalid since first operand is infinity */
67 if (Is_invalidtrap_enabled())
68 return(INVALIDEXCEPTION);
69 Set_invalidflag();
70 Sgl_makequietnan(result);
71 *dstptr = result;
72 return(NOEXCEPTION);
73 }
74 }
75 else {
76 /*
77 * is NaN; signaling or quiet?
78 */
79 if (Sgl_isone_signaling(opnd1)) {
80 /* trap if INVALIDTRAP enabled */
81 if (Is_invalidtrap_enabled())
82 return(INVALIDEXCEPTION);
83 /* make NaN quiet */
84 Set_invalidflag();
85 Sgl_set_quiet(opnd1);
86 }
87 /*
88 * is second operand a signaling NaN?
89 */
90 else if (Sgl_is_signalingnan(opnd2)) {
91 /* trap if INVALIDTRAP enabled */
92 if (Is_invalidtrap_enabled())
93 return(INVALIDEXCEPTION);
94 /* make NaN quiet */
95 Set_invalidflag();
96 Sgl_set_quiet(opnd2);
97 *dstptr = opnd2;
98 return(NOEXCEPTION);
99 }
100 /*
101 * return quiet NaN
102 */
103 *dstptr = opnd1;
104 return(NOEXCEPTION);
105 }
106 }
107 /*
108 * check second operand for NaN's or infinity
109 */
110 if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) {
111 if (Sgl_iszero_mantissa(opnd2)) {
112 /*
113 * return first operand
114 */
115 *dstptr = opnd1;
116 return(NOEXCEPTION);
117 }
118 /*
119 * is NaN; signaling or quiet?
120 */
121 if (Sgl_isone_signaling(opnd2)) {
122 /* trap if INVALIDTRAP enabled */
123 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
124 /* make NaN quiet */
125 Set_invalidflag();
126 Sgl_set_quiet(opnd2);
127 }
128 /*
129 * return quiet NaN
130 */
131 *dstptr = opnd2;
132 return(NOEXCEPTION);
133 }
134 /*
135 * check second operand for zero
136 */
137 if (Sgl_iszero_exponentmantissa(opnd2)) {
138 /* invalid since second operand is zero */
139 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
140 Set_invalidflag();
141 Sgl_makequietnan(result);
142 *dstptr = result;
143 return(NOEXCEPTION);
144 }
145
146 /*
147 * get sign of result
148 */
149 result = opnd1;
150
151 /*
152 * check for denormalized operands
153 */
154 if (opnd1_exponent == 0) {
155 /* check for zero */
156 if (Sgl_iszero_mantissa(opnd1)) {
157 *dstptr = opnd1;
158 return(NOEXCEPTION);
159 }
160 /* normalize, then continue */
161 opnd1_exponent = 1;
162 Sgl_normalize(opnd1,opnd1_exponent);
163 }
164 else {
165 Sgl_clear_signexponent_set_hidden(opnd1);
166 }
167 if (opnd2_exponent == 0) {
168 /* normalize, then continue */
169 opnd2_exponent = 1;
170 Sgl_normalize(opnd2,opnd2_exponent);
171 }
172 else {
173 Sgl_clear_signexponent_set_hidden(opnd2);
174 }
175
176 /* find result exponent and divide step loop count */
177 dest_exponent = opnd2_exponent - 1;
178 stepcount = opnd1_exponent - opnd2_exponent;
179
180 /*
181 * check for opnd1/opnd2 < 1
182 */
183 if (stepcount < 0) {
184 /*
185 * check for opnd1/opnd2 > 1/2
186 *
187 * In this case n will round to 1, so
188 * r = opnd1 - opnd2
189 */
190 if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) {
191 Sgl_all(result) = ~Sgl_all(result); /* set sign */
192 /* align opnd2 with opnd1 */
193 Sgl_leftshiftby1(opnd2);
194 Sgl_subtract(opnd2,opnd1,opnd2);
195 /* now normalize */
196 while (Sgl_iszero_hidden(opnd2)) {
197 Sgl_leftshiftby1(opnd2);
198 dest_exponent--;
199 }
200 Sgl_set_exponentmantissa(result,opnd2);
201 goto testforunderflow;
202 }
203 /*
204 * opnd1/opnd2 <= 1/2
205 *
206 * In this case n will round to zero, so
207 * r = opnd1
208 */
209 Sgl_set_exponentmantissa(result,opnd1);
210 dest_exponent = opnd1_exponent;
211 goto testforunderflow;
212 }
213
214 /*
215 * Generate result
216 *
217 * Do iterative subtract until remainder is less than operand 2.
218 */
219 while (stepcount-- > 0 && Sgl_all(opnd1)) {
220 if (Sgl_isnotlessthan(opnd1,opnd2))
221 Sgl_subtract(opnd1,opnd2,opnd1);
222 Sgl_leftshiftby1(opnd1);
223 }
224 /*
225 * Do last subtract, then determine which way to round if remainder
226 * is exactly 1/2 of opnd2
227 */
228 if (Sgl_isnotlessthan(opnd1,opnd2)) {
229 Sgl_subtract(opnd1,opnd2,opnd1);
230 roundup = TRUE;
231 }
232 if (stepcount > 0 || Sgl_iszero(opnd1)) {
233 /* division is exact, remainder is zero */
234 Sgl_setzero_exponentmantissa(result);
235 *dstptr = result;
236 return(NOEXCEPTION);
237 }
238
239 /*
240 * Check for cases where opnd1/opnd2 < n
241 *
242 * In this case the result's sign will be opposite that of
243 * opnd1. The mantissa also needs some correction.
244 */
245 Sgl_leftshiftby1(opnd1);
246 if (Sgl_isgreaterthan(opnd1,opnd2)) {
247 Sgl_invert_sign(result);
248 Sgl_subtract((opnd2<<1),opnd1,opnd1);
249 }
250 /* check for remainder being exactly 1/2 of opnd2 */
251 else if (Sgl_isequal(opnd1,opnd2) && roundup) {
252 Sgl_invert_sign(result);
253 }
254
255 /* normalize result's mantissa */
256 while (Sgl_iszero_hidden(opnd1)) {
257 dest_exponent--;
258 Sgl_leftshiftby1(opnd1);
259 }
260 Sgl_set_exponentmantissa(result,opnd1);
261
262 /*
263 * Test for underflow
264 */
265 testforunderflow:
266 if (dest_exponent <= 0) {
267 /* trap if UNDERFLOWTRAP enabled */
268 if (Is_underflowtrap_enabled()) {
269 /*
270 * Adjust bias of result
271 */
272 Sgl_setwrapped_exponent(result,dest_exponent,unfl);
273 *dstptr = result;
274 /* frem is always exact */
275 return(UNDERFLOWEXCEPTION);
276 }
277 /*
278 * denormalize result or set to signed zero
279 */
280 if (dest_exponent >= (1 - SGL_P)) {
281 Sgl_rightshift_exponentmantissa(result,1-dest_exponent);
282 }
283 else {
284 Sgl_setzero_exponentmantissa(result);
285 }
286 }
287 else Sgl_set_exponent(result,dest_exponent);
288 *dstptr = result;
289 return(NOEXCEPTION);
290}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/sfsqrt.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single Floating-point Square Root
29 *
30 * External Interfaces:
31 * sgl_fsqrt(srcptr,nullptr,dstptr,status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "sgl_float.h"
44
45/*
46 * Single Floating-point Square Root
47 */
48
49/*ARGSUSED*/
50unsigned int
51sgl_fsqrt(
52 sgl_floating_point *srcptr,
53 unsigned int *nullptr,
54 sgl_floating_point *dstptr,
55 unsigned int *status)
56{
57 register unsigned int src, result;
58 register int src_exponent;
59 register unsigned int newbit, sum;
60 register boolean guardbit = FALSE, even_exponent;
61
62 src = *srcptr;
63 /*
64 * check source operand for NaN or infinity
65 */
66 if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
67 /*
68 * is signaling NaN?
69 */
70 if (Sgl_isone_signaling(src)) {
71 /* trap if INVALIDTRAP enabled */
72 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
73 /* make NaN quiet */
74 Set_invalidflag();
75 Sgl_set_quiet(src);
76 }
77 /*
78 * Return quiet NaN or positive infinity.
79 * Fall thru to negative test if negative infinity.
80 */
81 if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) {
82 *dstptr = src;
83 return(NOEXCEPTION);
84 }
85 }
86
87 /*
88 * check for zero source operand
89 */
90 if (Sgl_iszero_exponentmantissa(src)) {
91 *dstptr = src;
92 return(NOEXCEPTION);
93 }
94
95 /*
96 * check for negative source operand
97 */
98 if (Sgl_isone_sign(src)) {
99 /* trap if INVALIDTRAP enabled */
100 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
101 /* make NaN quiet */
102 Set_invalidflag();
103 Sgl_makequietnan(src);
104 *dstptr = src;
105 return(NOEXCEPTION);
106 }
107
108 /*
109 * Generate result
110 */
111 if (src_exponent > 0) {
112 even_exponent = Sgl_hidden(src);
113 Sgl_clear_signexponent_set_hidden(src);
114 }
115 else {
116 /* normalize operand */
117 Sgl_clear_signexponent(src);
118 src_exponent++;
119 Sgl_normalize(src,src_exponent);
120 even_exponent = src_exponent & 1;
121 }
122 if (even_exponent) {
123 /* exponent is even */
124 /* Add comment here. Explain why odd exponent needs correction */
125 Sgl_leftshiftby1(src);
126 }
127 /*
128 * Add comment here. Explain following algorithm.
129 *
130 * Trust me, it works.
131 *
132 */
133 Sgl_setzero(result);
134 newbit = 1 << SGL_P;
135 while (newbit && Sgl_isnotzero(src)) {
136 Sgl_addition(result,newbit,sum);
137 if(sum <= Sgl_all(src)) {
138 /* update result */
139 Sgl_addition(result,(newbit<<1),result);
140 Sgl_subtract(src,sum,src);
141 }
142 Sgl_rightshiftby1(newbit);
143 Sgl_leftshiftby1(src);
144 }
145 /* correct exponent for pre-shift */
146 if (even_exponent) {
147 Sgl_rightshiftby1(result);
148 }
149
150 /* check for inexact */
151 if (Sgl_isnotzero(src)) {
152 if (!even_exponent && Sgl_islessthan(result,src))
153 Sgl_increment(result);
154 guardbit = Sgl_lowmantissa(result);
155 Sgl_rightshiftby1(result);
156
157 /* now round result */
158 switch (Rounding_mode()) {
159 case ROUNDPLUS:
160 Sgl_increment(result);
161 break;
162 case ROUNDNEAREST:
163 /* stickybit is always true, so guardbit
164 * is enough to determine rounding */
165 if (guardbit) {
166 Sgl_increment(result);
167 }
168 break;
169 }
170 /* increment result exponent by 1 if mantissa overflowed */
171 if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2;
172
173 if (Is_inexacttrap_enabled()) {
174 Sgl_set_exponent(result,
175 ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
176 *dstptr = result;
177 return(INEXACTEXCEPTION);
178 }
179 else Set_inexactflag();
180 }
181 else {
182 Sgl_rightshiftby1(result);
183 }
184 Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
185 *dstptr = result;
186 return(NOEXCEPTION);
187}
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/sfsub.c $Revision: 1.1 $
26 *
27 * Purpose:
28 * Single_subtract: subtract two single precision values.
29 *
30 * External Interfaces:
31 * sgl_fsub(leftptr, rightptr, dstptr, status)
32 *
33 * Internal Interfaces:
34 *
35 * Theory:
36 * <<please update with a overview of the operation of this file>>
37 *
38 * END_DESC
39*/
40
41
42#include "float.h"
43#include "sgl_float.h"
44
45/*
46 * Single_subtract: subtract two single precision values.
47 */
48int
49sgl_fsub(
50 sgl_floating_point *leftptr,
51 sgl_floating_point *rightptr,
52 sgl_floating_point *dstptr,
53 unsigned int *status)
54 {
55 register unsigned int left, right, result, extent;
56 register unsigned int signless_upper_left, signless_upper_right, save;
57
58 register int result_exponent, right_exponent, diff_exponent;
59 register int sign_save, jumpsize;
60 register boolean inexact = FALSE, underflowtrap;
61
62 /* Create local copies of the numbers */
63 left = *leftptr;
64 right = *rightptr;
65
66 /* A zero "save" helps discover equal operands (for later), *
67 * and is used in swapping operands (if needed). */
68 Sgl_xortointp1(left,right,/*to*/save);
69
70 /*
71 * check first operand for NaN's or infinity
72 */
73 if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
74 {
75 if (Sgl_iszero_mantissa(left))
76 {
77 if (Sgl_isnotnan(right))
78 {
79 if (Sgl_isinfinity(right) && save==0)
80 {
81 /*
82 * invalid since operands are same signed infinity's
83 */
84 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
85 Set_invalidflag();
86 Sgl_makequietnan(result);
87 *dstptr = result;
88 return(NOEXCEPTION);
89 }
90 /*
91 * return infinity
92 */
93 *dstptr = left;
94 return(NOEXCEPTION);
95 }
96 }
97 else
98 {
99 /*
100 * is NaN; signaling or quiet?
101 */
102 if (Sgl_isone_signaling(left))
103 {
104 /* trap if INVALIDTRAP enabled */
105 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
106 /* make NaN quiet */
107 Set_invalidflag();
108 Sgl_set_quiet(left);
109 }
110 /*
111 * is second operand a signaling NaN?
112 */
113 else if (Sgl_is_signalingnan(right))
114 {
115 /* trap if INVALIDTRAP enabled */
116 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
117 /* make NaN quiet */
118 Set_invalidflag();
119 Sgl_set_quiet(right);
120 *dstptr = right;
121 return(NOEXCEPTION);
122 }
123 /*
124 * return quiet NaN
125 */
126 *dstptr = left;
127 return(NOEXCEPTION);
128 }
129 } /* End left NaN or Infinity processing */
130 /*
131 * check second operand for NaN's or infinity
132 */
133 if (Sgl_isinfinity_exponent(right))
134 {
135 if (Sgl_iszero_mantissa(right))
136 {
137 /* return infinity */
138 Sgl_invert_sign(right);
139 *dstptr = right;
140 return(NOEXCEPTION);
141 }
142 /*
143 * is NaN; signaling or quiet?
144 */
145 if (Sgl_isone_signaling(right))
146 {
147 /* trap if INVALIDTRAP enabled */
148 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
149 /* make NaN quiet */
150 Set_invalidflag();
151 Sgl_set_quiet(right);
152 }
153 /*
154 * return quiet NaN
155 */
156 *dstptr = right;
157 return(NOEXCEPTION);
158 } /* End right NaN or Infinity processing */
159
160 /* Invariant: Must be dealing with finite numbers */
161
162 /* Compare operands by removing the sign */
163 Sgl_copytoint_exponentmantissa(left,signless_upper_left);
164 Sgl_copytoint_exponentmantissa(right,signless_upper_right);
165
166 /* sign difference selects sub or add operation. */
167 if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
168 {
169 /* Set the left operand to the larger one by XOR swap *
170 * First finish the first word using "save" */
171 Sgl_xorfromintp1(save,right,/*to*/right);
172 Sgl_xorfromintp1(save,left,/*to*/left);
173 result_exponent = Sgl_exponent(left);
174 Sgl_invert_sign(left);
175 }
176 /* Invariant: left is not smaller than right. */
177
178 if((right_exponent = Sgl_exponent(right)) == 0)
179 {
180 /* Denormalized operands. First look for zeroes */
181 if(Sgl_iszero_mantissa(right))
182 {
183 /* right is zero */
184 if(Sgl_iszero_exponentmantissa(left))
185 {
186 /* Both operands are zeros */
187 Sgl_invert_sign(right);
188 if(Is_rounding_mode(ROUNDMINUS))
189 {
190 Sgl_or_signs(left,/*with*/right);
191 }
192 else
193 {
194 Sgl_and_signs(left,/*with*/right);
195 }
196 }
197 else
198 {
199 /* Left is not a zero and must be the result. Trapped
200 * underflows are signaled if left is denormalized. Result
201 * is always exact. */
202 if( (result_exponent == 0) && Is_underflowtrap_enabled() )
203 {
204 /* need to normalize results mantissa */
205 sign_save = Sgl_signextendedsign(left);
206 Sgl_leftshiftby1(left);
207 Sgl_normalize(left,result_exponent);
208 Sgl_set_sign(left,/*using*/sign_save);
209 Sgl_setwrapped_exponent(left,result_exponent,unfl);
210 *dstptr = left;
211 /* inexact = FALSE */
212 return(UNDERFLOWEXCEPTION);
213 }
214 }
215 *dstptr = left;
216 return(NOEXCEPTION);
217 }
218
219 /* Neither are zeroes */
220 Sgl_clear_sign(right); /* Exponent is already cleared */
221 if(result_exponent == 0 )
222 {
223 /* Both operands are denormalized. The result must be exact
224 * and is simply calculated. A sum could become normalized and a
225 * difference could cancel to a true zero. */
226 if( (/*signed*/int) save >= 0 )
227 {
228 Sgl_subtract(left,/*minus*/right,/*into*/result);
229 if(Sgl_iszero_mantissa(result))
230 {
231 if(Is_rounding_mode(ROUNDMINUS))
232 {
233 Sgl_setone_sign(result);
234 }
235 else
236 {
237 Sgl_setzero_sign(result);
238 }
239 *dstptr = result;
240 return(NOEXCEPTION);
241 }
242 }
243 else
244 {
245 Sgl_addition(left,right,/*into*/result);
246 if(Sgl_isone_hidden(result))
247 {
248 *dstptr = result;
249 return(NOEXCEPTION);
250 }
251 }
252 if(Is_underflowtrap_enabled())
253 {
254 /* need to normalize result */
255 sign_save = Sgl_signextendedsign(result);
256 Sgl_leftshiftby1(result);
257 Sgl_normalize(result,result_exponent);
258 Sgl_set_sign(result,/*using*/sign_save);
259 Sgl_setwrapped_exponent(result,result_exponent,unfl);
260 *dstptr = result;
261 /* inexact = FALSE */
262 return(UNDERFLOWEXCEPTION);
263 }
264 *dstptr = result;
265 return(NOEXCEPTION);
266 }
267 right_exponent = 1; /* Set exponent to reflect different bias
268 * with denomalized numbers. */
269 }
270 else
271 {
272 Sgl_clear_signexponent_set_hidden(right);
273 }
274 Sgl_clear_exponent_set_hidden(left);
275 diff_exponent = result_exponent - right_exponent;
276
277 /*
278 * Special case alignment of operands that would force alignment
279 * beyond the extent of the extension. A further optimization
280 * could special case this but only reduces the path length for this
281 * infrequent case.
282 */
283 if(diff_exponent > SGL_THRESHOLD)
284 {
285 diff_exponent = SGL_THRESHOLD;
286 }
287
288 /* Align right operand by shifting to right */
289 Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
290 /*and lower to*/extent);
291
292 /* Treat sum and difference of the operands separately. */
293 if( (/*signed*/int) save >= 0 )
294 {
295 /*
296 * Difference of the two operands. Their can be no overflow. A
297 * borrow can occur out of the hidden bit and force a post
298 * normalization phase.
299 */
300 Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
301 if(Sgl_iszero_hidden(result))
302 {
303 /* Handle normalization */
304 /* A straight foward algorithm would now shift the result
305 * and extension left until the hidden bit becomes one. Not
306 * all of the extension bits need participate in the shift.
307 * Only the two most significant bits (round and guard) are
308 * needed. If only a single shift is needed then the guard
309 * bit becomes a significant low order bit and the extension
310 * must participate in the rounding. If more than a single
311 * shift is needed, then all bits to the right of the guard
312 * bit are zeros, and the guard bit may or may not be zero. */
313 sign_save = Sgl_signextendedsign(result);
314 Sgl_leftshiftby1_withextent(result,extent,result);
315
316 /* Need to check for a zero result. The sign and exponent
317 * fields have already been zeroed. The more efficient test
318 * of the full object can be used.
319 */
320 if(Sgl_iszero(result))
321 /* Must have been "x-x" or "x+(-x)". */
322 {
323 if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
324 *dstptr = result;
325 return(NOEXCEPTION);
326 }
327 result_exponent--;
328 /* Look to see if normalization is finished. */
329 if(Sgl_isone_hidden(result))
330 {
331 if(result_exponent==0)
332 {
333 /* Denormalized, exponent should be zero. Left operand *
334 * was normalized, so extent (guard, round) was zero */
335 goto underflow;
336 }
337 else
338 {
339 /* No further normalization is needed. */
340 Sgl_set_sign(result,/*using*/sign_save);
341 Ext_leftshiftby1(extent);
342 goto round;
343 }
344 }
345
346 /* Check for denormalized, exponent should be zero. Left *
347 * operand was normalized, so extent (guard, round) was zero */
348 if(!(underflowtrap = Is_underflowtrap_enabled()) &&
349 result_exponent==0) goto underflow;
350
351 /* Shift extension to complete one bit of normalization and
352 * update exponent. */
353 Ext_leftshiftby1(extent);
354
355 /* Discover first one bit to determine shift amount. Use a
356 * modified binary search. We have already shifted the result
357 * one position right and still not found a one so the remainder
358 * of the extension must be zero and simplifies rounding. */
359 /* Scan bytes */
360 while(Sgl_iszero_hiddenhigh7mantissa(result))
361 {
362 Sgl_leftshiftby8(result);
363 if((result_exponent -= 8) <= 0 && !underflowtrap)
364 goto underflow;
365 }
366 /* Now narrow it down to the nibble */
367 if(Sgl_iszero_hiddenhigh3mantissa(result))
368 {
369 /* The lower nibble contains the normalizing one */
370 Sgl_leftshiftby4(result);
371 if((result_exponent -= 4) <= 0 && !underflowtrap)
372 goto underflow;
373 }
374 /* Select case were first bit is set (already normalized)
375 * otherwise select the proper shift. */
376 if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
377 {
378 /* Already normalized */
379 if(result_exponent <= 0) goto underflow;
380 Sgl_set_sign(result,/*using*/sign_save);
381 Sgl_set_exponent(result,/*using*/result_exponent);
382 *dstptr = result;
383 return(NOEXCEPTION);
384 }
385 Sgl_sethigh4bits(result,/*using*/sign_save);
386 switch(jumpsize)
387 {
388 case 1:
389 {
390 Sgl_leftshiftby3(result);
391 result_exponent -= 3;
392 break;
393 }
394 case 2:
395 case 3:
396 {
397 Sgl_leftshiftby2(result);
398 result_exponent -= 2;
399 break;
400 }
401 case 4:
402 case 5:
403 case 6:
404 case 7:
405 {
406 Sgl_leftshiftby1(result);
407 result_exponent -= 1;
408 break;
409 }
410 }
411 if(result_exponent > 0)
412 {
413 Sgl_set_exponent(result,/*using*/result_exponent);
414 *dstptr = result; /* Sign bit is already set */
415 return(NOEXCEPTION);
416 }
417 /* Fixup potential underflows */
418 underflow:
419 if(Is_underflowtrap_enabled())
420 {
421 Sgl_set_sign(result,sign_save);
422 Sgl_setwrapped_exponent(result,result_exponent,unfl);
423 *dstptr = result;
424 /* inexact = FALSE */
425 return(UNDERFLOWEXCEPTION);
426 }
427 /*
428 * Since we cannot get an inexact denormalized result,
429 * we can now return.
430 */
431 Sgl_right_align(result,/*by*/(1-result_exponent),extent);
432 Sgl_clear_signexponent(result);
433 Sgl_set_sign(result,sign_save);
434 *dstptr = result;
435 return(NOEXCEPTION);
436 } /* end if(hidden...)... */
437 /* Fall through and round */
438 } /* end if(save >= 0)... */
439 else
440 {
441 /* Add magnitudes */
442 Sgl_addition(left,right,/*to*/result);
443 if(Sgl_isone_hiddenoverflow(result))
444 {
445 /* Prenormalization required. */
446 Sgl_rightshiftby1_withextent(result,extent,extent);
447 Sgl_arithrightshiftby1(result);
448 result_exponent++;
449 } /* end if hiddenoverflow... */
450 } /* end else ...sub magnitudes... */
451
452 /* Round the result. If the extension is all zeros,then the result is
453 * exact. Otherwise round in the correct direction. No underflow is
454 * possible. If a postnormalization is necessary, then the mantissa is
455 * all zeros so no shift is needed. */
456 round:
457 if(Ext_isnotzero(extent))
458 {
459 inexact = TRUE;
460 switch(Rounding_mode())
461 {
462 case ROUNDNEAREST: /* The default. */
463 if(Ext_isone_sign(extent))
464 {
465 /* at least 1/2 ulp */
466 if(Ext_isnotzero_lower(extent) ||
467 Sgl_isone_lowmantissa(result))
468 {
469 /* either exactly half way and odd or more than 1/2ulp */
470 Sgl_increment(result);
471 }
472 }
473 break;
474
475 case ROUNDPLUS:
476 if(Sgl_iszero_sign(result))
477 {
478 /* Round up positive results */
479 Sgl_increment(result);
480 }
481 break;
482
483 case ROUNDMINUS:
484 if(Sgl_isone_sign(result))
485 {
486 /* Round down negative results */
487 Sgl_increment(result);
488 }
489
490 case ROUNDZERO:;
491 /* truncate is simple */
492 } /* end switch... */
493 if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
494 }
495 if(result_exponent == SGL_INFINITY_EXPONENT)
496 {
497 /* Overflow */
498 if(Is_overflowtrap_enabled())
499 {
500 Sgl_setwrapped_exponent(result,result_exponent,ovfl);
501 *dstptr = result;
502 if (inexact)
503 if (Is_inexacttrap_enabled())
504 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
505 else Set_inexactflag();
506 return(OVERFLOWEXCEPTION);
507 }
508 else
509 {
510 Set_overflowflag();
511 inexact = TRUE;
512 Sgl_setoverflow(result);
513 }
514 }
515 else Sgl_set_exponent(result,result_exponent);
516 *dstptr = result;
517 if(inexact)
518 if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
519 else Set_inexactflag();
520 return(NOEXCEPTION);
521 }
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 @@
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifdef __NO_PA_HDRS
23 PA header file -- do not include this header file for non-PA builds.
24#endif
25
26/* 32-bit word grabing functions */
27#define Sgl_firstword(value) Sall(value)
28#define Sgl_secondword(value) dummy_location
29#define Sgl_thirdword(value) dummy_location
30#define Sgl_fourthword(value) dummy_location
31
32#define Sgl_sign(object) Ssign(object)
33#define Sgl_exponent(object) Sexponent(object)
34#define Sgl_signexponent(object) Ssignexponent(object)
35#define Sgl_mantissa(object) Smantissa(object)
36#define Sgl_exponentmantissa(object) Sexponentmantissa(object)
37#define Sgl_all(object) Sall(object)
38
39/* sgl_and_signs ands the sign bits of each argument and puts the result
40 * into the first argument. sgl_or_signs ors those same sign bits */
41#define Sgl_and_signs( src1dst, src2) \
42 Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst)
43#define Sgl_or_signs( src1dst, src2) \
44 Sall(src1dst) = (Sall(src2)&((unsigned int)1<<31)) | Sall(src1dst)
45
46/* The hidden bit is always the low bit of the exponent */
47#define Sgl_clear_exponent_set_hidden(srcdst) Deposit_sexponent(srcdst,1)
48#define Sgl_clear_signexponent_set_hidden(srcdst) \
49 Deposit_ssignexponent(srcdst,1)
50#define Sgl_clear_sign(srcdst) Sall(srcdst) &= ~((unsigned int)1<<31)
51#define Sgl_clear_signexponent(srcdst) Sall(srcdst) &= 0x007fffff
52
53/* varamount must be less than 32 for the next three functions */
54#define Sgl_rightshift(srcdst, varamount) \
55 Sall(srcdst) >>= varamount
56#define Sgl_leftshift(srcdst, varamount) \
57 Sall(srcdst) <<= varamount
58#define Sgl_rightshift_exponentmantissa(srcdst, varamount) \
59 Sall(srcdst) = \
60 (Sexponentmantissa(srcdst) >> varamount) | \
61 (Sall(srcdst) & ((unsigned int)1<<31))
62
63#define Sgl_leftshiftby1_withextent(left,right,result) \
64 Shiftdouble(Sall(left),Extall(right),31,Sall(result))
65
66#define Sgl_rightshiftby1_withextent(left,right,dst) \
67 Shiftdouble(Sall(left),Extall(right),1,Extall(right))
68#define Sgl_arithrightshiftby1(srcdst) \
69 Sall(srcdst) = (int)Sall(srcdst) >> 1
70
71/* Sign extend the sign bit with an integer destination */
72#define Sgl_signextendedsign(value) Ssignedsign(value)
73
74#define Sgl_isone_hidden(sgl_value) (Shidden(sgl_value))
75#define Sgl_increment(sgl_value) Sall(sgl_value) += 1
76#define Sgl_increment_mantissa(sgl_value) \
77 Deposit_smantissa(sgl_value,sgl_value+1)
78#define Sgl_decrement(sgl_value) Sall(sgl_value) -= 1
79
80#define Sgl_isone_sign(sgl_value) (Is_ssign(sgl_value)!=0)
81#define Sgl_isone_hiddenoverflow(sgl_value) \
82 (Is_shiddenoverflow(sgl_value)!=0)
83#define Sgl_isone_lowmantissa(sgl_value) (Is_slow(sgl_value)!=0)
84#define Sgl_isone_signaling(sgl_value) (Is_ssignaling(sgl_value)!=0)
85#define Sgl_is_signalingnan(sgl_value) (Ssignalingnan(sgl_value)==0x1ff)
86#define Sgl_isnotzero(sgl_value) (Sall(sgl_value)!=0)
87#define Sgl_isnotzero_hiddenhigh7mantissa(sgl_value) \
88 (Shiddenhigh7mantissa(sgl_value)!=0)
89#define Sgl_isnotzero_low4(sgl_value) (Slow4(sgl_value)!=0)
90#define Sgl_isnotzero_exponent(sgl_value) (Sexponent(sgl_value)!=0)
91#define Sgl_isnotzero_mantissa(sgl_value) (Smantissa(sgl_value)!=0)
92#define Sgl_isnotzero_exponentmantissa(sgl_value) \
93 (Sexponentmantissa(sgl_value)!=0)
94#define Sgl_iszero(sgl_value) (Sall(sgl_value)==0)
95#define Sgl_iszero_signaling(sgl_value) (Is_ssignaling(sgl_value)==0)
96#define Sgl_iszero_hidden(sgl_value) (Is_shidden(sgl_value)==0)
97#define Sgl_iszero_hiddenoverflow(sgl_value) \
98 (Is_shiddenoverflow(sgl_value)==0)
99#define Sgl_iszero_hiddenhigh3mantissa(sgl_value) \
100 (Shiddenhigh3mantissa(sgl_value)==0)
101#define Sgl_iszero_hiddenhigh7mantissa(sgl_value) \
102 (Shiddenhigh7mantissa(sgl_value)==0)
103#define Sgl_iszero_sign(sgl_value) (Is_ssign(sgl_value)==0)
104#define Sgl_iszero_exponent(sgl_value) (Sexponent(sgl_value)==0)
105#define Sgl_iszero_mantissa(sgl_value) (Smantissa(sgl_value)==0)
106#define Sgl_iszero_exponentmantissa(sgl_value) \
107 (Sexponentmantissa(sgl_value)==0)
108#define Sgl_isinfinity_exponent(sgl_value) \
109 (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT)
110#define Sgl_isnotinfinity_exponent(sgl_value) \
111 (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT)
112#define Sgl_isinfinity(sgl_value) \
113 (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \
114 Sgl_mantissa(sgl_value)==0)
115#define Sgl_isnan(sgl_value) \
116 (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \
117 Sgl_mantissa(sgl_value)!=0)
118#define Sgl_isnotnan(sgl_value) \
119 (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT || \
120 Sgl_mantissa(sgl_value)==0)
121#define Sgl_islessthan(sgl_op1,sgl_op2) \
122 (Sall(sgl_op1) < Sall(sgl_op2))
123#define Sgl_isgreaterthan(sgl_op1,sgl_op2) \
124 (Sall(sgl_op1) > Sall(sgl_op2))
125#define Sgl_isnotlessthan(sgl_op1,sgl_op2) \
126 (Sall(sgl_op1) >= Sall(sgl_op2))
127#define Sgl_isequal(sgl_op1,sgl_op2) \
128 (Sall(sgl_op1) == Sall(sgl_op2))
129
130#define Sgl_leftshiftby8(sgl_value) \
131 Sall(sgl_value) <<= 8
132#define Sgl_leftshiftby4(sgl_value) \
133 Sall(sgl_value) <<= 4
134#define Sgl_leftshiftby3(sgl_value) \
135 Sall(sgl_value) <<= 3
136#define Sgl_leftshiftby2(sgl_value) \
137 Sall(sgl_value) <<= 2
138#define Sgl_leftshiftby1(sgl_value) \
139 Sall(sgl_value) <<= 1
140#define Sgl_rightshiftby1(sgl_value) \
141 Sall(sgl_value) >>= 1
142#define Sgl_rightshiftby4(sgl_value) \
143 Sall(sgl_value) >>= 4
144#define Sgl_rightshiftby8(sgl_value) \
145 Sall(sgl_value) >>= 8
146
147#define Sgl_ismagnitudeless(signlessleft,signlessright) \
148/* unsigned int signlessleft, signlessright; */ \
149 (signlessleft < signlessright)
150
151
152#define Sgl_copytoint_exponentmantissa(source,dest) \
153 dest = Sexponentmantissa(source)
154
155/* A quiet NaN has the high mantissa bit clear and at least on other (in this
156 * case the adjacent bit) bit set. */
157#define Sgl_set_quiet(sgl_value) Deposit_shigh2mantissa(sgl_value,1)
158#define Sgl_set_exponent(sgl_value,exp) Deposit_sexponent(sgl_value,exp)
159
160#define Sgl_set_mantissa(dest,value) Deposit_smantissa(dest,value)
161#define Sgl_set_exponentmantissa(dest,value) \
162 Deposit_sexponentmantissa(dest,value)
163
164/* An infinity is represented with the max exponent and a zero mantissa */
165#define Sgl_setinfinity_exponent(sgl_value) \
166 Deposit_sexponent(sgl_value,SGL_INFINITY_EXPONENT)
167#define Sgl_setinfinity_exponentmantissa(sgl_value) \
168 Deposit_sexponentmantissa(sgl_value, \
169 (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))))
170#define Sgl_setinfinitypositive(sgl_value) \
171 Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH)))
172#define Sgl_setinfinitynegative(sgl_value) \
173 Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) \
174 | ((unsigned int)1<<31)
175#define Sgl_setinfinity(sgl_value,sign) \
176 Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | \
177 ((unsigned int)sign << 31)
178#define Sgl_sethigh4bits(sgl_value, extsign) \
179 Deposit_shigh4(sgl_value,extsign)
180#define Sgl_set_sign(sgl_value,sign) Deposit_ssign(sgl_value,sign)
181#define Sgl_invert_sign(sgl_value) \
182 Deposit_ssign(sgl_value,~Ssign(sgl_value))
183#define Sgl_setone_sign(sgl_value) Deposit_ssign(sgl_value,1)
184#define Sgl_setone_lowmantissa(sgl_value) Deposit_slow(sgl_value,1)
185#define Sgl_setzero_sign(sgl_value) Sall(sgl_value) &= 0x7fffffff
186#define Sgl_setzero_exponent(sgl_value) Sall(sgl_value) &= 0x807fffff
187#define Sgl_setzero_mantissa(sgl_value) Sall(sgl_value) &= 0xff800000
188#define Sgl_setzero_exponentmantissa(sgl_value) Sall(sgl_value) &= 0x80000000
189#define Sgl_setzero(sgl_value) Sall(sgl_value) = 0
190#define Sgl_setnegativezero(sgl_value) Sall(sgl_value) = (unsigned int)1 << 31
191
192/* Use following macro for both overflow & underflow conditions */
193#define ovfl -
194#define unfl +
195#define Sgl_setwrapped_exponent(sgl_value,exponent,op) \
196 Deposit_sexponent(sgl_value,(exponent op SGL_WRAP))
197
198#define Sgl_setlargestpositive(sgl_value) \
199 Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
200 | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 )
201#define Sgl_setlargestnegative(sgl_value) \
202 Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
203 | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) \
204 | ((unsigned int)1<<31)
205
206#define Sgl_setnegativeinfinity(sgl_value) \
207 Sall(sgl_value) = \
208 ((1<<SGL_EXP_LENGTH) | SGL_INFINITY_EXPONENT) << (32-(1+SGL_EXP_LENGTH))
209#define Sgl_setlargest(sgl_value,sign) \
210 Sall(sgl_value) = (unsigned int)sign << 31 | \
211 (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
212 | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 ))
213#define Sgl_setlargest_exponentmantissa(sgl_value) \
214 Sall(sgl_value) = Sall(sgl_value) & ((unsigned int)1<<31) | \
215 (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
216 | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 ))
217
218/* The high bit is always zero so arithmetic or logical shifts will work. */
219#define Sgl_right_align(srcdst,shift,extent) \
220 /* sgl_floating_point srcdst; int shift; extension extent */ \
221 if (shift < 32) { \
222 Extall(extent) = Sall(srcdst) << (32-(shift)); \
223 Sall(srcdst) >>= shift; \
224 } \
225 else { \
226 Extall(extent) = Sall(srcdst); \
227 Sall(srcdst) = 0; \
228 }
229#define Sgl_hiddenhigh3mantissa(sgl_value) Shiddenhigh3mantissa(sgl_value)
230#define Sgl_hidden(sgl_value) Shidden(sgl_value)
231#define Sgl_lowmantissa(sgl_value) Slow(sgl_value)
232
233/* The left argument is never smaller than the right argument */
234#define Sgl_subtract(sgl_left,sgl_right,sgl_result) \
235 Sall(sgl_result) = Sall(sgl_left) - Sall(sgl_right)
236
237/* Subtract right augmented with extension from left augmented with zeros and
238 * store into result and extension. */
239#define Sgl_subtract_withextension(left,right,extent,result) \
240 /* sgl_floating_point left,right,result; extension extent */ \
241 Sgl_subtract(left,right,result); \
242 if((Extall(extent) = 0-Extall(extent))) \
243 Sall(result) = Sall(result)-1
244
245#define Sgl_addition(sgl_left,sgl_right,sgl_result) \
246 Sall(sgl_result) = Sall(sgl_left) + Sall(sgl_right)
247
248#define Sgl_xortointp1(left,right,result) \
249 result = Sall(left) XOR Sall(right);
250
251#define Sgl_xorfromintp1(left,right,result) \
252 Sall(result) = left XOR Sall(right)
253
254/* Need to Initialize */
255#define Sgl_makequietnan(dest) \
256 Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \
257 | (1<<(32-(1+SGL_EXP_LENGTH+2)))
258#define Sgl_makesignalingnan(dest) \
259 Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \
260 | (1<<(32-(1+SGL_EXP_LENGTH+1)))
261
262#define Sgl_normalize(sgl_opnd,exponent) \
263 while(Sgl_iszero_hiddenhigh7mantissa(sgl_opnd)) { \
264 Sgl_leftshiftby8(sgl_opnd); \
265 exponent -= 8; \
266 } \
267 if(Sgl_iszero_hiddenhigh3mantissa(sgl_opnd)) { \
268 Sgl_leftshiftby4(sgl_opnd); \
269 exponent -= 4; \
270 } \
271 while(Sgl_iszero_hidden(sgl_opnd)) { \
272 Sgl_leftshiftby1(sgl_opnd); \
273 exponent -= 1; \
274 }
275
276#define Sgl_setoverflow(sgl_opnd) \
277 /* set result to infinity or largest number */ \
278 switch (Rounding_mode()) { \
279 case ROUNDPLUS: \
280 if (Sgl_isone_sign(sgl_opnd)) { \
281 Sgl_setlargestnegative(sgl_opnd); \
282 } \
283 else { \
284 Sgl_setinfinitypositive(sgl_opnd); \
285 } \
286 break; \
287 case ROUNDMINUS: \
288 if (Sgl_iszero_sign(sgl_opnd)) { \
289 Sgl_setlargestpositive(sgl_opnd); \
290 } \
291 else { \
292 Sgl_setinfinitynegative(sgl_opnd); \
293 } \
294 break; \
295 case ROUNDNEAREST: \
296 Sgl_setinfinity_exponentmantissa(sgl_opnd); \
297 break; \
298 case ROUNDZERO: \
299 Sgl_setlargest_exponentmantissa(sgl_opnd); \
300 }
301
302#define Sgl_denormalize(opnd,exponent,guard,sticky,inexact) \
303 Sgl_clear_signexponent_set_hidden(opnd); \
304 if (exponent >= (1 - SGL_P)) { \
305 guard = (Sall(opnd) >> -exponent) & 1; \
306 if (exponent < 0) sticky |= Sall(opnd) << (32+exponent); \
307 inexact = guard | sticky; \
308 Sall(opnd) >>= (1-exponent); \
309 } \
310 else { \
311 guard = 0; \
312 sticky |= Sall(opnd); \
313 inexact = sticky; \
314 Sgl_setzero(opnd); \
315 }
316
317/*
318 * The fused multiply add instructions requires a single extended format,
319 * with 48 bits of mantissa.
320 */
321#define SGLEXT_THRESHOLD 48
322
323#define Sglext_setzero(valA,valB) \
324 Sextallp1(valA) = 0; Sextallp2(valB) = 0
325
326#define Sglext_isnotzero_mantissap2(valB) (Sextallp2(valB)!=0)
327#define Sglext_isone_lowp1(val) (Sextlowp1(val)!=0)
328#define Sglext_isone_highp2(val) (Sexthighp2(val)!=0)
329#define Sglext_isnotzero_low31p2(val) (Sextlow31p2(val)!=0)
330#define Sglext_iszero(valA,valB) (Sextallp1(valA)==0 && Sextallp2(valB)==0)
331
332#define Sgl_copytoptr(src,destptr) *destptr = src
333#define Sgl_copyfromptr(srcptr,dest) dest = *srcptr
334#define Sglext_copy(srca,srcb,desta,destb) \
335 Sextallp1(desta) = Sextallp1(srca); \
336 Sextallp2(destb) = Sextallp2(srcb)
337#define Sgl_copyto_sglext(src1,dest1,dest2) \
338 Sextallp1(dest1) = Sall(src1); Sextallp2(dest2) = 0
339
340#define Sglext_swap_lower(leftp2,rightp2) \
341 Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \
342 Sextallp2(rightp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \
343 Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2)
344
345#define Sglext_setone_lowmantissap2(value) Deposit_dlowp2(value,1)
346
347/* The high bit is always zero so arithmetic or logical shifts will work. */
348#define Sglext_right_align(srcdstA,srcdstB,shift) \
349 {int shiftamt, sticky; \
350 shiftamt = shift % 32; \
351 sticky = 0; \
352 switch (shift/32) { \
353 case 0: if (shiftamt > 0) { \
354 sticky = Sextallp2(srcdstB) << 32 - (shiftamt); \
355 Variable_shift_double(Sextallp1(srcdstA), \
356 Sextallp2(srcdstB),shiftamt,Sextallp2(srcdstB)); \
357 Sextallp1(srcdstA) >>= shiftamt; \
358 } \
359 break; \
360 case 1: if (shiftamt > 0) { \
361 sticky = (Sextallp1(srcdstA) << 32 - (shiftamt)) | \
362 Sextallp2(srcdstB); \
363 } \
364 else { \
365 sticky = Sextallp2(srcdstB); \
366 } \
367 Sextallp2(srcdstB) = Sextallp1(srcdstA) >> shiftamt; \
368 Sextallp1(srcdstA) = 0; \
369 break; \
370 } \
371 if (sticky) Sglext_setone_lowmantissap2(srcdstB); \
372 }
373
374/* The left argument is never smaller than the right argument */
375#define Sglext_subtract(lefta,leftb,righta,rightb,resulta,resultb) \
376 if( Sextallp2(rightb) > Sextallp2(leftb) ) Sextallp1(lefta)--; \
377 Sextallp2(resultb) = Sextallp2(leftb) - Sextallp2(rightb); \
378 Sextallp1(resulta) = Sextallp1(lefta) - Sextallp1(righta)
379
380#define Sglext_addition(lefta,leftb,righta,rightb,resulta,resultb) \
381 /* If the sum of the low words is less than either source, then \
382 * an overflow into the next word occurred. */ \
383 if ((Sextallp2(resultb) = Sextallp2(leftb)+Sextallp2(rightb)) < \
384 Sextallp2(rightb)) \
385 Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)+1; \
386 else Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)
387
388
389#define Sglext_arithrightshiftby1(srcdstA,srcdstB) \
390 Shiftdouble(Sextallp1(srcdstA),Sextallp2(srcdstB),1,Sextallp2(srcdstB)); \
391 Sextallp1(srcdstA) = (int)Sextallp1(srcdstA) >> 1
392
393#define Sglext_leftshiftby8(valA,valB) \
394 Shiftdouble(Sextallp1(valA),Sextallp2(valB),24,Sextallp1(valA)); \
395 Sextallp2(valB) <<= 8
396#define Sglext_leftshiftby4(valA,valB) \
397 Shiftdouble(Sextallp1(valA),Sextallp2(valB),28,Sextallp1(valA)); \
398 Sextallp2(valB) <<= 4
399#define Sglext_leftshiftby3(valA,valB) \
400 Shiftdouble(Sextallp1(valA),Sextallp2(valB),29,Sextallp1(valA)); \
401 Sextallp2(valB) <<= 3
402#define Sglext_leftshiftby2(valA,valB) \
403 Shiftdouble(Sextallp1(valA),Sextallp2(valB),30,Sextallp1(valA)); \
404 Sextallp2(valB) <<= 2
405#define Sglext_leftshiftby1(valA,valB) \
406 Shiftdouble(Sextallp1(valA),Sextallp2(valB),31,Sextallp1(valA)); \
407 Sextallp2(valB) <<= 1
408
409#define Sglext_rightshiftby4(valueA,valueB) \
410 Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),4,Sextallp2(valueB)); \
411 Sextallp1(valueA) >>= 4
412#define Sglext_rightshiftby3(valueA,valueB) \
413 Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),3,Sextallp2(valueB)); \
414 Sextallp1(valueA) >>= 3
415#define Sglext_rightshiftby1(valueA,valueB) \
416 Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),1,Sextallp2(valueB)); \
417 Sextallp1(valueA) >>= 1
418
419#define Sglext_xortointp1(left,right,result) Sgl_xortointp1(left,right,result)
420#define Sglext_xorfromintp1(left,right,result) \
421 Sgl_xorfromintp1(left,right,result)
422#define Sglext_copytoint_exponentmantissa(src,dest) \
423 Sgl_copytoint_exponentmantissa(src,dest)
424#define Sglext_ismagnitudeless(signlessleft,signlessright) \
425 Sgl_ismagnitudeless(signlessleft,signlessright)
426
427#define Sglext_set_sign(dbl_value,sign) Sgl_set_sign(dbl_value,sign)
428#define Sglext_clear_signexponent_set_hidden(srcdst) \
429 Sgl_clear_signexponent_set_hidden(srcdst)
430#define Sglext_clear_signexponent(srcdst) Sgl_clear_signexponent(srcdst)
431#define Sglext_clear_sign(srcdst) Sgl_clear_sign(srcdst)
432#define Sglext_isone_hidden(dbl_value) Sgl_isone_hidden(dbl_value)
433
434#define Sglext_denormalize(opndp1,opndp2,exponent,is_tiny) \
435 {int sticky; \
436 is_tiny = TRUE; \
437 if (exponent == 0 && Sextallp2(opndp2)) { \
438 switch (Rounding_mode()) { \
439 case ROUNDPLUS: \
440 if (Sgl_iszero_sign(opndp1)) \
441 if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
442 is_tiny = FALSE; \
443 break; \
444 case ROUNDMINUS: \
445 if (Sgl_isone_sign(opndp1)) { \
446 if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
447 is_tiny = FALSE; \
448 } \
449 break; \
450 case ROUNDNEAREST: \
451 if (Sglext_isone_highp2(opndp2) && \
452 (Sglext_isone_lowp1(opndp1) || \
453 Sglext_isnotzero_low31p2(opndp2))) \
454 if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
455 is_tiny = FALSE; \
456 break; \
457 } \
458 } \
459 Sglext_clear_signexponent_set_hidden(opndp1); \
460 if (exponent >= (1-DBL_P)) { \
461 if (exponent >= -31) { \
462 if (exponent > -31) { \
463 sticky = Sextallp2(opndp2) << 31+exponent; \
464 Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \
465 Sextallp1(opndp1) >>= 1-exponent; \
466 } \
467 else { \
468 sticky = Sextallp2(opndp2); \
469 Sextallp2(opndp2) = Sextallp1(opndp1); \
470 Sextallp1(opndp1) = 0; \
471 } \
472 } \
473 else { \
474 sticky = (Sextallp1(opndp1) << 31+exponent) | \
475 Sextallp2(opndp2); \
476 Sextallp2(opndp2) = Sextallp1(opndp1) >> -31-exponent; \
477 Sextallp1(opndp1) = 0; \
478 } \
479 } \
480 else { \
481 sticky = Sextallp1(opndp1) | Sextallp2(opndp2); \
482 Sglext_setzero(opndp1,opndp2); \
483 } \
484 if (sticky) Sglext_setone_lowmantissap2(opndp2); \
485 exponent = 0; \
486 }
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 @@
1#
2# Makefile for arch/parisc/mm
3#
4
5obj-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 @@
1/* $Id: fault.c,v 1.5 2000/01/26 16:20:29 jsm Exp $
2 *
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 *
8 * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
9 * Copyright 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
10 * Copyright 1999 Hewlett Packard Co.
11 *
12 */
13
14#include <linux/mm.h>
15#include <linux/ptrace.h>
16#include <linux/sched.h>
17#include <linux/interrupt.h>
18#include <linux/module.h>
19
20#include <asm/uaccess.h>
21#include <asm/traps.h>
22
23#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
24 /* dumped to the console via printk) */
25
26
27/* Defines for parisc_acctyp() */
28#define READ 0
29#define WRITE 1
30
31/* Various important other fields */
32#define bit22set(x) (x & 0x00000200)
33#define bits23_25set(x) (x & 0x000001c0)
34#define isGraphicsFlushRead(x) ((x & 0xfc003fdf) == 0x04001a80)
35 /* extended opcode is 0x6a */
36
37#define BITSSET 0x1c0 /* for identifying LDCW */
38
39
40DEFINE_PER_CPU(struct exception_data, exception_data);
41
42/*
43 * parisc_acctyp(unsigned int inst) --
44 * Given a PA-RISC memory access instruction, determine if the
45 * the instruction would perform a memory read or memory write
46 * operation.
47 *
48 * This function assumes that the given instruction is a memory access
49 * instruction (i.e. you should really only call it if you know that
50 * the instruction has generated some sort of a memory access fault).
51 *
52 * Returns:
53 * VM_READ if read operation
54 * VM_WRITE if write operation
55 * VM_EXEC if execute operation
56 */
57static unsigned long
58parisc_acctyp(unsigned long code, unsigned int inst)
59{
60 if (code == 6 || code == 16)
61 return VM_EXEC;
62
63 switch (inst & 0xf0000000) {
64 case 0x40000000: /* load */
65 case 0x50000000: /* new load */
66 return VM_READ;
67
68 case 0x60000000: /* store */
69 case 0x70000000: /* new store */
70 return VM_WRITE;
71
72 case 0x20000000: /* coproc */
73 case 0x30000000: /* coproc2 */
74 if (bit22set(inst))
75 return VM_WRITE;
76
77 case 0x0: /* indexed/memory management */
78 if (bit22set(inst)) {
79 /*
80 * Check for the 'Graphics Flush Read' instruction.
81 * It resembles an FDC instruction, except for bits
82 * 20 and 21. Any combination other than zero will
83 * utilize the block mover functionality on some
84 * older PA-RISC platforms. The case where a block
85 * move is performed from VM to graphics IO space
86 * should be treated as a READ.
87 *
88 * The significance of bits 20,21 in the FDC
89 * instruction is:
90 *
91 * 00 Flush data cache (normal instruction behavior)
92 * 01 Graphics flush write (IO space -> VM)
93 * 10 Graphics flush read (VM -> IO space)
94 * 11 Graphics flush read/write (VM <-> IO space)
95 */
96 if (isGraphicsFlushRead(inst))
97 return VM_READ;
98 return VM_WRITE;
99 } else {
100 /*
101 * Check for LDCWX and LDCWS (semaphore instructions).
102 * If bits 23 through 25 are all 1's it is one of
103 * the above two instructions and is a write.
104 *
105 * Note: With the limited bits we are looking at,
106 * this will also catch PROBEW and PROBEWI. However,
107 * these should never get in here because they don't
108 * generate exceptions of the type:
109 * Data TLB miss fault/data page fault
110 * Data memory protection trap
111 */
112 if (bits23_25set(inst) == BITSSET)
113 return VM_WRITE;
114 }
115 return VM_READ; /* Default */
116 }
117 return VM_READ; /* Default */
118}
119
120#undef bit22set
121#undef bits23_25set
122#undef isGraphicsFlushRead
123#undef BITSSET
124
125
126#if 0
127/* This is the treewalk to find a vma which is the highest that has
128 * a start < addr. We're using find_vma_prev instead right now, but
129 * we might want to use this at some point in the future. Probably
130 * not, but I want it committed to CVS so I don't lose it :-)
131 */
132 while (tree != vm_avl_empty) {
133 if (tree->vm_start > addr) {
134 tree = tree->vm_avl_left;
135 } else {
136 prev = tree;
137 if (prev->vm_next == NULL)
138 break;
139 if (prev->vm_next->vm_start > addr)
140 break;
141 tree = tree->vm_avl_right;
142 }
143 }
144#endif
145
146void do_page_fault(struct pt_regs *regs, unsigned long code,
147 unsigned long address)
148{
149 struct vm_area_struct *vma, *prev_vma;
150 struct task_struct *tsk = current;
151 struct mm_struct *mm = tsk->mm;
152 const struct exception_table_entry *fix;
153 unsigned long acc_type;
154
155 if (in_interrupt() || !mm)
156 goto no_context;
157
158 down_read(&mm->mmap_sem);
159 vma = find_vma_prev(mm, address, &prev_vma);
160 if (!vma || address < vma->vm_start)
161 goto check_expansion;
162/*
163 * Ok, we have a good vm_area for this memory access. We still need to
164 * check the access permissions.
165 */
166
167good_area:
168
169 acc_type = parisc_acctyp(code,regs->iir);
170
171 if ((vma->vm_flags & acc_type) != acc_type)
172 goto bad_area;
173
174 /*
175 * If for any reason at all we couldn't handle the fault, make
176 * sure we exit gracefully rather than endlessly redo the
177 * fault.
178 */
179
180 switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) {
181 case 1:
182 ++current->min_flt;
183 break;
184 case 2:
185 ++current->maj_flt;
186 break;
187 case 0:
188 /*
189 * We ran out of memory, or some other thing happened
190 * to us that made us unable to handle the page fault
191 * gracefully.
192 */
193 goto bad_area;
194 default:
195 goto out_of_memory;
196 }
197 up_read(&mm->mmap_sem);
198 return;
199
200check_expansion:
201 vma = prev_vma;
202 if (vma && (expand_stack(vma, address) == 0))
203 goto good_area;
204
205/*
206 * Something tried to access memory that isn't in our memory map..
207 */
208bad_area:
209 up_read(&mm->mmap_sem);
210
211 if (user_mode(regs)) {
212 struct siginfo si;
213
214#ifdef PRINT_USER_FAULTS
215 printk(KERN_DEBUG "\n");
216 printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n",
217 tsk->pid, tsk->comm, code, address);
218 if (vma) {
219 printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n",
220 vma->vm_start, vma->vm_end);
221 }
222 show_regs(regs);
223#endif
224 /* FIXME: actually we need to get the signo and code correct */
225 si.si_signo = SIGSEGV;
226 si.si_errno = 0;
227 si.si_code = SEGV_MAPERR;
228 si.si_addr = (void __user *) address;
229 force_sig_info(SIGSEGV, &si, current);
230 return;
231 }
232
233no_context:
234
235 if (!user_mode(regs)) {
236 fix = search_exception_tables(regs->iaoq[0]);
237
238 if (fix) {
239 struct exception_data *d;
240
241 d = &__get_cpu_var(exception_data);
242 d->fault_ip = regs->iaoq[0];
243 d->fault_space = regs->isr;
244 d->fault_addr = regs->ior;
245
246 regs->iaoq[0] = ((fix->fixup) & ~3);
247
248 /*
249 * NOTE: In some cases the faulting instruction
250 * may be in the delay slot of a branch. We
251 * don't want to take the branch, so we don't
252 * increment iaoq[1], instead we set it to be
253 * iaoq[0]+4, and clear the B bit in the PSW
254 */
255
256 regs->iaoq[1] = regs->iaoq[0] + 4;
257 regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */
258
259 return;
260 }
261 }
262
263 parisc_terminate("Bad Address (null pointer deref?)", regs, code, address);
264
265 out_of_memory:
266 up_read(&mm->mmap_sem);
267 printk(KERN_CRIT "VM: killing process %s\n", current->comm);
268 if (user_mode(regs))
269 do_exit(SIGKILL);
270 goto no_context;
271}
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 @@
1/*
2 * linux/arch/parisc/mm/init.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 * Copyright 1999 SuSE GmbH
6 * changed by Philipp Rumpf
7 * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
8 * Copyright 2004 Randolph Chung (tausq@debian.org)
9 *
10 */
11
12#include <linux/config.h>
13
14#include <linux/module.h>
15#include <linux/mm.h>
16#include <linux/bootmem.h>
17#include <linux/delay.h>
18#include <linux/init.h>
19#include <linux/pci.h> /* for hppa_dma_ops and pcxl_dma_ops */
20#include <linux/initrd.h>
21#include <linux/swap.h>
22#include <linux/unistd.h>
23#include <linux/nodemask.h> /* for node_online_map */
24#include <linux/pagemap.h> /* for release_pages and page_cache_release */
25
26#include <asm/pgalloc.h>
27#include <asm/tlb.h>
28#include <asm/pdc_chassis.h>
29#include <asm/mmzone.h>
30
31DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
32
33extern char _text; /* start of kernel code, defined by linker */
34extern int data_start;
35extern char _end; /* end of BSS, defined by linker */
36extern char __init_begin, __init_end;
37
38#ifdef CONFIG_DISCONTIGMEM
39struct node_map_data node_data[MAX_NUMNODES];
40bootmem_data_t bmem_data[MAX_NUMNODES];
41unsigned char pfnnid_map[PFNNID_MAP_MAX];
42#endif
43
44static struct resource data_resource = {
45 .name = "Kernel data",
46 .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
47};
48
49static struct resource code_resource = {
50 .name = "Kernel code",
51 .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
52};
53
54static struct resource pdcdata_resource = {
55 .name = "PDC data (Page Zero)",
56 .start = 0,
57 .end = 0x9ff,
58 .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
59};
60
61static struct resource sysram_resources[MAX_PHYSMEM_RANGES];
62
63/* The following array is initialized from the firmware specific
64 * information retrieved in kernel/inventory.c.
65 */
66
67physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES];
68int npmem_ranges;
69
70#ifdef __LP64__
71#define MAX_MEM (~0UL)
72#else /* !__LP64__ */
73#define MAX_MEM (3584U*1024U*1024U)
74#endif /* !__LP64__ */
75
76static unsigned long mem_limit = MAX_MEM;
77
78static void __init mem_limit_func(void)
79{
80 char *cp, *end;
81 unsigned long limit;
82 extern char saved_command_line[];
83
84 /* We need this before __setup() functions are called */
85
86 limit = MAX_MEM;
87 for (cp = saved_command_line; *cp; ) {
88 if (memcmp(cp, "mem=", 4) == 0) {
89 cp += 4;
90 limit = memparse(cp, &end);
91 if (end != cp)
92 break;
93 cp = end;
94 } else {
95 while (*cp != ' ' && *cp)
96 ++cp;
97 while (*cp == ' ')
98 ++cp;
99 }
100 }
101
102 if (limit < mem_limit)
103 mem_limit = limit;
104}
105
106#define MAX_GAP (0x40000000UL >> PAGE_SHIFT)
107
108static void __init setup_bootmem(void)
109{
110 unsigned long bootmap_size;
111 unsigned long mem_max;
112 unsigned long bootmap_pages;
113 unsigned long bootmap_start_pfn;
114 unsigned long bootmap_pfn;
115#ifndef CONFIG_DISCONTIGMEM
116 physmem_range_t pmem_holes[MAX_PHYSMEM_RANGES - 1];
117 int npmem_holes;
118#endif
119 int i, sysram_resource_count;
120
121 disable_sr_hashing(); /* Turn off space register hashing */
122
123 /*
124 * Sort the ranges. Since the number of ranges is typically
125 * small, and performance is not an issue here, just do
126 * a simple insertion sort.
127 */
128
129 for (i = 1; i < npmem_ranges; i++) {
130 int j;
131
132 for (j = i; j > 0; j--) {
133 unsigned long tmp;
134
135 if (pmem_ranges[j-1].start_pfn <
136 pmem_ranges[j].start_pfn) {
137
138 break;
139 }
140 tmp = pmem_ranges[j-1].start_pfn;
141 pmem_ranges[j-1].start_pfn = pmem_ranges[j].start_pfn;
142 pmem_ranges[j].start_pfn = tmp;
143 tmp = pmem_ranges[j-1].pages;
144 pmem_ranges[j-1].pages = pmem_ranges[j].pages;
145 pmem_ranges[j].pages = tmp;
146 }
147 }
148
149#ifndef CONFIG_DISCONTIGMEM
150 /*
151 * Throw out ranges that are too far apart (controlled by
152 * MAX_GAP).
153 */
154
155 for (i = 1; i < npmem_ranges; i++) {
156 if (pmem_ranges[i].start_pfn -
157 (pmem_ranges[i-1].start_pfn +
158 pmem_ranges[i-1].pages) > MAX_GAP) {
159 npmem_ranges = i;
160 printk("Large gap in memory detected (%ld pages). "
161 "Consider turning on CONFIG_DISCONTIGMEM\n",
162 pmem_ranges[i].start_pfn -
163 (pmem_ranges[i-1].start_pfn +
164 pmem_ranges[i-1].pages));
165 break;
166 }
167 }
168#endif
169
170 if (npmem_ranges > 1) {
171
172 /* Print the memory ranges */
173
174 printk(KERN_INFO "Memory Ranges:\n");
175
176 for (i = 0; i < npmem_ranges; i++) {
177 unsigned long start;
178 unsigned long size;
179
180 size = (pmem_ranges[i].pages << PAGE_SHIFT);
181 start = (pmem_ranges[i].start_pfn << PAGE_SHIFT);
182 printk(KERN_INFO "%2d) Start 0x%016lx End 0x%016lx Size %6ld MB\n",
183 i,start, start + (size - 1), size >> 20);
184 }
185 }
186
187 sysram_resource_count = npmem_ranges;
188 for (i = 0; i < sysram_resource_count; i++) {
189 struct resource *res = &sysram_resources[i];
190 res->name = "System RAM";
191 res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT;
192 res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1;
193 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
194 request_resource(&iomem_resource, res);
195 }
196
197 /*
198 * For 32 bit kernels we limit the amount of memory we can
199 * support, in order to preserve enough kernel address space
200 * for other purposes. For 64 bit kernels we don't normally
201 * limit the memory, but this mechanism can be used to
202 * artificially limit the amount of memory (and it is written
203 * to work with multiple memory ranges).
204 */
205
206 mem_limit_func(); /* check for "mem=" argument */
207
208 mem_max = 0;
209 num_physpages = 0;
210 for (i = 0; i < npmem_ranges; i++) {
211 unsigned long rsize;
212
213 rsize = pmem_ranges[i].pages << PAGE_SHIFT;
214 if ((mem_max + rsize) > mem_limit) {
215 printk(KERN_WARNING "Memory truncated to %ld MB\n", mem_limit >> 20);
216 if (mem_max == mem_limit)
217 npmem_ranges = i;
218 else {
219 pmem_ranges[i].pages = (mem_limit >> PAGE_SHIFT)
220 - (mem_max >> PAGE_SHIFT);
221 npmem_ranges = i + 1;
222 mem_max = mem_limit;
223 }
224 num_physpages += pmem_ranges[i].pages;
225 break;
226 }
227 num_physpages += pmem_ranges[i].pages;
228 mem_max += rsize;
229 }
230
231 printk(KERN_INFO "Total Memory: %ld MB\n",mem_max >> 20);
232
233#ifndef CONFIG_DISCONTIGMEM
234 /* Merge the ranges, keeping track of the holes */
235
236 {
237 unsigned long end_pfn;
238 unsigned long hole_pages;
239
240 npmem_holes = 0;
241 end_pfn = pmem_ranges[0].start_pfn + pmem_ranges[0].pages;
242 for (i = 1; i < npmem_ranges; i++) {
243
244 hole_pages = pmem_ranges[i].start_pfn - end_pfn;
245 if (hole_pages) {
246 pmem_holes[npmem_holes].start_pfn = end_pfn;
247 pmem_holes[npmem_holes++].pages = hole_pages;
248 end_pfn += hole_pages;
249 }
250 end_pfn += pmem_ranges[i].pages;
251 }
252
253 pmem_ranges[0].pages = end_pfn - pmem_ranges[0].start_pfn;
254 npmem_ranges = 1;
255 }
256#endif
257
258 bootmap_pages = 0;
259 for (i = 0; i < npmem_ranges; i++)
260 bootmap_pages += bootmem_bootmap_pages(pmem_ranges[i].pages);
261
262 bootmap_start_pfn = PAGE_ALIGN(__pa((unsigned long) &_end)) >> PAGE_SHIFT;
263
264#ifdef CONFIG_DISCONTIGMEM
265 for (i = 0; i < MAX_PHYSMEM_RANGES; i++) {
266 memset(NODE_DATA(i), 0, sizeof(pg_data_t));
267 NODE_DATA(i)->bdata = &bmem_data[i];
268 }
269 memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
270
271 for (i = 0; i < npmem_ranges; i++)
272 node_set_online(i);
273#endif
274
275 /*
276 * Initialize and free the full range of memory in each range.
277 * Note that the only writing these routines do are to the bootmap,
278 * and we've made sure to locate the bootmap properly so that they
279 * won't be writing over anything important.
280 */
281
282 bootmap_pfn = bootmap_start_pfn;
283 max_pfn = 0;
284 for (i = 0; i < npmem_ranges; i++) {
285 unsigned long start_pfn;
286 unsigned long npages;
287
288 start_pfn = pmem_ranges[i].start_pfn;
289 npages = pmem_ranges[i].pages;
290
291 bootmap_size = init_bootmem_node(NODE_DATA(i),
292 bootmap_pfn,
293 start_pfn,
294 (start_pfn + npages) );
295 free_bootmem_node(NODE_DATA(i),
296 (start_pfn << PAGE_SHIFT),
297 (npages << PAGE_SHIFT) );
298 bootmap_pfn += (bootmap_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
299 if ((start_pfn + npages) > max_pfn)
300 max_pfn = start_pfn + npages;
301 }
302
303 if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) {
304 printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n");
305 BUG();
306 }
307
308 /* reserve PAGE0 pdc memory, kernel text/data/bss & bootmap */
309
310#define PDC_CONSOLE_IO_IODC_SIZE 32768
311
312 reserve_bootmem_node(NODE_DATA(0), 0UL,
313 (unsigned long)(PAGE0->mem_free + PDC_CONSOLE_IO_IODC_SIZE));
314 reserve_bootmem_node(NODE_DATA(0),__pa((unsigned long)&_text),
315 (unsigned long)(&_end - &_text));
316 reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
317 ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT));
318
319#ifndef CONFIG_DISCONTIGMEM
320
321 /* reserve the holes */
322
323 for (i = 0; i < npmem_holes; i++) {
324 reserve_bootmem_node(NODE_DATA(0),
325 (pmem_holes[i].start_pfn << PAGE_SHIFT),
326 (pmem_holes[i].pages << PAGE_SHIFT));
327 }
328#endif
329
330#ifdef CONFIG_BLK_DEV_INITRD
331 if (initrd_start) {
332 printk(KERN_INFO "initrd: %08lx-%08lx\n", initrd_start, initrd_end);
333 if (__pa(initrd_start) < mem_max) {
334 unsigned long initrd_reserve;
335
336 if (__pa(initrd_end) > mem_max) {
337 initrd_reserve = mem_max - __pa(initrd_start);
338 } else {
339 initrd_reserve = initrd_end - initrd_start;
340 }
341 initrd_below_start_ok = 1;
342 printk(KERN_INFO "initrd: reserving %08lx-%08lx (mem_max %08lx)\n", __pa(initrd_start), __pa(initrd_start) + initrd_reserve, mem_max);
343
344 reserve_bootmem_node(NODE_DATA(0),__pa(initrd_start), initrd_reserve);
345 }
346 }
347#endif
348
349 data_resource.start = virt_to_phys(&data_start);
350 data_resource.end = virt_to_phys(&_end)-1;
351 code_resource.start = virt_to_phys(&_text);
352 code_resource.end = virt_to_phys(&data_start)-1;
353
354 /* We don't know which region the kernel will be in, so try
355 * all of them.
356 */
357 for (i = 0; i < sysram_resource_count; i++) {
358 struct resource *res = &sysram_resources[i];
359 request_resource(res, &code_resource);
360 request_resource(res, &data_resource);
361 }
362 request_resource(&sysram_resources[0], &pdcdata_resource);
363}
364
365void free_initmem(void)
366{
367 /* FIXME: */
368#if 0
369 printk(KERN_INFO "NOT FREEING INITMEM (%dk)\n",
370 (&__init_end - &__init_begin) >> 10);
371 return;
372#else
373 unsigned long addr;
374
375 printk(KERN_INFO "Freeing unused kernel memory: ");
376
377#if 1
378 /* Attempt to catch anyone trying to execute code here
379 * by filling the page with BRK insns.
380 *
381 * If we disable interrupts for all CPUs, then IPI stops working.
382 * Kinda breaks the global cache flushing.
383 */
384 local_irq_disable();
385
386 memset(&__init_begin, 0x00,
387 (unsigned long)&__init_end - (unsigned long)&__init_begin);
388
389 flush_data_cache();
390 asm volatile("sync" : : );
391 flush_icache_range((unsigned long)&__init_begin, (unsigned long)&__init_end);
392 asm volatile("sync" : : );
393
394 local_irq_enable();
395#endif
396
397 addr = (unsigned long)(&__init_begin);
398 for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
399 ClearPageReserved(virt_to_page(addr));
400 set_page_count(virt_to_page(addr), 1);
401 free_page(addr);
402 num_physpages++;
403 totalram_pages++;
404 }
405
406 /* set up a new led state on systems shipped LED State panel */
407 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
408
409 printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
410#endif
411}
412
413/*
414 * Just an arbitrary offset to serve as a "hole" between mapping areas
415 * (between top of physical memory and a potential pcxl dma mapping
416 * area, and below the vmalloc mapping area).
417 *
418 * The current 32K value just means that there will be a 32K "hole"
419 * between mapping areas. That means that any out-of-bounds memory
420 * accesses will hopefully be caught. The vmalloc() routines leaves
421 * a hole of 4kB between each vmalloced area for the same reason.
422 */
423
424 /* Leave room for gateway page expansion */
425#if KERNEL_MAP_START < GATEWAY_PAGE_SIZE
426#error KERNEL_MAP_START is in gateway reserved region
427#endif
428#define MAP_START (KERNEL_MAP_START)
429
430#define VM_MAP_OFFSET (32*1024)
431#define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
432 & ~(VM_MAP_OFFSET-1)))
433
434void *vmalloc_start;
435EXPORT_SYMBOL(vmalloc_start);
436
437#ifdef CONFIG_PA11
438unsigned long pcxl_dma_start;
439#endif
440
441void __init mem_init(void)
442{
443 high_memory = __va((max_pfn << PAGE_SHIFT));
444
445#ifndef CONFIG_DISCONTIGMEM
446 max_mapnr = page_to_pfn(virt_to_page(high_memory - 1)) + 1;
447 totalram_pages += free_all_bootmem();
448#else
449 {
450 int i;
451
452 for (i = 0; i < npmem_ranges; i++)
453 totalram_pages += free_all_bootmem_node(NODE_DATA(i));
454 }
455#endif
456
457 printk(KERN_INFO "Memory: %luk available\n", num_physpages << (PAGE_SHIFT-10));
458
459#ifdef CONFIG_PA11
460 if (hppa_dma_ops == &pcxl_dma_ops) {
461 pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(MAP_START);
462 vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE);
463 } else {
464 pcxl_dma_start = 0;
465 vmalloc_start = SET_MAP_OFFSET(MAP_START);
466 }
467#else
468 vmalloc_start = SET_MAP_OFFSET(MAP_START);
469#endif
470
471}
472
473int do_check_pgt_cache(int low, int high)
474{
475 return 0;
476}
477
478unsigned long *empty_zero_page;
479
480void show_mem(void)
481{
482 int i,free = 0,total = 0,reserved = 0;
483 int shared = 0, cached = 0;
484
485 printk(KERN_INFO "Mem-info:\n");
486 show_free_areas();
487 printk(KERN_INFO "Free swap: %6ldkB\n",
488 nr_swap_pages<<(PAGE_SHIFT-10));
489#ifndef CONFIG_DISCONTIGMEM
490 i = max_mapnr;
491 while (i-- > 0) {
492 total++;
493 if (PageReserved(mem_map+i))
494 reserved++;
495 else if (PageSwapCache(mem_map+i))
496 cached++;
497 else if (!page_count(&mem_map[i]))
498 free++;
499 else
500 shared += page_count(&mem_map[i]) - 1;
501 }
502#else
503 for (i = 0; i < npmem_ranges; i++) {
504 int j;
505
506 for (j = node_start_pfn(i); j < node_end_pfn(i); j++) {
507 struct page *p;
508
509 p = node_mem_map(i) + j - node_start_pfn(i);
510
511 total++;
512 if (PageReserved(p))
513 reserved++;
514 else if (PageSwapCache(p))
515 cached++;
516 else if (!page_count(p))
517 free++;
518 else
519 shared += page_count(p) - 1;
520 }
521 }
522#endif
523 printk(KERN_INFO "%d pages of RAM\n", total);
524 printk(KERN_INFO "%d reserved pages\n", reserved);
525 printk(KERN_INFO "%d pages shared\n", shared);
526 printk(KERN_INFO "%d pages swap cached\n", cached);
527
528
529#ifdef CONFIG_DISCONTIGMEM
530 {
531 struct zonelist *zl;
532 int i, j, k;
533
534 for (i = 0; i < npmem_ranges; i++) {
535 for (j = 0; j < MAX_NR_ZONES; j++) {
536 zl = NODE_DATA(i)->node_zonelists + j;
537
538 printk("Zone list for zone %d on node %d: ", j, i);
539 for (k = 0; zl->zones[k] != NULL; k++)
540 printk("[%d/%s] ", zl->zones[k]->zone_pgdat->node_id, zl->zones[k]->name);
541 printk("\n");
542 }
543 }
544 }
545#endif
546}
547
548
549static void __init map_pages(unsigned long start_vaddr, unsigned long start_paddr, unsigned long size, pgprot_t pgprot)
550{
551 pgd_t *pg_dir;
552 pmd_t *pmd;
553 pte_t *pg_table;
554 unsigned long end_paddr;
555 unsigned long start_pmd;
556 unsigned long start_pte;
557 unsigned long tmp1;
558 unsigned long tmp2;
559 unsigned long address;
560 unsigned long ro_start;
561 unsigned long ro_end;
562 unsigned long fv_addr;
563 unsigned long gw_addr;
564 extern const unsigned long fault_vector_20;
565 extern void * const linux_gateway_page;
566
567 ro_start = __pa((unsigned long)&_text);
568 ro_end = __pa((unsigned long)&data_start);
569 fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
570 gw_addr = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK;
571
572 end_paddr = start_paddr + size;
573
574 pg_dir = pgd_offset_k(start_vaddr);
575
576#if PTRS_PER_PMD == 1
577 start_pmd = 0;
578#else
579 start_pmd = ((start_vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
580#endif
581 start_pte = ((start_vaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
582
583 address = start_paddr;
584 while (address < end_paddr) {
585#if PTRS_PER_PMD == 1
586 pmd = (pmd_t *)__pa(pg_dir);
587#else
588 pmd = (pmd_t *)pgd_address(*pg_dir);
589
590 /*
591 * pmd is physical at this point
592 */
593
594 if (!pmd) {
595 pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE << PMD_ORDER);
596 pmd = (pmd_t *) __pa(pmd);
597 }
598
599 pgd_populate(NULL, pg_dir, __va(pmd));
600#endif
601 pg_dir++;
602
603 /* now change pmd to kernel virtual addresses */
604
605 pmd = (pmd_t *)__va(pmd) + start_pmd;
606 for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++,pmd++) {
607
608 /*
609 * pg_table is physical at this point
610 */
611
612 pg_table = (pte_t *)pmd_address(*pmd);
613 if (!pg_table) {
614 pg_table = (pte_t *)
615 alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE);
616 pg_table = (pte_t *) __pa(pg_table);
617 }
618
619 pmd_populate_kernel(NULL, pmd, __va(pg_table));
620
621 /* now change pg_table to kernel virtual addresses */
622
623 pg_table = (pte_t *) __va(pg_table) + start_pte;
624 for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
625 pte_t pte;
626
627 /*
628 * Map the fault vector writable so we can
629 * write the HPMC checksum.
630 */
631 if (address >= ro_start && address < ro_end
632 && address != fv_addr
633 && address != gw_addr)
634 pte = __mk_pte(address, PAGE_KERNEL_RO);
635 else
636 pte = __mk_pte(address, pgprot);
637
638 if (address >= end_paddr)
639 pte_val(pte) = 0;
640
641 set_pte(pg_table, pte);
642
643 address += PAGE_SIZE;
644 }
645 start_pte = 0;
646
647 if (address >= end_paddr)
648 break;
649 }
650 start_pmd = 0;
651 }
652}
653
654/*
655 * pagetable_init() sets up the page tables
656 *
657 * Note that gateway_init() places the Linux gateway page at page 0.
658 * Since gateway pages cannot be dereferenced this has the desirable
659 * side effect of trapping those pesky NULL-reference errors in the
660 * kernel.
661 */
662static void __init pagetable_init(void)
663{
664 int range;
665
666 /* Map each physical memory range to its kernel vaddr */
667
668 for (range = 0; range < npmem_ranges; range++) {
669 unsigned long start_paddr;
670 unsigned long end_paddr;
671 unsigned long size;
672
673 start_paddr = pmem_ranges[range].start_pfn << PAGE_SHIFT;
674 end_paddr = start_paddr + (pmem_ranges[range].pages << PAGE_SHIFT);
675 size = pmem_ranges[range].pages << PAGE_SHIFT;
676
677 map_pages((unsigned long)__va(start_paddr), start_paddr,
678 size, PAGE_KERNEL);
679 }
680
681#ifdef CONFIG_BLK_DEV_INITRD
682 if (initrd_end && initrd_end > mem_limit) {
683 printk("initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end);
684 map_pages(initrd_start, __pa(initrd_start),
685 initrd_end - initrd_start, PAGE_KERNEL);
686 }
687#endif
688
689 empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
690 memset(empty_zero_page, 0, PAGE_SIZE);
691}
692
693static void __init gateway_init(void)
694{
695 unsigned long linux_gateway_page_addr;
696 /* FIXME: This is 'const' in order to trick the compiler
697 into not treating it as DP-relative data. */
698 extern void * const linux_gateway_page;
699
700 linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK;
701
702 /*
703 * Setup Linux Gateway page.
704 *
705 * The Linux gateway page will reside in kernel space (on virtual
706 * page 0), so it doesn't need to be aliased into user space.
707 */
708
709 map_pages(linux_gateway_page_addr, __pa(&linux_gateway_page),
710 PAGE_SIZE, PAGE_GATEWAY);
711}
712
713#ifdef CONFIG_HPUX
714void
715map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm)
716{
717 pgd_t *pg_dir;
718 pmd_t *pmd;
719 pte_t *pg_table;
720 unsigned long start_pmd;
721 unsigned long start_pte;
722 unsigned long address;
723 unsigned long hpux_gw_page_addr;
724 /* FIXME: This is 'const' in order to trick the compiler
725 into not treating it as DP-relative data. */
726 extern void * const hpux_gateway_page;
727
728 hpux_gw_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK;
729
730 /*
731 * Setup HP-UX Gateway page.
732 *
733 * The HP-UX gateway page resides in the user address space,
734 * so it needs to be aliased into each process.
735 */
736
737 pg_dir = pgd_offset(mm,hpux_gw_page_addr);
738
739#if PTRS_PER_PMD == 1
740 start_pmd = 0;
741#else
742 start_pmd = ((hpux_gw_page_addr >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
743#endif
744 start_pte = ((hpux_gw_page_addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
745
746 address = __pa(&hpux_gateway_page);
747#if PTRS_PER_PMD == 1
748 pmd = (pmd_t *)__pa(pg_dir);
749#else
750 pmd = (pmd_t *) pgd_address(*pg_dir);
751
752 /*
753 * pmd is physical at this point
754 */
755
756 if (!pmd) {
757 pmd = (pmd_t *) get_zeroed_page(GFP_KERNEL);
758 pmd = (pmd_t *) __pa(pmd);
759 }
760
761 __pgd_val_set(*pg_dir, PxD_FLAG_PRESENT | PxD_FLAG_VALID | (unsigned long) pmd);
762#endif
763 /* now change pmd to kernel virtual addresses */
764
765 pmd = (pmd_t *)__va(pmd) + start_pmd;
766
767 /*
768 * pg_table is physical at this point
769 */
770
771 pg_table = (pte_t *) pmd_address(*pmd);
772 if (!pg_table)
773 pg_table = (pte_t *) __pa(get_zeroed_page(GFP_KERNEL));
774
775 __pmd_val_set(*pmd, PxD_FLAG_PRESENT | PxD_FLAG_VALID | (unsigned long) pg_table);
776
777 /* now change pg_table to kernel virtual addresses */
778
779 pg_table = (pte_t *) __va(pg_table) + start_pte;
780 set_pte(pg_table, __mk_pte(address, PAGE_GATEWAY));
781}
782EXPORT_SYMBOL(map_hpux_gateway_page);
783#endif
784
785extern void flush_tlb_all_local(void);
786
787void __init paging_init(void)
788{
789 int i;
790
791 setup_bootmem();
792 pagetable_init();
793 gateway_init();
794 flush_cache_all_local(); /* start with known state */
795 flush_tlb_all_local();
796
797 for (i = 0; i < npmem_ranges; i++) {
798 unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0 };
799
800 /* We have an IOMMU, so all memory can go into a single
801 ZONE_DMA zone. */
802 zones_size[ZONE_DMA] = pmem_ranges[i].pages;
803
804#ifdef CONFIG_DISCONTIGMEM
805 /* Need to initialize the pfnnid_map before we can initialize
806 the zone */
807 {
808 int j;
809 for (j = (pmem_ranges[i].start_pfn >> PFNNID_SHIFT);
810 j <= ((pmem_ranges[i].start_pfn + pmem_ranges[i].pages) >> PFNNID_SHIFT);
811 j++) {
812 pfnnid_map[j] = i;
813 }
814 }
815#endif
816
817 free_area_init_node(i, NODE_DATA(i), zones_size,
818 pmem_ranges[i].start_pfn, NULL);
819 }
820}
821
822#ifdef CONFIG_PA20
823
824/*
825 * Currently, all PA20 chips have 18 bit protection id's, which is the
826 * limiting factor (space ids are 32 bits).
827 */
828
829#define NR_SPACE_IDS 262144
830
831#else
832
833/*
834 * Currently we have a one-to-one relationship between space id's and
835 * protection id's. Older parisc chips (PCXS, PCXT, PCXL, PCXL2) only
836 * support 15 bit protection id's, so that is the limiting factor.
837 * PCXT' has 18 bit protection id's, but only 16 bit spaceids, so it's
838 * probably not worth the effort for a special case here.
839 */
840
841#define NR_SPACE_IDS 32768
842
843#endif /* !CONFIG_PA20 */
844
845#define RECYCLE_THRESHOLD (NR_SPACE_IDS / 2)
846#define SID_ARRAY_SIZE (NR_SPACE_IDS / (8 * sizeof(long)))
847
848static unsigned long space_id[SID_ARRAY_SIZE] = { 1 }; /* disallow space 0 */
849static unsigned long dirty_space_id[SID_ARRAY_SIZE];
850static unsigned long space_id_index;
851static unsigned long free_space_ids = NR_SPACE_IDS - 1;
852static unsigned long dirty_space_ids = 0;
853
854static DEFINE_SPINLOCK(sid_lock);
855
856unsigned long alloc_sid(void)
857{
858 unsigned long index;
859
860 spin_lock(&sid_lock);
861
862 if (free_space_ids == 0) {
863 if (dirty_space_ids != 0) {
864 spin_unlock(&sid_lock);
865 flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */
866 spin_lock(&sid_lock);
867 }
868 if (free_space_ids == 0)
869 BUG();
870 }
871
872 free_space_ids--;
873
874 index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index);
875 space_id[index >> SHIFT_PER_LONG] |= (1L << (index & (BITS_PER_LONG - 1)));
876 space_id_index = index;
877
878 spin_unlock(&sid_lock);
879
880 return index << SPACEID_SHIFT;
881}
882
883void free_sid(unsigned long spaceid)
884{
885 unsigned long index = spaceid >> SPACEID_SHIFT;
886 unsigned long *dirty_space_offset;
887
888 dirty_space_offset = dirty_space_id + (index >> SHIFT_PER_LONG);
889 index &= (BITS_PER_LONG - 1);
890
891 spin_lock(&sid_lock);
892
893 if (*dirty_space_offset & (1L << index))
894 BUG(); /* attempt to free space id twice */
895
896 *dirty_space_offset |= (1L << index);
897 dirty_space_ids++;
898
899 spin_unlock(&sid_lock);
900}
901
902
903#ifdef CONFIG_SMP
904static void get_dirty_sids(unsigned long *ndirtyptr,unsigned long *dirty_array)
905{
906 int i;
907
908 /* NOTE: sid_lock must be held upon entry */
909
910 *ndirtyptr = dirty_space_ids;
911 if (dirty_space_ids != 0) {
912 for (i = 0; i < SID_ARRAY_SIZE; i++) {
913 dirty_array[i] = dirty_space_id[i];
914 dirty_space_id[i] = 0;
915 }
916 dirty_space_ids = 0;
917 }
918
919 return;
920}
921
922static void recycle_sids(unsigned long ndirty,unsigned long *dirty_array)
923{
924 int i;
925
926 /* NOTE: sid_lock must be held upon entry */
927
928 if (ndirty != 0) {
929 for (i = 0; i < SID_ARRAY_SIZE; i++) {
930 space_id[i] ^= dirty_array[i];
931 }
932
933 free_space_ids += ndirty;
934 space_id_index = 0;
935 }
936}
937
938#else /* CONFIG_SMP */
939
940static void recycle_sids(void)
941{
942 int i;
943
944 /* NOTE: sid_lock must be held upon entry */
945
946 if (dirty_space_ids != 0) {
947 for (i = 0; i < SID_ARRAY_SIZE; i++) {
948 space_id[i] ^= dirty_space_id[i];
949 dirty_space_id[i] = 0;
950 }
951
952 free_space_ids += dirty_space_ids;
953 dirty_space_ids = 0;
954 space_id_index = 0;
955 }
956}
957#endif
958
959/*
960 * flush_tlb_all() calls recycle_sids(), since whenever the entire tlb is
961 * purged, we can safely reuse the space ids that were released but
962 * not flushed from the tlb.
963 */
964
965#ifdef CONFIG_SMP
966
967static unsigned long recycle_ndirty;
968static unsigned long recycle_dirty_array[SID_ARRAY_SIZE];
969static unsigned int recycle_inuse = 0;
970
971void flush_tlb_all(void)
972{
973 int do_recycle;
974
975 do_recycle = 0;
976 spin_lock(&sid_lock);
977 if (dirty_space_ids > RECYCLE_THRESHOLD) {
978 if (recycle_inuse) {
979 BUG(); /* FIXME: Use a semaphore/wait queue here */
980 }
981 get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
982 recycle_inuse++;
983 do_recycle++;
984 }
985 spin_unlock(&sid_lock);
986 on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
987 if (do_recycle) {
988 spin_lock(&sid_lock);
989 recycle_sids(recycle_ndirty,recycle_dirty_array);
990 recycle_inuse = 0;
991 spin_unlock(&sid_lock);
992 }
993}
994#else
995void flush_tlb_all(void)
996{
997 spin_lock(&sid_lock);
998 flush_tlb_all_local();
999 recycle_sids();
1000 spin_unlock(&sid_lock);
1001}
1002#endif
1003
1004#ifdef CONFIG_BLK_DEV_INITRD
1005void free_initrd_mem(unsigned long start, unsigned long end)
1006{
1007#if 0
1008 if (start < end)
1009 printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
1010 for (; start < end; start += PAGE_SIZE) {
1011 ClearPageReserved(virt_to_page(start));
1012 set_page_count(virt_to_page(start), 1);
1013 free_page(start);
1014 num_physpages++;
1015 totalram_pages++;
1016 }
1017#endif
1018}
1019#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 @@
1/*
2 * arch/parisc/mm/ioremap.c
3 *
4 * Re-map IO memory to kernel address space so that we can access it.
5 * This is needed for high PCI addresses that aren't mapped in the
6 * 640k-1MB IO memory area on PC's
7 *
8 * (C) Copyright 1995 1996 Linus Torvalds
9 * (C) Copyright 2001 Helge Deller <deller@gmx.de>
10 */
11
12#include <linux/vmalloc.h>
13#include <linux/errno.h>
14#include <linux/module.h>
15#include <asm/io.h>
16#include <asm/pgalloc.h>
17
18static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
19 unsigned long phys_addr, unsigned long flags)
20{
21 unsigned long end;
22
23 address &= ~PMD_MASK;
24 end = address + size;
25 if (end > PMD_SIZE)
26 end = PMD_SIZE;
27 if (address >= end)
28 BUG();
29 do {
30 if (!pte_none(*pte)) {
31 printk(KERN_ERR "remap_area_pte: page already exists\n");
32 BUG();
33 }
34 set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW |
35 _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
36 address += PAGE_SIZE;
37 phys_addr += PAGE_SIZE;
38 pte++;
39 } while (address && (address < end));
40}
41
42static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
43 unsigned long phys_addr, unsigned long flags)
44{
45 unsigned long end;
46
47 address &= ~PGDIR_MASK;
48 end = address + size;
49 if (end > PGDIR_SIZE)
50 end = PGDIR_SIZE;
51 phys_addr -= address;
52 if (address >= end)
53 BUG();
54 do {
55 pte_t * pte = pte_alloc_kernel(NULL, pmd, address);
56 if (!pte)
57 return -ENOMEM;
58 remap_area_pte(pte, address, end - address, address + phys_addr, flags);
59 address = (address + PMD_SIZE) & PMD_MASK;
60 pmd++;
61 } while (address && (address < end));
62 return 0;
63}
64
65#if (USE_HPPA_IOREMAP)
66static int remap_area_pages(unsigned long address, unsigned long phys_addr,
67 unsigned long size, unsigned long flags)
68{
69 int error;
70 pgd_t * dir;
71 unsigned long end = address + size;
72
73 phys_addr -= address;
74 dir = pgd_offset(&init_mm, address);
75 flush_cache_all();
76 if (address >= end)
77 BUG();
78 spin_lock(&init_mm.page_table_lock);
79 do {
80 pmd_t *pmd;
81 pmd = pmd_alloc(dir, address);
82 error = -ENOMEM;
83 if (!pmd)
84 break;
85 if (remap_area_pmd(pmd, address, end - address,
86 phys_addr + address, flags))
87 break;
88 error = 0;
89 address = (address + PGDIR_SIZE) & PGDIR_MASK;
90 dir++;
91 } while (address && (address < end));
92 spin_unlock(&init_mm.page_table_lock);
93 flush_tlb_all();
94 return error;
95}
96#endif /* USE_HPPA_IOREMAP */
97
98#ifdef CONFIG_DEBUG_IOREMAP
99static unsigned long last = 0;
100
101void gsc_bad_addr(unsigned long addr)
102{
103 if (time_after(jiffies, last + HZ*10)) {
104 printk("gsc_foo() called with bad address 0x%lx\n", addr);
105 dump_stack();
106 last = jiffies;
107 }
108}
109EXPORT_SYMBOL(gsc_bad_addr);
110
111void __raw_bad_addr(const volatile void __iomem *addr)
112{
113 if (time_after(jiffies, last + HZ*10)) {
114 printk("__raw_foo() called with bad address 0x%p\n", addr);
115 dump_stack();
116 last = jiffies;
117 }
118}
119EXPORT_SYMBOL(__raw_bad_addr);
120#endif
121
122/*
123 * Generic mapping function (not visible outside):
124 */
125
126/*
127 * Remap an arbitrary physical address space into the kernel virtual
128 * address space. Needed when the kernel wants to access high addresses
129 * directly.
130 *
131 * NOTE! We need to allow non-page-aligned mappings too: we will obviously
132 * have to convert them into an offset in a page-aligned mapping, but the
133 * caller shouldn't need to know that small detail.
134 */
135void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
136{
137#if !(USE_HPPA_IOREMAP)
138
139 unsigned long end = phys_addr + size - 1;
140 /* Support EISA addresses */
141 if ((phys_addr >= 0x00080000 && end < 0x000fffff)
142 || (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
143 phys_addr |= 0xfc000000;
144 }
145
146#ifdef CONFIG_DEBUG_IOREMAP
147 return (void __iomem *)(phys_addr - (0x1UL << NYBBLE_SHIFT));
148#else
149 return (void __iomem *)phys_addr;
150#endif
151
152#else
153 void * addr;
154 struct vm_struct * area;
155 unsigned long offset, last_addr;
156
157 /* Don't allow wraparound or zero size */
158 last_addr = phys_addr + size - 1;
159 if (!size || last_addr < phys_addr)
160 return NULL;
161
162 /*
163 * Don't allow anybody to remap normal RAM that we're using..
164 */
165 if (phys_addr < virt_to_phys(high_memory)) {
166 char *t_addr, *t_end;
167 struct page *page;
168
169 t_addr = __va(phys_addr);
170 t_end = t_addr + (size - 1);
171
172 for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
173 if(!PageReserved(page))
174 return NULL;
175 }
176
177 /*
178 * Mappings have to be page-aligned
179 */
180 offset = phys_addr & ~PAGE_MASK;
181 phys_addr &= PAGE_MASK;
182 size = PAGE_ALIGN(last_addr) - phys_addr;
183
184 /*
185 * Ok, go for it..
186 */
187 area = get_vm_area(size, VM_IOREMAP);
188 if (!area)
189 return NULL;
190 addr = area->addr;
191 if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
192 vfree(addr);
193 return NULL;
194 }
195 return (void __iomem *) (offset + (char *)addr);
196#endif
197}
198
199void iounmap(void __iomem *addr)
200{
201#if !(USE_HPPA_IOREMAP)
202 return;
203#else
204 if (addr > high_memory)
205 return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
206#endif
207}
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 @@
1/*
2 * kmap/page table map and unmap support routines
3 *
4 * Copyright 1999,2000 Hewlett-Packard Company
5 * Copyright 2000 John Marvin <jsm at hp.com>
6 * Copyright 2000 Grant Grundler <grundler at parisc-linux.org>
7 * Copyright 2000 Philipp Rumpf <prumpf@tux.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24/*
25** Stolen mostly from arch/parisc/kernel/pci-dma.c
26*/
27
28#include <linux/types.h>
29#include <linux/mm.h>
30#include <linux/string.h>
31#include <linux/pci.h>
32
33#include <linux/slab.h>
34#include <linux/vmalloc.h>
35
36#include <asm/uaccess.h>
37#include <asm/pgalloc.h>
38
39#include <asm/io.h>
40#include <asm/page.h> /* get_order */
41
42#undef flush_cache_all
43#define flush_cache_all flush_all_caches
44
45typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg);
46
47#if 0
48/* XXX This routine could be used with iterate_page() to replace
49 * unmap_uncached_page() and save a little code space but I didn't
50 * do that since I'm not certain whether this is the right path. -PB
51 */
52static void unmap_cached_pte(pte_t * pte, unsigned long addr, unsigned long arg)
53{
54 pte_t page = *pte;
55 pte_clear(&init_mm, addr, pte);
56 if (!pte_none(page)) {
57 if (pte_present(page)) {
58 unsigned long map_nr = pte_pagenr(page);
59 if (map_nr < max_mapnr)
60 __free_page(mem_map + map_nr);
61 } else {
62 printk(KERN_CRIT
63 "Whee.. Swapped out page in kernel page table\n");
64 }
65 }
66}
67#endif
68
69/* These two routines should probably check a few things... */
70static void set_uncached(pte_t * pte, unsigned long arg)
71{
72 pte_val(*pte) |= _PAGE_NO_CACHE;
73}
74
75static void set_cached(pte_t * pte, unsigned long arg)
76{
77 pte_val(*pte) &= ~_PAGE_NO_CACHE;
78}
79
80static inline void iterate_pte(pmd_t * pmd, unsigned long address,
81 unsigned long size, pte_iterator_t op,
82 unsigned long arg)
83{
84 pte_t *pte;
85 unsigned long end;
86
87 if (pmd_none(*pmd))
88 return;
89 if (pmd_bad(*pmd)) {
90 pmd_ERROR(*pmd);
91 pmd_clear(pmd);
92 return;
93 }
94 pte = pte_offset(pmd, address);
95 address &= ~PMD_MASK;
96 end = address + size;
97 if (end > PMD_SIZE)
98 end = PMD_SIZE;
99 do {
100 op(pte, arg);
101 address += PAGE_SIZE;
102 pte++;
103 } while (address < end);
104}
105
106static inline void iterate_pmd(pgd_t * dir, unsigned long address,
107 unsigned long size, pte_iterator_t op,
108 unsigned long arg)
109{
110 pmd_t *pmd;
111 unsigned long end;
112
113 if (pgd_none(*dir))
114 return;
115 if (pgd_bad(*dir)) {
116 pgd_ERROR(*dir);
117 pgd_clear(dir);
118 return;
119 }
120 pmd = pmd_offset(dir, address);
121 address &= ~PGDIR_MASK;
122 end = address + size;
123 if (end > PGDIR_SIZE)
124 end = PGDIR_SIZE;
125 do {
126 iterate_pte(pmd, address, end - address, op, arg);
127 address = (address + PMD_SIZE) & PMD_MASK;
128 pmd++;
129 } while (address < end);
130}
131
132static void iterate_pages(unsigned long address, unsigned long size,
133 pte_iterator_t op, unsigned long arg)
134{
135 pgd_t *dir;
136 unsigned long end = address + size;
137
138 dir = pgd_offset_k(address);
139 flush_cache_all();
140 do {
141 iterate_pmd(dir, address, end - address, op, arg);
142 address = (address + PGDIR_SIZE) & PGDIR_MASK;
143 dir++;
144 } while (address && (address < end));
145 flush_tlb_all();
146}
147
148void
149kernel_set_cachemode(unsigned long vaddr, unsigned long size, int what)
150{
151 switch (what) {
152 case IOMAP_FULL_CACHING:
153 iterate_pages(vaddr, size, set_cached, 0);
154 flush_tlb_range(NULL, vaddr, size);
155 break;
156 case IOMAP_NOCACHE_SER:
157 iterate_pages(vaddr, size, set_uncached, 0);
158 flush_tlb_range(NULL, vaddr, size);
159 break;
160 default:
161 printk(KERN_CRIT
162 "kernel_set_cachemode mode %d not understood\n",
163 what);
164 break;
165 }
166}
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 @@
1#!/bin/sh
2##
3# Hack to have an nm which removes the local symbols. We also rely
4# on this nm being hidden out of the ordinarily executable path
5##
6${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 @@
1
2menu "Profiling support"
3 depends on EXPERIMENTAL
4
5config PROFILING
6 bool "Profiling support (EXPERIMENTAL)"
7 help
8 Say Y here to enable the extended profiling support mechanisms used
9 by profilers such as OProfile.
10
11
12config OPROFILE
13 tristate "OProfile system profiling (EXPERIMENTAL)"
14 depends on PROFILING
15 help
16 OProfile is a profiling system capable of profiling the
17 whole system, include the kernel, kernel modules, libraries,
18 and applications.
19
20 If unsure, say N.
21
22endmenu
23
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 @@
1obj-$(CONFIG_OPROFILE) += oprofile.o
2
3DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
4 oprof.o cpu_buffer.o buffer_sync.o \
5 event_buffer.o oprofile_files.o \
6 oprofilefs.o oprofile_stats.o \
7 timer_int.o )
8
9oprofile-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 @@
1/**
2 * @file init.c
3 *
4 * @remark Copyright 2002 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author John Levon <levon@movementarian.org>
8 */
9
10#include <linux/errno.h>
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/oprofile.h>
14
15int __init oprofile_arch_init(struct oprofile_operations * ops)
16{
17 return -ENODEV;
18}
19
20
21void oprofile_arch_exit()
22{
23}